This project sets up everything you need to run your application reliably in a production environment. It includes ready-made Kubernetes files, security settings, automation scripts, and monitoring tools to help you deploy, scale, and manage your app with confidence. Whether you’re testing locally on Minikube or rolling out to a real cluster, this setup gives you a solid starting point for modern DevOps and smooth operations.
Note: This project was carried out using a minikube cluster for testing purposes, minikube should never be used in a production environment.
.
├── README.md
├── RUNBOOK.md
├── backend
│ ├── Dockerfile
│ ├── main.py
│ ├── requirements.txt
│ └── test_main.py
├── k8s
│ ├── configmap.yml
│ ├── deployment.yml
│ ├── hpa.yml
│ ├── ingress.yml
│ ├── networkpolicy.yml
│ ├── secret.yml
│ ├── service.yml
│ └── serviceaccount.yml
├── monitoring
│ ├── alerts.yml
│ ├── grafana-dashboard.json
│ └── prometheus.yml
├── scripts
│ ├── deploy.sh
│ ├── health-check.sh
│ └── rollback.sh
├── security
│ ├── pod-security.yml
│ └── rbac.yml
└── terraform
├── main.tf
├── output.tf
└── variable.tf
- Docker
- Kubernetes Cluster
- GitHub Actions
- Terraform
- Bash Scripting
This project involves containerizing a FastAPI backend service that is scalable and production ready. The application is configured to expose prometheus metrics for observability and monitoring. Built, tested and deployed using GitHub Actions.
Made use of Multi stage build in my docker file that reduced my application size to 260MB. I prioritised the use of slim base images that are lightweight and run faster builds. Configured docker to run the container as appuser and not root, which is a best practice for security.
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# Final stage
FROM python:3.12-slim
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
WORKDIR /app
COPY --from=builder /usr/local /usr/local
COPY --from=builder /app /app
USER appuser
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
-
- I configured my workflow to run a pytest for testing API endpoints "GET
/items" "GET/health" and "POST/items" and it automatically fails the workflow if any test is not successful. - Integrated docker trivy scanner to scan my dockerfile and docker images. The workflow fails if vulnerabilities are detected in my dockerfile and docker images. This will minimize production issues and improve security.
- My integration pipeline is triggered by a pull request to the main branch, in this case all application test are performed before merging into "main" branch for deployment.
- I configured my workflow to run a pytest for testing API endpoints "GET
-
- After my image has been scanned successfully with no vulnerabilities, my deployment workflow is set up to build and tag my docker images.
- I configured a versioning system to tag my images using the traditional versioning pattern i.e "v1.0.1" which helps to track various images properly for best practice.
- Once the image has been tagged, my workflow pushes my image to dockerhub remote repository.
- Because I decided to use a Minikube cluster, my workflow will SSH into my minikube server and run my deployment script to deploy the backend service in my kubernetes cluster.
-
configmap.yml: Stores general configuration settings for my application(like environment name or feature flags) so I don’t have to hard-code them. -
deployment.yml: Defines how my app should run on Kubernetes, how many copies (pods) to run, which Docker image to use, and basic health checks. -
hpa.yml: The Horizontal Pod Autoscaler automatically adds or removes pods based on CPU or memory usage, so my app can handle more traffic when needed. -
ingress.yml: Manages external access to my app (like routing traffic from your domain name to the right service) and handles things like SSL and CORS rules. Ingress also works like a load balancer for my application. -
networkpolicy.yml: Controls what network traffic is allowed to reach my pods, adding an extra layer of security. -
secret.yml: Stores sensitive data e.g Docker Hub username and password that my application needs but shouldn’t be hard-coded or visible in plain text. -
service.yml: Creates a stable internal IP and DNS name for backend service so other services or users can reach it reliably inside the cluster. -
serviceaccount.yml: Gives my backend app permissions to interact with the Kubernetes API securely, using only the access it needs. -
pod-security.yml: Defines rules that control what my pods are allowed to do (for example, restricting running as root), helping keep your cluster safer. -
rbac.yml: Sets up Role-Based Access Control (RBAC) to manage who (or what) can access specific Kubernetes resources, ensuring only the right accounts have permission.
I implemented the use of prometheus and Grafana to monitor and visualize metrics from my backend service. Although the full configuration is not here just to maintain project demands. If you want to get a view of the whole configuration click here.
A quick look at what each monitoring file does:
-
alerts.yml: Defines alert rules for Prometheus so you get notified when something goes wrong or crosses a threshold (like high CPU or memory usage). -
grafana-dashboard.json: A pre-made dashboard configuration for Grafana to visualize my backend service key metrics in a clear, beautiful way. This was downloaded from Grafana Labs. -
prometheus.yml: The main configuration for Prometheus that tells it what to monitor, where to scrape metrics from, and how often to check. For this project, it scrapes only my backend service for metrics.
I authored wrapper scripts for automating kubernetes deployment for all my kubernetes manifests ehich makes it easier and faster to deploy. Also wrote rollback scripts to handle failed deployments and reduce downtime. Implemented a production based design to handle downtime, deployment and health check.
A quick look at what each script does:
-
deploy.sh: Runs all the steps needed to deploy my backend service app and Kubernetes resources to the cluster in one go. -
health-check.sh: Checks if my app and pods are healthy and running as expected, so I know everything is working fine. -
rollback.sh: If something goes wrong, this script lets you roll back your deployment to the previous stable version easily. By running./rollback.sh <deployment name>, my app rolls back to previous working version.
Provisioned my infrastructure using IAC for best practice, versioning, and reusability. Makes automated provisioning secure and fast. Because I made use of a Minikube cluster, I provisioned my EC2 instance, security group(firewall), SSH Key and Elastic IP address.
Here’s what each Terraform file does:
-
main.tf: This is the main configuration file that defines the cloud infrastructure I want to create (like servers, networks, and storage). -
output.tf: Specifies what useful information Terraform should show me after deploying (Private and Public IP address). -
variable.tf: Defines the input variables I confugured when I run Terraform (like region, firewall or environment name).
- Fork the repository
- Create a feature branch
- Submit a pull request