All case studiesLab project
Kubernetes Platform on AWS (EKS)
A production-style Kubernetes platform on Amazon EKS, provisioned with Terraform: multi-AZ VPC, managed node groups, ALB ingress with TLS, autoscaling workloads, images in Amazon ECR, and Prometheus/Grafana monitoring.
- Kubernetes
- Amazon EKS
- Terraform
- AWS VPC
- IAM
- Amazon ECR
- ALB
- Helm
- Prometheus
This is a personal lab build used to practise and demonstrate the approach. It describes architecture and decisions, not results from a client engagement.
Problem
An application had outgrown a single Docker host: deployments caused downtime, scaling meant resizing a server by hand, and the AWS resources behind it had been created through the console with no record of how.
Architecture
- AWS network
- VPC across availability zones
- Public subnets (load balancers)
- Private subnets (nodes)
- NAT gateway
- Cluster
- Amazon EKS control plane
- Managed node groups
- IAM roles for service accounts
- Ingress
- AWS Load Balancer Controller
- Application Load Balancer
- ACM TLS certificate
- Route 53
- Workloads
- Deployments
- Services
- HorizontalPodAutoscaler
- PodDisruptionBudget
- Delivery & data
- Amazon ECR
- GitHub Actions (OIDC)
- Amazon RDS PostgreSQL
- Observability
- Prometheus
- Grafana
- CloudWatch
Technical decisions
- Everything in Terraform
- VPC, EKS cluster, node groups, IAM, ECR, and RDS are defined as Terraform modules with remote state, so the whole environment can be reviewed, recreated, or copied for staging.
- Nodes in private subnets
- Worker nodes and the database have no public IPs. Only the Application Load Balancer is internet-facing, terminating TLS with an ACM certificate.
- Least-privilege identity for pods and pipelines
- Workloads get AWS permissions through IAM roles for service accounts rather than node-wide credentials, and the CI pipeline authenticates to AWS with GitHub OIDC — no long-lived access keys.
- Let Kubernetes handle rollouts and scaling
- Rolling updates gated by readiness probes, a PodDisruptionBudget for node maintenance, and an HPA that scales on CPU replace the manual deploy-and-resize routine.
Implementation
- Wrote Terraform modules for the VPC, EKS cluster, managed node groups, IAM roles, ECR repositories, and RDS.
- Installed the AWS Load Balancer Controller and exposed services through an Ingress backed by an ALB.
- Packaged the application as Kubernetes manifests with probes, resource requests and limits, HPA, and PDB.
- Built a GitHub Actions pipeline that builds the image, pushes a SHA-tagged image to ECR, and runs a rolling update.
- Deployed Prometheus and Grafana for cluster and workload metrics alongside CloudWatch for AWS-level signals.
- Documented cluster access, deployment, rollback, and upgrade procedures.
Security considerations
- Private subnets for nodes and database; only the load balancer is public.
- IAM roles for service accounts and GitHub OIDC instead of static AWS keys.
- Kubernetes Secrets for application configuration, never committed to Git.
- Containers run as non-root with resource limits.
- TLS everywhere at the edge via ACM.
Operational benefits
- Deployments roll out without taking the application offline.
- Capacity follows load instead of manual server resizing.
- The full AWS environment is reproducible from code.
- Rollback is a single command to the previous image tag.
Lessons learned
- Resource requests drive both scheduling and autoscaling — getting them right matters more than any other setting.
- Plan IAM for pods early; retrofitting least privilege is harder than starting with it.
- Watch the quiet AWS costs — NAT gateways, idle nodes, and unattached volumes add up.