Kubernetes EKS

Quick Start: EKS with Classic Load Balancer

Minimal setup for deploying nginx on EKS with internet-facing load balancer in EU (Ireland).

Prerequisites

  • AWS Account with admin access
  • AWS CLI installed and configured
  • kubectl installed (verify with kubectl version --client)

Step 1: Create EKS Cluster (AWS Console)

1.1 Create Cluster with Auto Mode

  1. Go to EKS Console
  2. Click Create cluster
  3. Select Quick configuration (default)
  4. Cluster name: my-cluster
  5. Kubernetes version: Latest (e.g., 1.34)

1.2 Configure IAM Roles

  1. Cluster IAM role: Click Create recommended role
    • Creates AmazonEKSAutoClusterRole
    • Click refresh icon if needed
  2. Node IAM role: Click Create recommended role
    • Creates AmazonEKSAutoNodeRole
    • Click refresh icon if needed

1.3 Configure Networking

  1. VPC: Click Create VPC

    This opens the VPC wizard. Configure these settings:

    • Resources to create: VPC and more (auto-selected)
    • Name tag auto-generation: Your cluster name is used
    • Number of Availability Zones: 2 (recommended)
    • Number of public subnets: 2
    • Number of private subnets: 2
    • NAT gateways: 1 per AZ (costs ~$35/month per NAT Gateway)
    • VPC endpoints: S3 Gateway (recommended to reduce NAT costs)

    Additional tags (scroll down):

    • Click Add new tag
    • Key: kubernetes.io/cluster/my-cluster
    • Value: shared
    • This tags ALL 4 subnets (both public and private)

    Click Create VPC, wait ~2 minutes, then return to EKS setup

  2. Back in EKS cluster creation:

    • VPC: Select the VPC you just created
    • Subnets: EKS auto-selects the 2 private subnets (correct!)
  3. Click Create cluster

  4. Wait ~10-15 minutes for Active status

Note: You tagged all 4 subnets with kubernetes.io/cluster/my-cluster = shared in the VPC wizard. Next, you need to add kubernetes.io/role/elb = 1 to the 2 public subnets only (for internet-facing load balancers).

1.4 Tag Public Subnets for Load Balancers (CRITICAL!)

Why this is critical: Kubernetes needs the kubernetes.io/role/elb = 1 tag on public subnets to know where to create internet-facing load balancers.

Steps (AWS Console):

  1. Go to VPC Console β†’ Subnets

  2. Find your public subnets:

    • Look for subnets with your VPC name (created in step 1.3)
    • Public subnets have “Auto-assign public IPv4 address” = Yes
    • You should have 2 public subnets (one per availability zone)
  3. Tag the first public subnet:

    • Select the first public subnet
    • Click Actions β†’ Manage tags
    • Click Add new tag
    • Key: kubernetes.io/role/elb
    • Value: 1
    • Click Save changes
  4. Tag the second public subnet:

    • Repeat step 3 for the second public subnet

Verify: Both public subnets should now have these tags:

  • kubernetes.io/cluster/my-cluster = shared βœ… (added in VPC wizard)
  • kubernetes.io/role/elb = 1 βœ… (just added)

Step 2: Connect to Cluster

aws eks update-kubeconfig --region eu-west-1 --name my-cluster
kubectl get nodes

Expected output: No resources found (EKS Auto Mode creates nodes when you deploy pods)

Step 3: Deploy Nginx

kubectl run my-nginx --image=nginx

Wait 1-2 minutes for the node to be created automatically, then:

kubectl get pods

Expected: Pod status changes from Pending β†’ ContainerCreating β†’ Running

Step 4: Expose with Load Balancer

kubectl expose pod my-nginx --type=LoadBalancer --port=80

kubectl annotate service my-nginx service.beta.kubernetes.io/aws-load-balancer-scheme=internet-facing

Why the annotation? By default, AWS tries to create an internal load balancer (only accessible within the VPC). This annotation tells AWS to create an internet-facing load balancer, which uses the public subnets you tagged in Step 1.4.

Wait 2-3 minutes for AWS to create the Classic Load Balancer:

kubectl get service my-nginx --watch

Press Ctrl+C when you see EXTERNAL-IP change from <pending> to a DNS name.

Get the Load Balancer URL:

Option 1 - AWS Console:

  1. Go to EC2 Console β†’ Load Balancers (in left menu)
  2. Find the load balancer (name starts with k8s-default-mynginx)
  3. Copy the DNS name (e.g., k8s-default-mynginx-abc123.eu-west-1.elb.amazonaws.com)
  4. Open in browser: http://DNS-NAME

Option 2 - kubectl:

kubectl get service my-nginx

Copy the EXTERNAL-IP value and open http://EXTERNAL-IP in your browser.

Expected: You should see the nginx welcome page! πŸŽ‰

Cleanup

Delete Kubernetes resources:

kubectl delete service my-nginx
kubectl delete pod my-nginx

Wait 5-10 minutes - EKS Auto Mode will automatically terminate the node when no pods are running.

Delete the cluster:

  1. Go to EKS Console
  2. Select your cluster β†’ Delete
  3. Type cluster name to confirm
  4. Wait ~5 minutes for deletion

Delete the VPC (if you created one):

  1. Go to VPC Console
  2. Find VPC named eks-vpc-xxx
  3. Select it β†’ Actions β†’ Delete VPC
  4. Deletes VPC, subnets, NAT Gateways, Internet Gateway automatically

Troubleshooting

EXTERNAL-IP stuck at <pending>

Check for errors:

kubectl describe service my-nginx

Common issues:

  1. “Failed build model due to unable to resolve at least one subnet”

    • The subnet tags are wrong
    • Run the subnet tag fix commands in Step 1.4 again
  2. “Evaluated 0 subnets”

    • Missing the internet-facing annotation
    • Add it: kubectl annotate service my-nginx service.beta.kubernetes.io/aws-load-balancer-scheme=internet-facing

Re-create service:

kubectl delete service my-nginx
kubectl expose pod my-nginx --type=LoadBalancer --port=80
kubectl annotate service my-nginx service.beta.kubernetes.io/aws-load-balancer-scheme=internet-facing

Pod stuck in Pending

Check pod status:

kubectl describe pod my-nginx

Common causes:

  • Node still provisioning (EKS Auto Mode takes 1-2 minutes)
  • Wait and check again: kubectl get pods --watch

Summary

What you built:

  1. EKS cluster with Auto Mode in EU (Ireland)
  2. VPC with 4 subnets (2 public, 2 private)
  3. Nginx pod running in private subnet
  4. Classic Load Balancer in public subnets
  5. Internet β†’ Load Balancer β†’ Pod flow

Key learnings:

  • EKS Auto Mode creates nodes automatically (no manual node groups!)
  • Public subnets need kubernetes.io/role/elb = 1 tag for load balancers
  • Private subnets should NOT have the elb tag
  • The wizard tags things wrong - you need to fix it manually

Total time: ~20 minutes

Total cost:

  • Control plane: $0.10/hour (~$73/month)
  • Nodes: Only when pods are running (Auto Mode!)
  • NAT Gateway: $0.048/hour (~$35/month)
  • Load Balancer: $0.027/hour (~$20/month)

πŸ’‘ Tip: Delete everything when not using to avoid charges!

Tools needed: kubectl only!


Happy Cluster! πŸš€