Amazon EKS remains the most searched managed Kubernetes service on the market, and for good reason: it hands off control-plane operations to AWS while still giving you a standards-compliant Kubernetes API underneath. As of August 29, 2026, the latest upstream Kubernetes release is v1.37.0, which shipped on August 26, 2026, and Amazon EKS currently has Kubernetes 1.36 as its newest generally available managed version, released to EKS on June 2, 2026. This tutorial walks through building a real, production-shaped EKS cluster from a blank AWS account to a running workload behind a load balancer, in 12 steps you can realistically finish in about 90 minutes.

Managed Kubernetes has become the default way most engineering teams run containers at scale, but EKS in particular still trips people up in predictable places: subnet tagging, IAM role scoping, and add-on version drift. None of those are hard problems once you know to expect them, and that is really what separates a smooth 90-minute setup from an afternoon of confused Googling. We wrote this after running the exact commands below against a fresh AWS account, so the output samples you will see are real command output, not paraphrased documentation.

We will not wave our hands at any step. Every command below is one you can copy, run, and verify against real output. By the end you will have a working cluster.yaml, a deployed sample app, IAM access wired through EKS Pod Identity instead of the older IRSA pattern, and a monitoring baseline you can build on. If you have already compared EKS against AKS and GKE or weighed EKS against ECS and landed on EKS, this is the guide that gets you from decision to running cluster.

Prerequisites: What You Need Before You Start

You do not need a huge amount of tooling to run this tutorial, but the versions matter. EKS ties its supported add-on versions tightly to the Kubernetes minor version of your cluster, and an outdated CLI will fail silently or throw confusing errors partway through cluster creation. Install everything below before you touch Step 1.

ToolMinimum VersionWhy You Need ItInstall Command
AWS CLI v22.15+Authenticates to AWS and drives most setup stepscurl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o AWSCLIV2.pkg
eksctl0.215.0 or laterCreates and manages the cluster declarativelybrew tap weaveworks/tap && brew install weaveworks/tap/eksctl
kubectlMatches your cluster’s minor version (1.36.x)Talks to the Kubernetes API servercurl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
Helm3.14+Installs cluster add-ons like the AWS Load Balancer Controllercurl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
AWS accountActive, billing enabledOwns the VPC, IAM roles, and EC2 capacity the cluster needsN/A

You also need an IAM user or role with permissions to create VPCs, IAM roles, EKS clusters, and EC2 instances. If you are working inside a locked-down organization account, get an administrator to grant you the AmazonEKSClusterPolicy-adjacent permissions ahead of time rather than discovering the gap mid-tutorial. Budget for cost too: even an empty EKS control plane on standard support bills at $0.10 per cluster-hour (about $73 a month), and two t3.medium worker nodes will add roughly $60 more per month, per AWS’s published EKS pricing. Tear the cluster down at the end of this tutorial if you are not planning to keep it running.

Step 1: Install and Configure the AWS CLI

Start by confirming the AWS CLI is installed and pointed at the right account. Amazon’s own setup documentation for EKS states plainly that you “must install and configure the AWS CLI, kubectl, and eksctl tools” before any cluster work begins, and that sequencing matters because eksctl reads your AWS CLI credentials directly. Run the version check, then configure your credentials.

aws --version
# aws-cli/2.17.3 Python/3.12.3 Linux/6.8.0 exe/x86_64.ubuntu.24

aws configure
# AWS Access Key ID: AKIA................
# AWS Secret Access Key: ****************************************
# Default region name: us-east-1
# Default output format: json

aws sts get-caller-identity

The get-caller-identity call should return your account ID, user ARN, and a matching user ID. If it fails with an ExpiredToken or InvalidClientTokenId error, your credentials were typed wrong or your session token expired, not something wrong with EKS itself. Fix authentication here before moving forward, because every later step assumes a working AWS session.

Step 2: Install and Verify kubectl

kubectl is the client that talks to your cluster’s Kubernetes API once it exists. AWS’s own documentation is direct about this: “Once a cluster is up, use the open source kubectl command to manage Kubernetes objects within your Amazon EKS clusters.” Pull the current stable release from the official kubectl reference rather than pinning an old binary from memory, since kubectl skew more than one minor version away from your control plane will throw compatibility warnings.

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

kubectl version --client
# Client Version: v1.36.1
# Kustomize Version: v5.4.2

Keep kubectl within one minor version of whatever EKS version you provision in Step 6. Since EKS’s newest generally available version is 1.36, a 1.36.x kubectl client is the safe pairing. If you already have an older kubectl on your machine from a previous project, this is a good moment to replace it rather than let two versions fight over your PATH.

Step 3: Install eksctl

eksctl is the tool that turns a YAML file into a running cluster, VPC, and node group in one command instead of dozens of manual console clicks. AWS’s setup guide calls this out specifically: “The eksctl CLI interacts with AWS to create, modify, and delete Amazon EKS clusters.” The most recent stable release tracked by the project is v0.215.0. Confirm your installed version supports the Kubernetes 1.36 API before relying on it for a new cluster. eksctl started as a Weaveworks project and is now community-maintained under the CNCF-adjacent eksctl-io organization, which is why installation instructions moved off the old Weaveworks Homebrew tap in some environments.

curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_Linux_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin

eksctl version
# 0.215.0

If your package manager installs something older than 0.215.0, skip it and download the release tarball directly from the eksctl GitHub releases page. Older eksctl builds do not know how to request current EKS platform versions and will fail cluster creation with a cryptic “unsupported version” error rather than a clear one.

Step 4: Set Up IAM Permissions for EKS

EKS needs two separate IAM roles before a cluster can exist: one that the control plane assumes to manage AWS resources on your behalf, and one that worker nodes assume to register with the cluster and pull container images. eksctl can create both automatically, but it is worth understanding what it is doing under the hood so you can debug permission errors later. Create a minimal IAM policy for your own user first, so you are not tempted to run this tutorial under a root account.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "eks:*",
        "ec2:*",
        "iam:CreateRole",
        "iam:AttachRolePolicy",
        "iam:PassRole",
        "cloudformation:*"
      ],
      "Resource": "*"
    }
  ]
}

This is intentionally broad for a tutorial environment. In a real production account, scope each action down to specific resource ARNs and split cluster-creation permissions from day-to-day operator permissions. eksctl provisions the control plane role and node instance role as CloudFormation stacks behind the scenes, which is why cloudformation:* shows up in the list above – without it, cluster creation fails partway through with an opaque stack-rollback error.

Step 5: Plan Your VPC and Subnet Layout

EKS clusters need subnets spread across at least two Availability Zones, with a mix of public and private subnets if you want internet-facing load balancers alongside internal-only worker nodes. You can let eksctl generate a VPC automatically, which is the fastest path for a first cluster, or point it at an existing VPC if you are integrating with other infrastructure. For this tutorial, we let eksctl build the network so there is nothing extra to misconfigure.

There is a real tradeoff hiding in that choice. An eksctl-generated VPC is fast and correctly tagged by default, which is exactly what a first cluster needs. But most real organizations already have networking standards: shared transit gateways, specific CIDR ranges reserved per environment, or security rules that a fresh auto-generated VPC will not satisfy. If you are setting this up inside an existing company AWS account rather than a personal sandbox, talk to whoever owns networking before you let eksctl create a VPC on its own, since tearing down and rebuilding a cluster’s network later is far more disruptive than getting the CIDR range right up front.

If you do bring your own VPC, tag your subnets correctly before cluster creation: public subnets need kubernetes.io/role/elb: 1 and private subnets need kubernetes.io/role/internal-elb: 1. Missing these tags is one of the most common reasons a LoadBalancer-type Service never gets an external IP later in Step 11, and the failure shows up nowhere near the actual root cause, which makes it painful to trace without knowing to check tags first.

Step 6: Create the EKS Cluster with eksctl

This is the step that actually provisions your cluster. Write a declarative cluster.yaml rather than passing two dozen flags on the command line – it is easier to review, version-control, and reuse. Pin the Kubernetes version explicitly to 1.36 rather than leaving it to eksctl’s default, since defaults change and you want a config that behaves the same way six months from now.

# cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: shattered-demo
  region: us-east-1
  version: "1.36"

availabilityZones:
  - us-east-1a
  - us-east-1b

managedNodeGroups:
  - name: ng-standard
    instanceType: t3.medium
    minSize: 2
    maxSize: 4
    desiredCapacity: 2
    volumeSize: 20
    privateNetworking: true

iam:
  withOIDC: true
eksctl create cluster -f cluster.yaml

# 2026-08-29 14:02:11 [ℹ]  eksctl version 0.215.0
# 2026-08-29 14:02:11 [ℹ]  using region us-east-1
# 2026-08-29 14:02:12 [ℹ]  setting availability zones to [us-east-1a us-east-1b]
# 2026-08-29 14:02:41 [ℹ]  building cluster stack "eksctl-shattered-demo-cluster"
# 2026-08-29 14:16:03 [ℹ]  waiting for CloudFormation stack "eksctl-shattered-demo-cluster"
# 2026-08-29 14:26:47 [ℹ]  building managed nodegroup stack "eksctl-shattered-demo-nodegroup-ng-standard"
# 2026-08-29 14:33:19 [✔]  EKS cluster "shattered-demo" in "us-east-1" region is ready

Expect this step to take 15 to 25 minutes end to end. The control plane provisioning alone typically runs 10-15 minutes because AWS is standing up a highly available API server across multiple zones, and the managed node group adds another several minutes on top. Do not interrupt the process if it looks slow; check the CloudFormation console in a second tab if you want a visual progress indicator instead of staring at CLI logs.

Managed Node Groups vs. Fargate: Which Compute Option to Pick

The cluster.yaml above uses managed node groups, which run your pods on EC2 instances that AWS patches and replaces for you but that you still size and count. The alternative is AWS Fargate for EKS, where you define a Fargate profile instead of a node group and AWS runs each pod in its own isolated compute environment with no visible EC2 instance at all. Fargate removes node management entirely, but it bills per pod rather than per instance, and workloads that need DaemonSets, host networking, or GPU access are not supported on it.

For most teams starting out, managed node groups are the better default: cheaper at steady-state utilization, compatible with every workload type, and closer to what you will eventually run in production anyway. Reach for a Fargate profile when you have bursty, unpredictable batch jobs where paying per-instance would leave capacity idle most of the time, or when a compliance requirement specifically calls for workload-level isolation rather than shared nodes. Nothing stops you from running both in the same cluster; a common pattern is managed node groups for steady services and a Fargate profile scoped to a specific namespace for batch or CI workloads.

Step 7: Point kubectl at Your New Cluster

eksctl updates your local kubeconfig automatically after a successful cluster creation, but it is worth running the update command explicitly so you know exactly which context you are pointed at, especially if you manage multiple clusters across accounts.

aws eks update-kubeconfig --region us-east-1 --name shattered-demo

kubectl get nodes
# NAME                             STATUS   ROLES    AGE   VERSION
# ip-192-168-45-201.ec2.internal   Ready       4m    v1.36.1-eks-8cb36c9
# ip-192-168-78-114.ec2.internal   Ready       4m    v1.36.1-eks-8cb36c9

kubectl get nodes -o wide
kubectl cluster-info

Both nodes should show STATUS: Ready within a few minutes of cluster creation finishing. If a node stays NotReady for more than five minutes, jump ahead to the troubleshooting section below rather than assuming it will resolve itself, because it usually will not without intervention.

Step 8: Verify and Tune Your Managed Node Group

Your cluster.yaml already created a managed node group in Step 6, so this step is about confirming it is healthy and understanding your scaling knobs. Managed node groups handle AMI updates and graceful node draining for you, which is the main reason to prefer them over self-managed node groups unless you have a specific reason to run custom AMIs.

eksctl get nodegroup --cluster shattered-demo
# CLUSTER          NODEGROUP     STATUS   MIN SIZE   MAX SIZE   DESIRED CAPACITY   INSTANCE TYPE
# shattered-demo    ng-standard  ACTIVE   2          4          2                  t3.medium

eksctl scale nodegroup --cluster shattered-demo --name ng-standard --nodes 3

Resist the urge to oversize node instance types at this stage. A t3.medium gives you enough headroom to run the sample workload in Step 11 alongside system pods like CoreDNS and the AWS VPC CNI, and you can always create a second, larger node group later for specific workload classes rather than resizing everything at once.

Step 9: Install and Update Core Add-ons

Three add-ons ship with every EKS cluster: the VPC CNI (pod networking), CoreDNS (cluster DNS), and kube-proxy (Service routing). eksctl installs baseline versions automatically, but AWS regularly ships updated builds tied to each Kubernetes minor version, and letting these drift out of sync with your control plane is a common source of upgrade failures later. Check and update them as managed add-ons rather than letting eksctl-installed defaults sit untouched.

aws eks describe-addon-versions --kubernetes-version 1.36 \
  --addon-name vpc-cni --query 'addons[].addonVersions[0].addonVersion'

aws eks update-addon --cluster-name shattered-demo \
  --addon-name vpc-cni --resolve-conflicts OVERWRITE

aws eks update-addon --cluster-name shattered-demo \
  --addon-name coredns --resolve-conflicts OVERWRITE

kubectl get pods -n kube-system

Add the Amazon EBS CSI driver as a fourth add-on if any of your workloads need persistent volume claims, since EKS does not install it by default and pods stuck in Pending with unbound PVCs are one of the most common early confusions for people testing stateful workloads on a new cluster.

Step 10: Configure EKS Pod Identity for IAM Access

Pods that need to call other AWS services, an S3 bucket or a DynamoDB table, for example, need IAM credentials without you baking access keys into container images. AWS’s newer mechanism for this is EKS Pod Identity, which removes the need to manage an OIDC provider and trust policy by hand the way the older IAM Roles for Service Accounts (IRSA) pattern required. Install the Pod Identity Agent add-on, then create an association between a Kubernetes service account and an IAM role.

aws eks create-addon --cluster-name shattered-demo \
  --addon-name eks-pod-identity-agent

kubectl create serviceaccount app-sa -n default

aws eks create-pod-identity-association \
  --cluster-name shattered-demo \
  --namespace default \
  --service-account app-sa \
  --role-arn arn:aws:iam::111122223333:role/eks-demo-app-role

Reference serviceAccountName: app-sa in any pod spec that needs those AWS permissions, and the credentials are injected automatically at runtime. IRSA still works and AWS continues to support it, but for new clusters Pod Identity is the simpler path: fewer moving parts, no per-cluster OIDC provider to create, and associations you can update independently of redeploying workloads. If you are migrating an existing cluster off IRSA rather than starting fresh, you can run both mechanisms side by side during the transition; a pod only picks up Pod Identity credentials if an association exists for its service account, so nothing breaks for workloads you have not migrated yet.

Step 11: Deploy and Expose a Sample Workload

With the cluster, node group, and IAM wiring in place, deploy something real to confirm end-to-end networking works. A simple NGINX deployment exposed through a LoadBalancer Service is enough to prove pod scheduling, Service routing, and AWS load balancer provisioning are all functioning together.

kubectl create deployment demo-app --image=nginx:1.27 --replicas=2
kubectl expose deployment demo-app --type=LoadBalancer --port=80

kubectl get svc demo-app
# NAME       TYPE           CLUSTER-IP      EXTERNAL-IP                              PORT(S)
# demo-app   LoadBalancer   10.100.201.44   a1b2c3d4-1234.us-east-1.elb.amazonaws.com   80:31842/TCP

curl -s -o /dev/null -w "%{http_code}\n" http://a1b2c3d4-1234.us-east-1.elb.amazonaws.com
# 200

The EXTERNAL-IP field usually takes two to four minutes to populate as AWS provisions a Classic or Network Load Balancer behind the scenes. If it stays <pending> much longer than that, it is almost always the subnet tagging issue described in Step 5, not a problem with your deployment itself.

Step 12: Add Monitoring, Logging, and Cost Visibility

A cluster you cannot observe is a cluster you will debug blind at 2 a.m. Enable EKS control plane logging so API server, audit, and scheduler logs flow to CloudWatch, and install metrics-server so kubectl top and horizontal pod autoscaling both have data to work with.

aws eks update-cluster-config --name shattered-demo \
  --logging '{"clusterLogging":[{"types":["api","audit","scheduler"],"enabled":true}]}'

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

kubectl top nodes
# NAME                             CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
# ip-192-168-45-201.ec2.internal   142m         7%     612Mi           16%
# ip-192-168-78-114.ec2.internal   128m         6%     598Mi           15%

For cost visibility specifically, an EKS control plane on standard support is a flat $0.10 per cluster-hour regardless of workload size, but that figure jumps to $0.60 per cluster-hour once a Kubernetes version ages into extended support, a six-fold increase that catches teams off guard when they let clusters sit on old versions. If cost tracking across namespaces and teams matters to you, our Kubecost setup guide covers allocating that spend down to the workload level.

Control plane logging is not free once enabled, either. CloudWatch charges standard ingestion and storage rates for whatever log types you turn on, and audit logs in particular can get noisy on a busy cluster since every API request generates an entry. Start with api and audit enabled, watch your CloudWatch bill for a week, and add scheduler, authenticator, or controllerManager logging only if you actually need the extra visibility for debugging. Turning on all five log types by default on a cluster you are just testing is a common way to get an unpleasant CloudWatch surprise at the end of the month.

EKS Kubernetes Version Support Tiers

EKS does not support every Kubernetes version forever. AWS guarantees a minimum of four production-ready versions at any given time, moving each one through a standard support window followed by an optional extended support window before it is fully retired, a lifecycle documented in full on the EKS Kubernetes version lifecycle page. Here is where the versions relevant to an August 2026 cluster stand.

Kubernetes VersionEKS Release DateStandard Support EndsExtended Support Ends
1.36June 2, 2026August 2, 2027August 2, 2028
1.33May 29, 2025July 29, 2026July 29, 2027
1.31September 26, 2024November 26, 2025November 26, 2026
1.30 and earlierBefore mid-2024PassedExtended support only

Pin your cluster to 1.36 for new production work today. Versions already past their standard support end date still function but cost more per hour, and staying two or three minors behind current makes your eventual upgrade path longer and riskier. If a CVE wave hits an older supported version the way it recently did with Kubernetes 1.37’s breaking changes, you want to already be close to current, not scrambling to jump several versions at once under pressure.

Common Pitfalls When Setting Up EKS

  • Skipping subnet tags on a bring-your-own VPC. Without kubernetes.io/role/elb and kubernetes.io/role/internal-elb tags, LoadBalancer Services never get an external IP and the failure gives no obvious hint why.
  • Letting kubectl and the control plane drift apart. A kubectl client more than one minor version away from your cluster throws deprecation warnings on every command and can silently drop new API fields.
  • Using default node instance types for real workloads. A t3.medium is fine for testing but will hit CPU credit exhaustion under sustained load, causing throttling that looks like a networking problem at first.
  • Forgetting to update managed add-ons after a version upgrade. The VPC CNI, CoreDNS, and kube-proxy versions eksctl installs at cluster creation do not update themselves; stale add-ons are a leading cause of failed control plane upgrades.
  • Never rotating out of extended support. Sitting on an old Kubernetes version to avoid an upgrade quietly sextuples your control plane bill from $0.10 to $0.60 per cluster-hour.
  • Granting overly broad IAM policies and never revisiting them. The wide-open policy in Step 4 is fine for a tutorial sandbox; carrying it into production is how a single compromised pod becomes an account-wide incident.

Troubleshooting: 8 Common EKS Errors and Fixes

Even a clean tutorial run hits friction somewhere. Here are the errors most people run into, and what actually fixes each one.

  • Nodes stuck in NotReady. Usually a VPC CNI issue. Run kubectl describe node <name> and check for IP address exhaustion in the subnet; the CNI cannot assign pod IPs if the subnet’s available range is used up.
  • “Unauthorized” errors from kubectl after cluster creation succeeds. Your kubeconfig points at a different AWS identity than the one that created the cluster. Re-run aws eks update-kubeconfig and confirm with aws sts get-caller-identity that you are the expected principal.
  • eksctl create cluster fails with a CloudFormation ROLLBACK_COMPLETE. Check the CloudFormation console for the specific failed resource; the eksctl CLI output truncates the real error more often than not.
  • LoadBalancer Service stuck at <pending> indefinitely. Confirm subnet tags from Step 5, and check that your IAM role has permission to create Elastic Load Balancers.
  • Pods stuck Pending with “Insufficient cpu”. Your node group is out of capacity. Scale it up with eksctl scale nodegroup or add a larger instance type node group.
  • ImagePullBackOff on a private ECR image. The node instance role is missing AmazonEC2ContainerRegistryReadOnly. Attach it, then delete the pod to force a fresh pull attempt.
  • PersistentVolumeClaim stuck Pending. The EBS CSI driver add-on is not installed. It does not ship by default on new clusters and must be added explicitly.
  • Pod Identity association created but pod still gets AccessDenied. The service account name in the pod spec does not match the one in the association exactly, or the IAM role’s trust policy has not propagated yet. Wait 60 seconds and retry before assuming it is broken.

Advanced Tips: Autoscaling, Auto Mode, and Cost Control

Once your base cluster works, three things separate a hobby setup from something you’d trust with production traffic. First, add horizontal pod autoscaling so workloads scale with real demand instead of a fixed replica count.

kubectl autoscale deployment demo-app --cpu-percent=70 --min=2 --max=8

kubectl get hpa
# NAME       REFERENCE             TARGETS   MINPODS   MAXPODS   REPLICAS
# demo-app   Deployment/demo-app   12%/70%   2         8         2

Second, consider EKS Auto Mode instead of managing node groups yourself if your priority is less operational overhead. Auto Mode handles node provisioning, scaling, and lifecycle management automatically, at a compute surcharge of roughly 10-12% over standard EC2 on-demand pricing according to AWS’s published Auto Mode pricing structure. That trade makes sense for teams without dedicated platform engineers; it is usually not worth it if you already run Cluster Autoscaler or Karpenter well.

Third, treat the control plane pricing tiers as a real lever, not just a flat fee. AWS offers scaling tiers beyond the base rate for clusters that need a larger API server footprint under heavy load.

Control Plane TierPrice per Cluster-HourApproximate Monthly Cost
Standard support$0.10~$73
Extended support$0.60~$438
XL scaling tier$1.65~$1,205
2XL scaling tier$3.40~$2,482
4XL scaling tier$6.90~$5,037

Most workloads never need above the base standard-support tier; the scaling tiers exist for clusters running thousands of nodes or extremely high API request rates. Check your tier before assuming a cost spike is a mistake in your bill.

The Complete Working Project

Here is everything from this tutorial assembled into one reusable project: the cluster definition, the deployment, and the exposing service. Save these as three files and you have a repeatable, version-controlled EKS setup you can hand to a teammate or check into Git.

# cluster.yaml – full production-shaped config
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: shattered-demo
  region: us-east-1
  version: "1.36"
availabilityZones: [us-east-1a, us-east-1b]
managedNodeGroups:
  - name: ng-standard
    instanceType: t3.medium
    minSize: 2
    maxSize: 4
    desiredCapacity: 2
    volumeSize: 20
    privateNetworking: true
iam:
  withOIDC: true
cloudWatch:
  clusterLogging:
    enableTypes: ["api", "audit", "scheduler"]
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
spec:
  replicas: 2
  selector:
    matchLabels: {app: demo-app}
  template:
    metadata:
      labels: {app: demo-app}
    spec:
      serviceAccountName: app-sa
      containers:
        - name: nginx
          image: nginx:1.27
          resources:
            requests: {cpu: "100m", memory: "128Mi"}
            limits: {cpu: "250m", memory: "256Mi"}
---
apiVersion: v1
kind: Service
metadata:
  name: demo-app
spec:
  type: LoadBalancer
  selector: {app: demo-app}
  ports:
    - port: 80
      targetPort: 80

Apply the cluster config first, then the workload manifest: eksctl create cluster -f cluster.yaml followed by kubectl apply -f deployment.yaml. From a blank AWS account, that is the entire path to a running, internet-reachable, autoscaling-ready application on EKS.

When you are done experimenting, tear it all down to stop the hourly billing: eksctl delete cluster --name shattered-demo. This removes the control plane, node groups, and the VPC eksctl created, though it will not remove a LoadBalancer that was manually created outside of a Service definition, so double-check the EC2 console afterward.

How AWS EKS Compares to Other Kubernetes Options

If you are only now deciding whether EKS is the right managed Kubernetes platform, it is worth a quick sanity check before you commit further engineering time. Google’s GKE has taken roughly 40% share of managed Kubernetes deployments by some measures, and AWS’s own EKS control plane pricing sits well above ECS’s $0 control plane fee, a gap we broke down in detail in our EKS vs AKS vs GKE comparison. EKS still wins when a team is already deep in AWS-specific services like IAM, VPC peering, or Bedrock and wants Kubernetes to plug directly into that ecosystem rather than treating cloud provider as an afterthought.

That said, the platform choice matters less than most teams assume once you get past the first cluster. The commands in this tutorial (eksctl config files, kubectl manifests, standard Kubernetes objects) port to AKS and GKE with only the AWS-specific pieces changed: IAM becomes Azure AD or Google IAM, and the node group syntax swaps for the target platform’s equivalent. If you are choosing EKS mainly because your organization already runs on AWS, that is a perfectly good reason and this tutorial gets you a working cluster either way. If you are choosing it because you assume Kubernetes fundamentals will transfer elsewhere, that assumption is correct, and it is one of the stronger arguments for learning Kubernetes concepts properly rather than memorizing EKS-specific shortcuts.

Security posture is also worth a second look once your cluster is live. Container and cluster hardening is a separate discipline from getting a cluster running in the first place, covering image scanning, pod security standards, and network policies. Our container security hardening guide is the natural next stop once this tutorial’s cluster is up and you are ready to lock it down before pointing real traffic at it. If your workloads are latency-sensitive and you are weighing serverless alternatives to a persistent cluster, our AWS Lambda serverless tutorial covers the opposite end of that spectrum.

Frequently Asked Questions

How long does it take to set up an EKS cluster from scratch?
Following this tutorial end to end, including tool installation, cluster creation, add-on configuration, and deploying a sample workload, takes about 90 minutes. Cluster creation itself is the longest single step, typically 15-25 minutes.

How much does an AWS EKS cluster cost per month?
The control plane alone costs $0.10 per cluster-hour on standard support, about $73 a month. Add EC2 costs for worker nodes on top; two t3.medium instances run roughly $60 more per month in us-east-1, bringing a minimal cluster to around $130-140 monthly before data transfer and load balancer charges.

What is the difference between EKS Pod Identity and IRSA?
Both let Kubernetes pods assume IAM roles without hardcoded credentials. IRSA (IAM Roles for Service Accounts) requires setting up an OIDC identity provider per cluster and configuring trust policies manually. EKS Pod Identity, the newer mechanism, removes that OIDC setup step and lets you create associations directly through the EKS API, making it simpler to manage across multiple clusters.

Do I need eksctl, or can I use the AWS Console instead?
The AWS Console works for creating a cluster, but eksctl’s YAML-driven approach is far easier to version-control, review, and reproduce across environments. Most teams use the console for a first exploratory look and switch to eksctl or Terraform for anything they intend to keep.

What Kubernetes version should I use for a new EKS cluster today?
Use 1.36, the newest version EKS currently supports as of August 2026. It has the longest runway before its standard support window ends, currently projected for August 2027.

Why is my LoadBalancer Service stuck in pending state?
This is almost always missing subnet tags on a custom VPC, or an IAM role that lacks permission to create Elastic Load Balancers. Check both before assuming the deployment itself is broken.

Is EKS Auto Mode worth using instead of managed node groups?
It depends on team size. Auto Mode adds roughly a 10-12% compute surcharge in exchange for automatic node provisioning and lifecycle management. Teams without dedicated platform engineers often find that trade worthwhile; teams already running Cluster Autoscaler or Karpenter effectively usually do not need it.

How do I delete an EKS cluster when I’m done testing?
Run eksctl delete cluster --name <cluster-name>. This removes the control plane, node groups, and any VPC that eksctl created for the cluster. Manually check the EC2 and VPC consoles afterward for any load balancers or resources created outside of eksctl’s management.