Course outline

14.4

Amazon EKS

Managed Kubernetes, node types, storage drivers, ECS vs EKS, and App Runner.

20 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • Explain what Kubernetes is (an open-source orchestrator from Google, now governed by the CNCF) and use its basic words: cluster, control plane, node, pod, Deployment, Service, namespace, kubectl, Helm.
  • Describe Amazon EKS: a managed Kubernetes control plane spread over three AZs, billed per cluster-hour ($0.10 standard, $0.60 in extended support), with your worker nodes in your own VPC.
  • Choose the worker capacity: managed node groups, self-managed nodes, Fargate profiles, or EKS Auto Mode, and scale nodes with Cluster Autoscaler or Karpenter.
  • Give pods persistent storage through CSI drivers: EBS (ReadWriteOnce, one AZ), EFS (ReadWriteMany, the only choice on Fargate), FSx for Lustre for ML and HPC, and the others.
  • Give each pod its own IAM permissions with IRSA or EKS Pod Identity, and put an ALB or NLB in front with the AWS Load Balancer Controller.
  • Choose between ECS and EKS from the exam keywords, and between App Runner, ECS on Fargate, ECS on EC2, EKS and Lambda for any container workload.

#Kubernetes in one page

Lesson 14.2 showed Amazon ECS, AWS’s own container orchestrator. Kubernetes (often written K8s: K, eight letters, s) does the same job, keeping hundreds of containers running, replacing the ones that crash and adding more under load, but it is open source. Google built it from its experience running containers internally, released it in 2014, and in 2015 gave it to the Cloud Native Computing Foundation (CNCF), part of the Linux Foundation. No single cloud owns it, every major cloud offers it, and you can run it in your own data center. That is why it became the industry standard for containers.

Amazon EKS (Elastic Kubernetes Service) is managed Kubernetes on AWS. It is an alternative to ECS with the same goal and a different API: you talk to it with the standard Kubernetes tools, not with ECS task definitions.

The words you need:

Kubernetes wordWhat it isClosest ECS idea (lesson 14.2)
ClusterThe control plane plus the worker nodes it managesECS cluster
Control planeAPI server, etcd (the database of desired state), scheduler, controllersThe ECS service itself, run by AWS
NodeA machine (an EC2 instance, or a Fargate micro-VM) that runs pods; its agent is the kubeletContainer instance with the ECS agent
PodThe smallest thing Kubernetes runs: one or more containers sharing one IP address and volumesTask
Deployment“Keep N replicas of this pod running”; does rolling updatesService (desired count)
ServiceA stable name and virtual IP in front of a changing set of podsService discovery + target group
NamespaceA named partition of the cluster for a team or an app(no direct equivalent; separate clusters or services)
ManifestA YAML file that declares the desired stateTask definition JSON
kubectlThe command-line client that talks to the API serveraws ecs CLI
HelmThe package manager: a chart is a reusable, versioned bundle of manifests(none; CloudFormation or Copilot)

Kubernetes is declarative: you write “I want three replicas of checkout:1.4.2”, and controllers keep comparing what you want with what exists, fixing the difference forever. A crashed container is restarted; a dead node’s pods are placed somewhere else.

#Amazon EKS: AWS runs the control plane

In a self-built Kubernetes cluster you must run the control plane yourself: at least three etcd servers, API servers behind a load balancer, certificates, backups and upgrades. It is the hardest part of Kubernetes. With EKS, AWS runs the control plane for you:

  • It runs at least two API server instances and three etcd members across three Availability Zones of the Region, in an AWS-managed account. Unhealthy members are replaced automatically, and etcd is backed up and encrypted.
  • You get an API endpoint (public, private, or both) for kubectl. The control plane reaches your nodes through ENIs that EKS places in your subnets.
  • You choose the Kubernetes version and trigger upgrades; AWS performs them.
  • Your worker nodes and pods live in your own VPC, usually in private subnets.

An EKS cluster: AWS runs the brain, your nodes run the pods

A Dhaka e-commerce shop runs its checkout API on EKS before the Eid sale. The control plane lives in an AWS-managed account across three AZs; the worker nodes and pods live in the shop’s own VPC. Watch a deployment, a crashing container, a dead node and a control-plane AZ outage.

Scenario

You declare what you want; the control plane makes it true.

AWS-managed
Your VPC
AZ a
AZ b
kubectl
Control planeAPI · etcd · scheduler
Node 1kubelet
Node 2kubelet
ECR
apply
Step 1 of 4
1

The developer runs kubectl apply with a Deployment manifest: image checkout:1.4.2, replicas: 2. kubectl talks only to the Kubernetes API server, which AWS runs for you. You never log in to it.

#Paying for the control plane

Each EKS cluster costs $0.10 per hour while its Kubernetes version is in standard support (about $73 a month for 730 hours), on top of the EC2 instances, Fargate pods, EBS volumes and load balancers it uses. A Kubernetes version gets 14 months of standard support after it appears on EKS, then 12 months of extended support at $0.60 per cluster per hour (about $438 a month). Extended support is on by default; when it ends, AWS upgrades the control plane automatically. Managed node groups and self-managed nodes are not upgraded with it; you must upgrade them yourself.

Multiply by the number of clusters: dev, staging and prod in three Regions is nine clusters, about $657 a month before a single pod runs. That is one reason small teams prefer ECS, whose control plane costs nothing.

#The EKS picture inside a VPC

The usual architecture spans three AZs. Each AZ has a public subnet with a NAT gateway (and, if you expose services publicly, the nodes of a public load balancer) and a private subnet with the worker nodes, which belong to an Auto Scaling group and run the pods. A Kubernetes Service can be published through a public load balancer for internet users or a private (internal) one for other systems in the VPC. Nodes reach ECR and AWS APIs through the NAT gateways or VPC endpoints (lesson 22.2).

Two more rules from the slides:

  • An EKS cluster lives in one Region. For a multi-Region application, deploy one EKS cluster per Region and route users between them (Route 53, Global Accelerator).
  • Collect logs and metrics with CloudWatch Container Insights, which reads metrics from every node and pod (chapter 19, lesson 19.4).

#Why companies choose EKS

From the notes: a company that does not want to depend on one cloud provider (vendor lock-in), and that already runs Kubernetes on its own servers, can move to EKS easily, because the same manifests, Helm charts and tools keep working. Kubernetes is cloud-agnostic: the same API on AWS, Azure, Google Cloud or on premises.

#Worker nodes: where the pods run

The control plane is always AWS’s job. The worker capacity under the pods comes in four kinds (the notes list the first three):

Managed node groupsSelf-managed nodesFargateEKS Auto Mode (Dec 2024)
What you getEC2 instances in an ASG that EKS creates and managesEC2 instances you create and register to the cluster, in your own ASGNo nodes: each pod runs in its own micro-VMEC2 nodes that AWS chooses, launches, patches and scales
AMIEKS-optimized AMI (Amazon Linux, Bottlerocket, Windows), or your own through a launch templateAny: the EKS-optimized AMI or your own custom AMINone to chooseBottlerocket variant chosen by AWS
UpgradesOne action: EKS replaces nodes, draining them gracefullyYour job, node by nodeRestart the pods; new ones get the new versionAutomatic; nodes live at most 21 days
SpotOn-Demand or SpotOn-Demand or SpotNot on EKS (no Fargate Spot for EKS)Yes, through NodePools
You payEC2 priceEC2 pricePer second for each pod’s vCPU and memoryEC2 price plus an Auto Mode fee per instance
Pick it whenThe default for most clustersYou need full control: special OS, kernel or bootstrap, your own upgrade timingNo servers to manage, spiky or small workloadsYou want EKS with the least node work

The notes say self-managed nodes are rarely used. That is fair: today they are the exception for teams with special operating systems, hardened images and strict control of upgrades. Managed node groups also accept a custom AMI through a launch template, so “custom AMI” alone no longer forces self-managed nodes.

Fargate on EKS works through a Fargate profile: a rule such as “pods in namespace checkout (with these labels) run on Fargate, in these private subnets”. A pod that matches is placed in its own micro-VM, sized from its CPU and memory requests plus 256 MB for the kubelet and friends, rounded up to the next Fargate size. A pod that matches no profile, in a cluster with no EC2 nodes, stays Pending. Fargate pods cannot run DaemonSets, privileged containers, GPUs or EBS volumes, and they run only in private subnets.

Where do the pods run? Four kinds of worker capacity

The control plane is always AWS’s job. The capacity under the pods is your choice: a managed node group, self-managed nodes, Fargate, or (since December 2024) Auto Mode. Each scenario shows who does what, and where it breaks.

Scenario

EKS creates the EC2 instances in an Auto Scaling group and upgrades them for you.

Managed node group
Self-managed nodes
Fargate profile
You
Control plane
EC2 nodesEKS-optimized AMI
create nodegroup
Step 1 of 3
1

You ask for a node group: instance type m6i.large, 3 to 10 nodes, On-Demand or Spot. EKS creates the launch template and an Auto Scaling group in your account, with the EKS-optimized AMI.

#Scaling nodes: Cluster Autoscaler and Karpenter

Two layers scale, just like ECS service scaling and capacity providers in lesson 14.3:

  1. Pods: the Horizontal Pod Autoscaler changes a Deployment’s replica count from CPU, memory or custom metrics (like ECS Service Auto Scaling). New pods need room on nodes.
  2. Nodes: when pods are Pending because no node has room, something must add EC2 capacity. Kubernetes alone never creates machines.
Cluster AutoscalerKarpenter
OriginKubernetes project, works on many cloudsOpen source, created by AWS, now part of the Kubernetes autoscaling community
How it adds nodesRaises the desired capacity of a node group’s ASG; every new node has that group’s instance typeReads the Pending pods’ needs and launches the right instance directly through the EC2 API, no node group or ASG
Instance choiceFixed per node group; more types need more groupsAny type allowed by a NodePool (families, sizes, Spot or On-Demand, zones)
Speed and packingMinutes; often half-empty nodesFaster; packs pods tightly
Scale-inRemoves underused nodes after about 10 minutesConsolidation: moves pods to fewer or cheaper nodes
SpotThrough mixed-instance node groupsNative, handles the 2-minute interruption notice

For new EKS clusters Karpenter is the usual recommendation, and EKS Auto Mode runs it for you. Either way, check the limits before a big event: a node group at its max size, or an EC2 service quota, leaves pods Pending however good the autoscaler is.

Pods are Pending: Cluster Autoscaler or Karpenter adds nodes

Eid sale traffic doubles. The Horizontal Pod Autoscaler asks for more checkout pods, but the nodes are full, so new pods wait as Pending. Two tools can add nodes: Cluster Autoscaler grows the Auto Scaling group; Karpenter launches right-sized instances directly.

Scenario

Unschedulable pods → raise the ASG’s desired capacity → a node of the group’s type.

Node group (ASG)
Control planescheduler4 pods Pending
Cluster Autoscaler
Karpenter
Node 1m6i.largefull
Step 1 of 4
1

Four new checkout pods ask for 1 vCPU each. Node 1 has no room left, so the scheduler marks them Pending with “Insufficient cpu”. Kubernetes alone never creates machines.

#Data volumes: CSI drivers

Containers lose their files when they stop. For data that must survive, Kubernetes uses three objects:

  • StorageClass: a named kind of storage, saying which driver creates it and with what settings (for example EBS gp3, encrypted). The slides note you must define one on the cluster.
  • PersistentVolumeClaim: a pod’s request: “100 GiB of class gp3, access mode ReadWriteOnce”.
  • PersistentVolume: the actual volume bound to the claim, created on demand by the driver (dynamic) or ahead of time (static).

The driver is a CSI (Container Storage Interface) driver, a plug-in that turns those objects into AWS API calls. AWS maintains a driver for each storage service:

CSI driverAccess modeScopeUse it for
Amazon EBSReadWriteOnce: one node at a timeOne AZPersonal storage per pod: databases, StatefulSets
Amazon EFSReadWriteMany: many pods on many nodesMulti-AZShared files: uploads, CMS media, shared config; the only one on Fargate
FSx for LustreReadWriteManyOne AZML training and HPC: hundreds of GB/s, linked to S3
FSx for NetApp ONTAPReadWriteMany (NFS, SMB) or block (iSCSI)Single- or Multi-AZEnterprise NAS features: snapshots, clones, migrated NetApp workloads
FSx for OpenZFSReadWriteManySingle- or Multi-AZLow-latency NFS for workloads moved from ZFS
Mountpoint for Amazon S3Read-mostly file access to a bucketRegionalReading large datasets straight from S3

FSx itself is lesson 12.2; EBS and EFS are lessons 5.1 and 5.4. Side note: EKS also lists Amazon File Cache and the 2026 Amazon S3 Files (S3 data presented as a shared file system, mounted through the EFS CSI driver, not on Fargate); neither is in the exam yet.

The trap the exam and production both love: an EBS volume belongs to one AZ. If a StatefulSet pod is rescheduled to a node in another AZ, it cannot attach its volume and stays Pending. Use the StorageClass binding mode WaitForFirstConsumer so new volumes are created in the pod’s AZ, keep nodes in every AZ that holds volumes, and for data that must survive an AZ loss, replicate at the database level or use EFS.

EKS on Fargate supports only EFS for persistent storage (static provisioning: create the file system and PersistentVolume first). EBS volumes cannot be mounted on Fargate pods, and FSx for Lustre is not available there either. Each Fargate pod also gets 20 GiB of ephemeral storage by default, up to 175 GiB, deleted when the pod stops.

Persistent volumes: EBS stays in one AZ, EFS is everywhere

Pods come and go; data must not. A PersistentVolumeClaim asks for storage, a StorageClass says which CSI driver creates it. Watch EBS (ReadWriteOnce, one AZ), EFS (ReadWriteMany), Fargate’s limits and FSx for Lustre.

Scenario

A claim makes the EBS CSI driver create a volume and attach it to one node.

AZ a
AZ b
Pod (AZ a)db-0: claim 100 GiB
EBS volumegp3 · AZ a
Step 1 of 3
1

The shop’s order database runs as a StatefulSet. Pod db-0 has a PersistentVolumeClaim: 100 GiB, StorageClass gp3, access mode ReadWriteOnce.

#Load balancers and IAM for pods

#AWS Load Balancer Controller

Kubernetes describes load balancing with its own objects. On EKS the AWS Load Balancer Controller (an add-on you install, built into Auto Mode) watches them and creates the AWS resources:

  • An Ingress (HTTP routing by host and path) → an Application Load Balancer with listeners, rules and target groups.
  • A Service of type LoadBalancer → a Network Load Balancer.

With target type ip the load balancer sends traffic straight to each pod’s VPC IP address, which every pod has thanks to the Amazon VPC CNI plugin; this is the only option for pods on Fargate. Target type instance sends traffic to a port on each node, which forwards it to a pod. The controller needs its own IAM permissions; without them the Ingress never gets an address. ALB and NLB themselves are lesson 6.3.

#IRSA and EKS Pod Identity

The same rule as ECS task roles (lesson 14.2): never put application permissions on the node’s IAM role, because every pod on that node can use it. The node role is for the kubelet: join the cluster, pull from ECR, attach network interfaces.

EKS has two ways to give a single workload its own IAM role:

  • IRSA (IAM Roles for Service Accounts): the cluster has an OIDC provider registered in IAM. You annotate a Kubernetes service account with a role ARN; the role’s trust policy accepts only that service account. The pod gets a signed token, and the AWS SDK exchanges it with STS (AssumeRoleWithWebIdentity) for short-lived credentials. Works on EC2 nodes and on Fargate.
  • EKS Pod Identity (2023): simpler. The role trusts the service pods.eks.amazonaws.com, and you create an association (cluster, namespace, service account, role) with the EKS API. The Pod Identity Agent on each node hands out the credentials. No OIDC provider per cluster, and one role can be reused by many clusters without editing its trust policy. It works for pods on Linux EC2 nodes only, not on Fargate.

Also limit the instance metadata service (IMDSv2 with a hop limit of 1) so pods cannot borrow the node role at all.

Which pod may touch S3? IAM for pods, and the ALB in front

A bKash-style payment company runs a payments pod and a reports pod on the same node. Only payments may read the payments bucket. Watch the node-role mistake, the fix with IRSA or EKS Pod Identity, and how an ALB reaches the pods.

Scenario

Every pod on the node inherits the node’s permissions.

One worker node
Pod rolepayments only
Node roleinstance profile
payments pod
reports pod
S3 bucketpayments-example
Step 1 of 3
1

In a hurry, someone adds s3:GetObject on payments-example to the node’s IAM role. The node role exists so the kubelet can join the cluster and pull images from ECR, not for applications.

#ECS vs EKS

The notes’ conclusion (the owner’s guess, confirmed in the chat): both have the same goal, container orchestration: manage hundreds of containers, start new ones when load grows, restart the ones that crash. They reach it by two different philosophies.

Amazon ECSAmazon EKS
EngineAWS’s own, proprietary APIOpen-source Kubernetes (CNCF)
Learning curveLow: task definitions and servicesHigh: pods, Deployments, Services, Ingress, Helm, RBAC…
Control plane costFree$0.10 per cluster-hour (extended support $0.60)
AWS integrationNative: ALB, IAM task roles, CloudWatch, Secrets Manager built inThrough add-ons and controllers (VPC CNI, Load Balancer Controller, CSI drivers, Pod Identity)
PortabilityAWS onlyAny cloud or data center
EcosystemAWS toolsThe whole Kubernetes ecosystem: Helm, Argo, Prometheus, Istio, Kubeflow…
ComputeEC2 or Fargate launch types, capacity providersManaged or self-managed node groups, Fargate profiles, Auto Mode
HybridECS AnywhereEKS Anywhere, EKS Hybrid Nodes, EKS on Outposts

Summary from the notes: both manage Docker containers, and both can run on Fargate (serverless) or on EC2. The difference is the engine: AWS’s own (ECS) or the open-source leader (EKS, Kubernetes).

#AWS App Runner: the simplest end

AWS App Runner takes source code (from a repository) or a container image (from ECR) and gives you a running HTTPS web service with a URL, load balancing, auto scaling and deployments on every push. No cluster, no task definition, no load balancer, no VPC design. You set the CPU and memory per instance and the concurrency per instance, and it scales between a minimum and a maximum number of instances.

Its status changed in 2026: App Runner closed to new customers on 30 April 2026. Existing customers keep using it, including creating new services, and AWS keeps it secure and available, but no new features are planned. For new work AWS recommends Amazon ECS Express Mode (November 2025): one API call with an image and two IAM roles creates an ECS service on Fargate, an ALB with HTTPS, auto scaling and networking in your account, at no extra charge beyond those resources.

#Choosing where a container runs

This closes the chapter. From simplest to most control:

OptionYou manageYou payPick it when
AWS App Runner (exam) / ECS Express Mode (today)Almost nothing: an image or codePer instance size and timeA web app or API, simplest possible
AWS Lambda (chapter 15)Only codePer request and millisecondShort event-driven work, under 15 minutes, idle in between
ECS on FargateTask definitions, servicesPer second for configured vCPU and memoryLong-running containers or jobs, no servers, deep AWS integration
ECS on EC2Plus the instances: AMI, patching, capacityEC2 prices (RIs, Savings Plans, Spot)GPUs, host access, privileged containers, steady fleets you want to reserve
Amazon EKSKubernetes itself, plus nodes (unless Fargate or Auto Mode)$0.10 per cluster-hour plus computeExisting Kubernetes, Helm, open-source tools, portability, multi-cloud
  1. Is it short, event-driven code that can finish within 15 minutes?

    An S3 upload, an API call, a queue message, a schedule: Lambda (lesson 15.1). Otherwise it is a container; continue.

  2. Does the question say Kubernetes, Helm, open source, vendor lock-in or multi-cloud?

    EKS. Then choose managed node groups (default), Fargate profiles (no nodes), or self-managed nodes (full control).

  3. Is it “the simplest way” to run a web app from code or an image?

    App Runner in an exam question; ECS Express Mode in a new design.

  4. Does it need GPUs, root or privileged access to the host, or Reserved Instances?

    ECS on EC2 (the EC2 launch type). Otherwise ECS on Fargate, the default for containers on AWS.

Where should this container run?

Pick a scenario, read its keywords, and choose: App Runner, ECS on Fargate, ECS on EC2, EKS or Lambda. Then read why. This is the whole chapter in one decision.

1. Choose a scenario(Right first time: 0/9)

A bank runs 60 microservices on Kubernetes in its own data center, deployed with Helm charts and watched with Prometheus. It wants to move to AWS without rewriting its manifests, and keep the option of running some services on premises.

Keywords:existing KubernetesHelm chartshybrid

2. Your answer

#What goes wrong

SymptomLikely causeFix
New pods stay Pending with “Insufficient cpu”Nodes are full and nothing adds capacity, or the node group is at its max sizeCluster Autoscaler or Karpenter; raise max size; check EC2 quotas
Pods Pending, cluster has only FargateThe pod’s namespace or labels match no Fargate profileAdd or fix a Fargate profile, or add a node group
A StatefulSet pod is Pending after an AZ problem, “volume node affinity conflict”Its EBS volume is in another AZNodes in every AZ that has volumes, WaitForFirstConsumer, snapshots, database replication, or EFS
A pod on Fargate cannot mount its volumeIt asks for EBS (or FSx for Lustre)Use EFS with a static PersistentVolume, or run that pod on EC2 nodes
Pods cannot get an IP address, “failed to assign an IP”The VPC CNI gives each pod a subnet IP; small subnets or ENI limits per instance run outBigger subnets or a secondary CIDR, prefix delegation, bigger instance types
Pods fail with ImagePullBackOffNode role lacks ECR permission, wrong tag, or no NAT / VPC endpoints from private subnetsFix the role, the tag, or the network path (lesson 14.1)
A container restarts again and again: CrashLoopBackOffThe app crashes on start (bad config, missing secret, out of memory)kubectl logs --previous, fix the config or raise the memory limit
Any pod can read the payments bucketS3 permissions on the node roleMove them to IRSA or Pod Identity; IMDSv2 with hop limit 1
Pod Identity does nothing on Fargate podsPod Identity is for Linux EC2 nodes onlyUse IRSA for Fargate pods
The Ingress never gets an addressAWS Load Balancer Controller missing or without IAM permissions, or subnets not taggedInstall it with its own role; tag public/private subnets for load balancers
The EKS bill jumped though nothing changedA cluster passed the end of standard support and now costs $0.60 an hourUpgrade on schedule; disable extended support if you prefer forced upgrades
Self-managed nodes break after a control-plane upgradeNobody upgraded them; they fell too many versions behindUpgrade nodes after every control-plane upgrade, or use managed node groups
A team cannot see why App Runner is missing in a new accountApp Runner is closed to new customers since April 2026ECS Express Mode or ECS on Fargate

#EKS in system design

  • Choose EKS for a reason, not by default: existing Kubernetes skills and manifests, the Kubernetes ecosystem, portability. Without one, ECS on Fargate is cheaper to run and to staff.
  • Fewer, bigger clusters, separated by namespaces with RBAC, network policies and resource quotas; separate clusters for prod and non-prod, and one cluster per Region for multi-Region apps.
  • Managed node groups or Auto Mode for most capacity, Karpenter for node scaling, Spot for stateless pods, Fargate profiles for small or spiky namespaces.
  • Spread replicas across AZs (topology spread constraints, pod disruption budgets) so one AZ or one upgrade never takes all copies.
  • State outside pods where possible: managed databases (RDS, DynamoDB), S3, EFS for shared files; EBS only with an AZ-aware design.
  • Least privilege per workload with Pod Identity (EC2 nodes) or IRSA (Fargate); nothing on the node role.
  • Upgrade every few months: a version is cheap for 14 months and six times dearer after that.
  • Observe with CloudWatch Container Insights or Prometheus and Grafana; ship logs with Fluent Bit as a DaemonSet (a sidecar on Fargate).

#Try it yourself

A small cluster for the shop’s checkout service in ap-southeast-1, account 111122223333. Outputs are shortened. It costs money while it runs; delete it at the end.

# 1. Create a cluster with a managed node group (eksctl writes the CloudFormation for you)
eksctl create cluster --name shop-example --region ap-southeast-1 --version 1.37 \
  --nodegroup-name general --node-type m6i.large --nodes 2 --nodes-min 2 --nodes-max 6 \
  --node-private-networking --with-oidc
#   [✔]  EKS cluster "shop-example" in "ap-southeast-1" region is ready

aws eks describe-cluster --name shop-example \
  --query 'cluster.{version:version,status:status,endpoint:endpoint,support:upgradePolicy.supportType}'
#   { "version": "1.37", "status": "ACTIVE",
#     "endpoint": "https://A1B2C3D4E5F6.gr7.ap-southeast-1.eks.amazonaws.com", "support": "EXTENDED" }

aws eks update-kubeconfig --name shop-example --region ap-southeast-1
kubectl get nodes -o wide
#   NAME                                            STATUS   VERSION   INTERNAL-IP
#   ip-10-0-101-23.ap-southeast-1.compute.internal  Ready    v1.37.1   10.0.101.23
#   ip-10-0-142-7.ap-southeast-1.compute.internal   Ready    v1.37.1   10.0.142.7

# 2. Deploy the checkout API: 2 replicas from ECR, exposed through an ALB (Load Balancer Controller installed)
kubectl create deployment checkout \
  --image=111122223333.dkr.ecr.ap-southeast-1.amazonaws.com/checkout-example:1.4.2 --replicas=2
kubectl get pods -o wide
#   NAME                        READY   STATUS    IP            NODE
#   checkout-6d9f7c8b5d-4xk2p   1/1     Running   10.0.101.88   ip-10-0-101-23…
#   checkout-6d9f7c8b5d-q7wz1   1/1     Running   10.0.142.31   ip-10-0-142-7…
kubectl delete pod checkout-6d9f7c8b5d-4xk2p        # watch a replacement appear within seconds
kubectl get pods -w

# 3. A Fargate profile: everything in namespace "reports" runs on Fargate
eksctl create fargateprofile --cluster shop-example --name reports --namespace reports
kubectl create namespace reports
kubectl -n reports create deployment report-api \
  --image=111122223333.dkr.ecr.ap-southeast-1.amazonaws.com/report-api-example:2.0.0
kubectl -n reports describe pod -l app=report-api | grep CapacityProvisioned
#   CapacityProvisioned: 0.25vCPU 0.5GB

# 4. Give only the payments service account S3 access with EKS Pod Identity
aws eks create-addon --cluster-name shop-example --addon-name eks-pod-identity-agent
aws eks create-pod-identity-association --cluster-name shop-example \
  --namespace payments --service-account payments-sa \
  --role-arn arn:aws:iam::111122223333:role/payments-s3-read-example
#   "association": { "associationId": "a-abcd1234example", "namespace": "payments", … }

# 5. A volume: claim 20 GiB of EBS (the EBS CSI driver add-on must be installed)
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: orders-db-data }
spec:
  accessModes: [ReadWriteOnce]
  storageClassName: gp3
  resources: { requests: { storage: 20Gi } }
EOF
kubectl get pvc
#   NAME             STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS
#   orders-db-data   Pending                                      gp3     # WaitForFirstConsumer: bound when a pod uses it

# 6. Check the version lifecycle, then clean up (the cluster costs $0.10 per hour even when idle)
aws eks describe-cluster-versions --cluster-versions 1.37 \
  --query 'clusterVersions[].{v:clusterVersion,endStandard:endOfStandardSupportDate}'
eksctl delete cluster --name shop-example --region ap-southeast-1

Compare with lesson 14.2: there was no control plane to create and nothing to pay for it, and IAM per task was one field in the task definition. That gap in effort is the whole ECS vs EKS decision in practice.

#Summary

Key takeaways

  • Kubernetes (K8s) is the open-source container orchestrator created by Google and governed by the CNCF. Words: cluster, control plane, node, pod, Deployment, Service, namespace, kubectl, Helm charts.
  • Amazon EKS = managed Kubernetes. AWS runs the control plane across three AZs in its own account; your worker nodes and pods run in your VPC. $0.10 per cluster-hour in standard support (14 months), $0.60 in extended support (12 months), then automatic upgrade. One cluster per Region; Container Insights for logs and metrics.
  • Worker capacity: managed node groups (EKS creates the ASG and upgrades nodes, On-Demand or Spot), self-managed nodes (you build, join and upgrade them), Fargate profiles (one micro-VM per pod, no DaemonSets, no EBS), EKS Auto Mode (AWS manages nodes too). EKS says node groups and Fargate profiles, not “launch types”.
  • Node scaling: Horizontal Pod Autoscaler adds pods; Cluster Autoscaler grows node-group ASGs; Karpenter launches right-sized instances directly and consolidates.
  • Storage via CSI drivers with StorageClass and PersistentVolumeClaim: EBS = ReadWriteOnce, one AZ; EFS = ReadWriteMany, multi-AZ, the only option on Fargate; FSx for Lustre = ML/HPC; also FSx for NetApp ONTAP, FSx for OpenZFS, Mountpoint for S3.
  • IAM per pod with IRSA (OIDC, works on Fargate) or EKS Pod Identity (simpler, EC2 nodes only); never on the node role. AWS Load Balancer Controller: Ingress → ALB, Service type LoadBalancer → NLB, target type ip for Fargate.
  • ECS vs EKS: same goal, different philosophy (iOS vs Android). ECS = simplicity, deepest AWS integration, no operational overhead. EKS = avoid vendor lock-in, existing Kubernetes, Helm and open-source tools, multi-cloud. Hybrid exists on both (ECS Anywhere; EKS Anywhere and Hybrid Nodes).
  • App Runner = simplest web app from code or image (the exam answer), closed to new customers since 30 April 2026; ECS Express Mode is today’s equivalent. Short event-driven code → Lambda; containers without servers → ECS on Fargate; GPUs, host access, RIs → ECS on EC2.