A production-like deployment of a microservices voting application on Amazon EKS with a fully automated CI/CD pipeline using GitHub Actions.
User → NGINX Ingress → /vote → Vote App (Python/Flask) → Redis
→ /result → Result App (Node.js) ← PostgreSQL
↑
Worker (.NET)
| Category | Technology |
|---|---|
| Cloud Provider | AWS (EKS) |
| Orchestration | Kubernetes |
| CI/CD | GitHub Actions |
| Container Registry | Docker Hub |
| Ingress | NGINX via Helm |
| Secret Management | Kubernetes Secrets |
| Infrastructure CLI | eksctl, kubectl, AWS CLI v2, Helm |
| Service | Language | Role |
|---|---|---|
| vote | Python (Flask) | Voting frontend |
| result | Node.js | Results frontend |
| worker | .NET | Processes votes from Redis to PostgreSQL |
| redis | Redis | Message queue |
| postgres | PostgreSQL | Persistent storage |
├── vote/ # Python voting app + Dockerfile
├── result/ # Node.js result app + Dockerfile
├── worker/ # .NET worker + Dockerfile
├── K8s/
│ ├── redis-deployment.yaml
│ ├── postgres-deployment.yaml
│ ├── vote-deployment.yaml
│ ├── result-deployment.yaml
│ ├── worker-deployment.yaml
│ └── ingress.yaml
└── .github/workflows/
└── ci-cd-pipeline.yml
Triggers automatically on every push to main:
Push to main
→ Build Docker images (vote, result, worker)
→ Push to Docker Hub
→ Configure AWS credentials
→ Update kubeconfig
→ kubectl apply -f K8s/
- AWS Account with IAM user (AdministratorAccess)
- Docker Hub account
- AWS CLI v2, eksctl, kubectl, Docker, Helm installed
eksctl create cluster \
--name voting-app-cluster \
--region eu-central-1 \
--nodegroup-name standard-workers \
--node-type t3.small \
--nodes 2aws eks update-kubeconfig --region eu-central-1 --name voting-app-clusterhelm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginxdocker build -t <dockerhub-username>/vote:latest ./vote && docker push <dockerhub-username>/vote:latest
docker build -t <dockerhub-username>/result:latest ./result && docker push <dockerhub-username>/result:latest
docker build -t <dockerhub-username>/worker:latest ./worker && docker push <dockerhub-username>/worker:latestkubectl create secret generic db-credentials \
--from-literal=POSTGRES_USER=postgres \
--from-literal=POSTGRES_PASSWORD=postgreskubectl apply -f K8s/
kubectl get pods
kubectl get ingressAccess the app:
http://<INGRESS-ADDRESS>/votehttp://<INGRESS-ADDRESS>/result
Add these secrets to your GitHub repo (Settings → Secrets → Actions):
| Secret | Description |
|---|---|
DOCKERHUB_USERNAME |
Docker Hub username |
DOCKERHUB_TOKEN |
Docker Hub password |
AWS_ACCESS_KEY_ID |
AWS access key |
AWS_SECRET_ACCESS_KEY |
AWS secret key |
- Database credentials managed via Kubernetes Secrets
- AWS and Docker Hub credentials stored as GitHub Secrets
- No sensitive data in version control
eksctl delete cluster --name voting-app-cluster --region eu-central-1