EKS vs Self-Managed Kubernetes
Introduction¶
"Managed Kubernetes" (EKS, GKE, AKS) means the control plane is the cloud's problem. Everything else — nodes, networking choices, add-ons, upgrades of the node fleet, observability — is still yours. Understanding the split prevents surprise.
What EKS manages¶
- API server, etcd, scheduler, controller-manager — HA across AZs, patched, backed up. You never SSH to a master.
- Control-plane upgrades (you click; it does a safe rollout) — but you must then upgrade your nodes and add-ons.
- The control plane's availability SLA.
What's still yours¶
- Nodes — provisioning, sizing, patching the OS, kubelet version, scaling.
- Networking — CNI choice (VPC CNI default; or Calico/Cilium), subnets, IP exhaustion planning (VPC CNI assigns real VPC IPs — a /24 runs out fast), security groups.
- Add-ons — CoreDNS, kube-proxy, VPC CNI (EKS "managed add-ons" help but you choose versions), plus everything else: ingress controller, cert-manager, metrics-server, cluster-autoscaler/Karpenter, CSI drivers, observability.
- IAM ↔ Kubernetes — IRSA / Pod Identity, the
aws-authconfigmap / access entries. - Cost management, security posture, backup of workloads (Velero), DR.
Node options¶
| Option | You manage | Good for |
|---|---|---|
| Managed node groups | instance type, scaling config; AWS handles the AMI + rolling updates | most workloads — the default |
| Self-managed nodes | the ASG, AMI, bootstrap, updates | custom AMIs, GPU/Windows edge cases, full control |
| Fargate | nothing (serverless pods) | bursty, isolation-sensitive, no node ops — but no DaemonSets, limited, pricier per pod |
| Karpenter | Karpenter config | fast, bin-packed, right-sized just-in-time nodes across many instance types — increasingly the standard for scale |
Karpenter vs Cluster Autoscaler: Karpenter provisions nodes directly (no ASGs), picks instance types to fit pending pods, consolidates aggressively. It's now the recommended autoscaler for EKS at scale.
Cost¶
- EKS control plane: a flat ~$0.10/hr per cluster (~$73/mo) + the extended support surcharge if you run an old version.
- The real cost is nodes, LBs, NAT, data transfer — same as self-managed.
- Fargate: pay per pod vCPU/memory-second — can be cheaper for spiky/low utilisation, more expensive for steady high load.
When self-managed (your own control plane) makes sense¶
- On-prem / bare metal — no managed option (kubeadm, k3s, RKE2, Talos, Kubespray).
- Extreme scale or customization — you need control-plane flags/API server tuning the managed service doesn't expose, custom admission webhooks on the API server itself, or a non-standard etcd setup.
- Cost at huge scale where the per-cluster fee across hundreds of clusters matters (rare; usually consolidate clusters instead).
- Air-gapped / regulatory environments.
For most teams on AWS, EKS with managed node groups or Karpenter is the right call — running etcd in production is a specialised job you can outsource.
Verification and troubleshooting¶
aws eks describe-cluster --name my-cluster --query 'cluster.{v:version,status:status,endpoint:endpoint}'
aws eks list-addons --cluster-name my-cluster
kubectl get nodes -o wide
kubectl version # server vs client skew
aws eks describe-addon-versions --addon-name vpc-cni
- Pods stuck
Pending, "too many pods" / no IPs — VPC CNI IP exhaustion. The instance type caps pods (ENIs × IPs-per-ENI); use prefix delegation (ENABLE_PREFIX_DELEGATION), bigger subnets, or a secondary CIDR. error: You must be logged in to the server (Unauthorized)— your IAM identity isn't mapped (aws-authconfigmap or EKS access entries), or the kubeconfig token expired (aws eks update-kubeconfig).- CoreDNS/kube-proxy version incompatible after a control-plane upgrade —
managed add-ons must be bumped to a version matching the new K8s version.
aws eks update-addon. - Nodes NotReady after AMI update — the VPC CNI / kube-proxy on the new node is a version the control plane doesn't like, or the bootstrap script/user-data changed. Managed node groups usually handle this; self-managed needs a matching AMI.
- Karpenter not scaling — its
NodePool/EC2NodeClassconstraints exclude all instance types, subnet/SG selectors wrong, or the IAM role lacksec2:RunInstances. Karpenter logs. - Surprise bill — NAT Gateway data processing (VPC CNI pods egress via NAT), cross-AZ traffic, unused LBs from deleted Ingresses. Not the control plane.
Related tools and reading¶
- On-site: Subnet Calculator.
- Related posts: The AWS Load Balancer Controller, Kubernetes version upgrades without drama.
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.More in Docker & Kubernetes
The AWS Load Balancer Controller
On EKS, the AWS Load Balancer Controller turns Ingress objects into ALBs and LoadBalancer Services into NLBs. Here's target types, ALB sharing, and the IAM/subnet-tag gotchas.
September 7, 2026Pod Security Admission
PSP is gone. Pod Security Admission enforces the Pod Security Standards via namespace labels — three levels, three modes. Here's how to roll it out without breaking things.
August 30, 2026Dockerfile Best Practices That Actually Matter
The handful of Dockerfile habits that cut build time and image size and remove the most common security findings.
August 27, 2026