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
StatefulSets Explained
StatefulSets give pods sticky names, sticky storage, and ordered operations — what databases and clustered apps need. Here's how each guarantee works.
October 24, 2026Persistent Volumes and Claims, Explained
PVC is a request, PV is the fulfilled storage, StorageClass is the factory. Most 'Pending PVC' problems are an access-mode or provisioner mismatch.
October 24, 2026Kubernetes Jobs and CronJobs
A Job runs pods until they succeed; a CronJob creates Jobs on a schedule. Here's parallelism, retry limits, the missed-schedule trap, and history cleanup.
October 24, 2026