A production-grade, end-to-end DevOps project built from scratch using industry-standard tools. Real app. Real pipeline. Real infrastructure. 100% Free.
This project demonstrates a complete DevOps lifecycle — from writing application code to deploying it on Kubernetes with GitOps and monitoring it with Prometheus, Grafana, and Alertmanager.
The application itself is an IPL Team Voter — users can vote for their favourite IPL team in real time, with a live leaderboard and persistent vote storage.
Developer → Git Push → GitHub
↓
GitHub Actions CI
├── Lint (flake8)
├── Tests (pytest)
├── Security Scan (Trivy)
├── Docker Build + Push
├── Helm Lint + Diff
└── Update values.yaml (image tag)
↓
ArgoCD (GitOps)
watches GitHub repo
↓
Deploy to Kubernetes (Minikube)
via Helm Chart
↓
Prometheus scrapes /metrics
↓
Grafana Dashboards (CPU, Memory,
Request Rate, Error Rate)
↓
Alertmanager → Email alerts
(HighCPU, HighMemory, PodDown)
| Category | Tool | Purpose |
|---|---|---|
| Language | Python 3.12 + Flask | REST API + UI |
| Database | SQLite | Vote persistence |
| Version Control | Git + GitHub | Source control |
| Containerization | Docker | Multi-stage image build |
| Registry | Docker Hub | Container image storage |
| CI | GitHub Actions | Auto build + push on every commit |
| CD | ArgoCD | GitOps, auto-deploy on git push |
| Packaging | Helm v3.19 | Kubernetes app packaging |
| Orchestration | Kubernetes (Minikube v1.37) | Container orchestration |
| Monitoring | Prometheus + Grafana | Metrics + Dashboards |
| Alerting | Alertmanager | Email alerts on CPU/Memory/Pod health |
- Multi-stage Dockerfile — builder stage + minimal runtime stage
- Non-root user inside container — security hardened
- Gunicorn as WSGI server — never Flask dev server in production
- Conventional Commits —
feat(),fix(),chore()on every commit - GitHub Actions Secrets — zero hardcoded credentials anywhere
- Image tagging —
:latest+:commit-SHAfor full traceability - Health endpoints —
/health(liveness) +/ready(readiness) for Kubernetes - Prometheus metrics —
/metricsendpoint baked in from day one - Helm values.yaml — single file controls all config, no hardcoded YAML
- GitOps with ArgoCD — git is the single source of truth for deployments
- Resource limits — CPU and memory limits on every Kubernetes pod
- Helm lint + diff — chart validated before every deploy
- Trivy security scan — CVE scan on every Docker image before push
- pytest + coverage — unit tests run before every build
- Alertmanager — real-time email alerts on infrastructure anomalies
Full-Stack-Devops-Project/
│
├── app/ # Application code
│ ├── app.py # Flask API + routes
│ ├── requirements.txt # Python dependencies
│ ├── Dockerfile # Multi-stage Docker build
│ ├── templates/
│ │ └── index.html # Dark-themed voting UI
│ └── tests/
│ ├── conftest.py # pytest fixtures
│ └── test_app.py # unit tests
│
├── k8/ # Kubernetes manifests
│ ├── helm/
│ │ └── ipl-voter/
│ │ ├── Chart.yaml # Helm chart metadata
│ │ ├── values.yaml # All config in one place
│ │ └── templates/
│ │ ├── _helpers.tpl # Helm named templates
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ ├── argocd/
│ │ └── application.yaml # ArgoCD app manifest
│ └── monitoring/
│ ├── servicemonitor.yaml # Prometheus scrape config
│ ├── alertmanager-config.yaml # Email route config
│ └── alert-rules.yaml # CPU/Memory/Pod alert rules
│
├── .github/
│ └── workflows/
│ └── cicd.yaml # GitHub Actions CI/CD pipeline
│
├── .gitignore
└── README.md
- Python Flask REST API
- 10 IPL teams with real-time voting
- SQLite persistence — votes survive container restarts
- Live leaderboard with vote percentage bars
- Routes:
/,/ui,/vote/<team>,/results,/health,/ready,/metrics
App UI — IPL Team Voter
- Multi-stage Dockerfile
- Non-root user for security
- Gunicorn production server
- Image:
omjaju18/ipl-voter:latest
Docker Hub — Image Tags
- GitHub Actions on every push to
main - Auto build + push to Docker Hub
- Tags:
:latest+:commit-sha
CI Pipeline — GitHub Actions
- Helm chart with
_helpers.tpl,deployment.yaml,service.yaml - Liveness probe →
/health, Readiness probe →/ready - NodePort
30007for local access - Resource limits: CPU
500m, Memory256Mi - Deployed to Minikube — 2 pods running
Helm Install + Lint
Kubernetes Pods Running
- ArgoCD v3.4.3 installed on Minikube
- Connected to GitHub repo — auto-sync enabled
- Every
git push= automatic Kubernetes deployment selfHeal: true— drift auto-correctedprune: true— removed resources cleaned up
ArgoCD — Synced to HEAD
testjob → flake8 lint + pytest unit testssecurity-scanjob → Trivy CVE scan on Docker imagebuildjob → Docker build + push (:latest+:sha)helm-validatejob → helm lint + helm diffupdate-image-tagjob → updatesvalues.yaml, triggers ArgoCDnotifyjob → Email notification on success/failure
CI/CD Pipeline — All Jobs Passing
Email Notification — Pipeline Success
kube-prometheus-stackHelm chart installed- Prometheus scrapes
/metricsfrom pods via ServiceMonitor - Grafana dashboard — CPU, Memory, Request Rate, Error Rate
- Alertmanager with Gmail SMTP email alerts
- 3 alert rules:
HighCPUUsage,HighMemoryUsage,PodNotReady
Grafana Dashboard — Live Metrics
Prometheus — Flask Metrics
Alert Rules — Prometheus
Alert Firing — HighMemoryUsage
Alert Email — Gmail Notification
git push origin main
↓
Lint + Tests (flake8 + pytest)
↓ fail = stop
Trivy Security Scan
↓ fail = stop
Docker Build + Push to Hub
omjaju18/ipl-voter:latest
omjaju18/ipl-voter:<sha>
↓
Helm Lint + Helm Diff
↓ fail = stop
Update values.yaml (image tag)
↓
ArgoCD detects change
↓
helm upgrade → Kubernetes
↓
New pods rolling deployed ✅
↓
Email Notification 📧
Flask App (/metrics)
↓
ServiceMonitor (Prometheus scrape every 15s)
↓
Prometheus (evaluates alert rules)
↓ threshold breached
Alertmanager (routes to email)
↓
Gmail alert → omjaju03@gmail.com 📧
| Alert | Condition | Severity |
|---|---|---|
HighCPUUsage |
CPU rate > 0.008 for 1m | warning |
HighMemoryUsage |
Memory > 90MB for 1m | warning |
PodNotReady |
Pod ready == 0 for 1m | critical |
- Docker
- Python 3.12+
- Minikube v1.37+
- Helm v3.19+
- kubectl v1.29+
- Git
cd app
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python app.py
# Visit http://localhost:5000/uidocker build -t ipl-voter:local ./app
docker run -p 5000:5000 ipl-voter:local
# Visit http://localhost:5000/uicd app
source venv/bin/activate
pip install pytest pytest-cov
pytest tests/ -vminikube start
helm install ipl-voter ./k8/helm/ipl-voter
kubectl get pods
kubectl port-forward svc/ipl-voter-ipl-voter 8080:80
# Visit http://localhost:8080/uikubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
kubectl port-forward svc/argocd-server -n argocd 8081:443
# Visit https://localhost:8081 (admin / <password above>)helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack -n monitoring --create-namespace
# Apply monitoring configs
kubectl apply -f k8/monitoring/servicemonitor.yaml
kubectl apply -f k8/monitoring/alertmanager-config.yaml
kubectl apply -f k8/monitoring/alert-rules.yaml# App
kubectl port-forward svc/ipl-voter-ipl-voter 8080:80
# Grafana
kubectl port-forward -n monitoring svc/monitoring-grafana 3000:80
# Prometheus
kubectl port-forward -n monitoring svc/monitoring-kube-prometheus-prometheus 9090:9090
# ArgoCD
kubectl port-forward svc/argocd-server -n argocd 8081:443| Method | Endpoint | Description |
|---|---|---|
| GET | / |
App info + team list (JSON) |
| GET | /ui |
Voting UI |
| GET | /vote/<team> |
Cast a vote |
| GET | /results |
Leaderboard + winner |
| GET | /health |
Liveness probe |
| GET | /ready |
Readiness probe |
| GET | /metrics |
Prometheus metrics |
| Tool | Cost |
|---|---|
| GitHub + GitHub Actions | $0 |
| Docker Hub | $0 |
| Minikube (local) | $0 |
| ArgoCD (self-hosted) | $0 |
| Prometheus + Grafana (self-hosted) | $0 |
| Alertmanager (self-hosted) | $0 |
| Total | $0 |
- GitHub Repo: https://github.com/omjaju18/Full_Stack_Devops_Project
- Docker Hub: https://hub.docker.com/repository/docker/omjaju18/ipl-voter/
Om Jaju — Building in public, one DevOps tool at a time.
MIT License — feel free to fork and build your own version!