This repository provides a production-ready, auto-scaling, and observable Kubernetes environment on AWS. It is built using Terraform and ArgoCD GitOps, as per the JUCR DevOps challenge requirements.
- Terraform-only provisioning — no prebuilt modules
- Highly available EKS cluster across 3 Availability Zones
- Karpenter for node autoscaling
- ArgoCD GitOps for application deployment
- Observability stack with metrics & logs:
- Prometheus, Grafana, Loki, Promtail, CloudWatch Exporter
- Fully automated CI/CD via GitHub Actions
terraform/
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars
└── modules/
bootstrap/
├── app-of-apps.yaml
└── apps/
argo_app/
├── karpenter/
├── kube-prometheus-stack/
├── loki-stack/
.github/
└── workflows/deploy.yaml
- AWS CLI and credentials
- Terraform >= 1.5.0
- GitHub repository secrets:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYGITHUB_TOKEN(for ArgoCD repo access)
cd terraform
terraform init
terraform apply -auto-approveThis provisions the complete infrastructure:
- VPC, subnets, NATs, Internet Gateway
- EKS cluster and node groups
- IAM roles for IRSA
- ArgoCD and Secrets integration
- Karpenter setup
- Logging (CloudTrail, VPC Flow Logs)
Once you push changes (or run the workflow manually), the GitHub Actions pipeline will:
- Fetch Terraform outputs
- Configure
kubectlaccess to EKS - Render and apply
karpenter.yamlviaenvsubst - Deploy
app-of-apps.yamlto ArgoCD
File: .github/workflows/deploy.yaml
- Push to any of:
terraform/**bootstrap/**.github/workflows/deploy.yaml
- Manual trigger (workflow_dispatch)
-
Terraform job
- Runs
terraform apply - Extracts outputs: cluster name, endpoint, IAM ARNs
- Runs
-
Bootstrap job
- Uses
kubectlwith generated kubeconfig - Applies ArgoCD
app-of-apps.yaml - Syncs all declared apps (observability stack, Karpenter)
- Uses
All components are deployed via ArgoCD and Helm under argo_app/.
| Component | Namespace | Purpose |
|---|---|---|
kube-prometheus-stack |
monitoring | Metrics collection & alerts |
grafana |
monitoring | Visualization via dashboards |
loki-stack |
monitoring | Centralized logging |
cloudwatch-exporter |
monitoring | AWS metrics to Prometheus |
metrics-server |
kube-system | Pod-level CPU/memory metrics |
Grafana is exposed via LoadBalancer.
To deploy a new app via ArgoCD:
- Create a new folder under
argo_app/, e.g.:
argo_app/my-app/
├── Chart.yaml
├── values.yaml
└── templates/
- Add an ArgoCD Application definition in
bootstrap/apps/my-app.yaml:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/<your-username>/terraform-aws-eks-infra.git
targetRevision: main
path: argo_app/my-app
helm:
valueFiles:
- values.yaml
destination:
server: https://kubernetes.default.svc
namespace: my-app
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true- Commit and push the changes:
git add argo_app/my-app/ bootstrap/apps/my-app.yaml
git commit -m "Add ArgoCD app: my-app"
git push origin main- ArgoCD will auto-sync and deploy the new app based on the
app-of-apps.yaml.
- ArgoCD admin password and GitHub PAT are stored in AWS Secrets Manager
- Retrieved via
data "aws_secretsmanager_secret_version"in Terraform - Injected into ArgoCD Helm chart
| Task | Frequency |
|---|---|
| Review Terraform plan & state | On infra updates |
| Monitor ArgoCD sync status | Ongoing |
| Rotate ArgoCD admin password | Monthly or as needed |
| Update Helm chart versions | Quarterly |
| Manage application configs | GitOps (commits) |
| Monitor logs and metrics | Continuous (Grafana) |