Start here
Scattered ECS, EC2, Lambda, and per-account stacks onto two GitOps-managed clusters.
N stacks → 2 clusters
ECS, EC2, and account sprawl onto EKS
10+ services
GitOps per environment
Public / internal
ingress as a first-class split
ELK fleet gone
forwarders replaced in-cluster
I migrated a production platform from legacy, dispersed AWS onto consolidated Kubernetes.
Before, workloads lived in different AWS accounts: ECS Fargate stacks per service, EC2 boxes with cron, Lambdas, and EventBridge kicking ECS tasks. Each app often brought its own ALB. Logs shipped through dozens of CloudWatch → Lambda → ELK forwarders. Environments drifted. Deploys were not one pipeline. After, dev and prod share one VPC and two EKS clusters. Apps ship through reusable CI → ECR → GitOps → Argo CD. Traffic goes through Istio. Operators reach private APIs over a Defguard split-tunnel VPN and private DNS. Secrets sync from AWS. Nodes scale with Karpenter. Cron and EventBridge/ECS jobs became CronJobs and KEDA-scaled workloads. Extra load balancers went away.
The estate had grown service-by-service and account-by-account, not as a platform. Pain: slow new services, inconsistent security, extra load balancers, expensive log plumbing, and no single place to see what is running where.
Treat Kubernetes as the runtime for app workloads. Clusters and data plane stay in Terraform. Everything that changes weekly — images, routes, replicas — lives in git and is synced by Argo CD. Istio owns north-south traffic. Defguard split-tunnel VPN plus private hosted zones is how humans reach the internal mesh. Secrets and AWS access are pod-scoped. One ingress path instead of a load balancer per service.
Cluster
Terraform EKS: KMS-encrypted secrets, EKS Pod Identity, pinned add-ons
Packaging
Kustomize overlays per env; one Argo CD Application per service
Traffic
Istio — public NLB vs internal gateway; NetworkPolicies on the VPC CNI; leftover ALBs retired
Access
Defguard split-tunnel VPN and Route 53 private zones for operator APIs
TLS
cert-manager and Let's Encrypt DNS-01 for wildcard internal certs
Secrets
External Secrets Operator from AWS Secrets Manager
Scale
Small system node group plus Karpenter for everything else
Jobs
CronJobs instead of EC2 cron; KEDA on SQS instead of Lambda and EventBridge + ECS
CI
Shared workflows and self-hosted runners inside the cluster for rollout checks
Obs
kube-prometheus-stack, Loki, Tempo — ELK and log-forwarder Lambdas gone
platform.txt
App repo push
→ reusable GitHub Actions (OIDC → ECR)
→ patch GitOps manifests
→ Argo CD syncs the cluster
→ Istio VirtualService
├── public gateway (internet / CDN)
└── internal gateway (VPN + private DNS)Before
After
Have a project in mind?
Let's build something together.