Skip to main content

Command Palette

Search for a command to run...

Configuring Kubernetes Ingress with Amazon EKS and ALB: A Comprehensive Guide

Detailed Instructions for Kubernetes Ingress Setup on EKS Using ALB

Updated
36 min read
Configuring Kubernetes Ingress with Amazon EKS and ALB: A Comprehensive Guide
A
Hi, I’m Abhishek Mishra — a passionate Cloud & DevOps Engineer in the making, certified by GUVI (IIT-M), with over 28+ IIT and Oracle certifications, AWS. I specialize in automating and securing cloud infrastructure using AWS, Terraform, Jenkins, Docker, and Kubernetes, with a strong focus on DevSecOps and real-world cloud deployment projects. 🧠 My mission is to bridge DevOps and Cybersecurity to build reliable, scalable, and secure cloud systems. 🧠 I share hands-on projects, cloud architecture guides, and DevOps insights to help others learn, grow, and build reliable systems. 📬 Let’s collaborate or connect: abhishekmishra09896@gmail.com

Introduction

In modern cloud-native architectures, efficiently managing traffic routing to multiple microservices while maintaining security, cost-efficiency, and high availability is crucial. This comprehensive guide walks you through building a production-ready Kubernetes Ingress implementation on Amazon EKS, leveraging the AWS Application Load Balancer (ALB) for intelligent traffic distribution.

Imagine a bustling city with thousands of vehicles navigating through its streets. Now, picture a single, intelligent traffic system that seamlessly directs each vehicle to its destination, avoiding congestion and ensuring smooth flow. This is exactly what a well-configured Kubernetes Ingress with Amazon EKS and ALB can do for your microservices architecture—efficiently managing traffic, enhancing security, and optimizing costs. Let's dive into how you can achieve this in your cloud environment.

What Makes This Project Special?

This isn't just another Kubernetes tutorial—it's a real-world, production-grade implementation that demonstrates:

Cost Optimization - Single ALB managing multiple services (saves ~70% on load balancer costs)
Enterprise Security - TLS/SSL encryption, IAM integration, and private networking
High Availability - Multi-AZ deployment with automatic failover
Scalability - Ready for auto-scaling and handles enterprise-level traffic
Infrastructure as Code - Fully declarative, version-controlled configuration

Who Is This For?

  • DevOps Engineers seeking hands-on AWS EKS experience

  • Cloud Architects designing scalable microservices architectures

  • Developers wanting to understand Kubernetes networking

  • SREs implementing production-ready infrastructure

Project Repository

GitHub: AWS EKS Kubernetes Ingress with ALB Routing


🎯 What Problem Are We Solving?

🤔 The Traditional Problem

Let's say you're Netflix and you have:

📱 A mobile app API
💻 A web application
🎮 A gaming service
📊 An analytics dashboard

Old Way (Expensive & Complex) ❌:

  • Each service gets its own load balancer

  • 4 services = 4 load balancers = 4× the cost

  • Managing 4 different DNS entries

  • 4 SSL certificates to maintain

New Way (Smart & Cost-Effective) ✅:

  • ONE intelligent load balancer

  • Routes traffic based on URLs

  • Single SSL certificate

  • Easy to manage

💡 Real-Life Example

Think of it like a smart pizza delivery system 🍕:

Without Ingress:

  • Customer calls → Direct line to specific pizza maker

  • Need separate phone numbers for: Cheese Pizza Guy, Pepperoni Guy, Veggie Guy

  • Expensive! Multiple phone lines, confusing for customers

With Ingress:

  • Customer calls ONE number → Smart receptionist listens to order

  • Receptionist routes to right pizza maker automatically

  • One phone bill, easy to remember, super organized!


Project Overview

The Problem We're Solving

Traditional Approach:

Service 1 → LoadBalancer 1 ($18/month) → Public IP 1
Service 2 → LoadBalancer 2 ($18/month) → Public IP 2
Service 3 → LoadBalancer 3 ($18/month) → Public IP 3

Total Cost: $54/month + complexity + management overhead

Our Solution:

All Services → Single ALB ($18/month) → One Public Endpoint
├── /iphone   → iPhone Service
├── /android  → Android Service
└── /         → Desktop Service

Total Cost: $18/month + simplified management + centralized SSL
Savings: ~67% reduction in load balancer costs

What You'll Build

By the end of this project, you'll have:

✅ An EKS Cluster spanning multiple availability zones (ap-south-1a, ap-south-1b)

✅ 4 Worker Nodes (t2.medium) distributed for high availability

✅ Single AWS ALB managing all three services

✅ Three different routing strategies: - Demo 1: Path-based routing (/iphone, /android, /) - Demo 2: HTTPS with TLS termination - Demo 3: Host-based routing with subdomains

✅ Custom domain integrated with Route 53

✅ SSL/TLS certificates from AWS Certificate Manager

✅ Secure IAM roles using IRSA


Architecture Deep Dive

🗺️ The Traffic Journey

🌍 Internet User
    ↓
🌐 Route 53 (DNS) - "Which website are you looking for?"
    ↓
⚖️ Application Load Balancer - "Where should I send you?"
    ↓
🎛️ Ingress Controller - "Traffic cop directing cars"
    ↓
📦 Kubernetes Services - "Store counters"
    ↓
🎯 Application Pods - "Actual workers serving customers"

High-Level Architecture Diagram

🚀 Kubernetes Multi-Service Architecture: A Complete Journey

🎯 Architecture Overview

This diagram illustrates a robust Kubernetes deployment on AWS, featuring three distinct services for iPhone, Android, and Desktop applications.

🌊 Traffic Flow & Components - Step by Step Journey

  1. 👤 User Entry Point - The Beginning

    • User: Abhishek Mishra enters the URL in his browser.

    • Connection: Secure entry from the Internet to AWS VPC.

  2. 🎯 Route 53 & Application Recovery Controller - The Traffic Manager

    • Route 53: Converts domain names to IP addresses with minimal latency.

    • Application Recovery Controller: Ensures high availability with automatic failover and continuous monitoring.

  3. ⚖️ Application Load Balancer (ALB) - The Traffic Cop

    • Distributes incoming traffic intelligently using path-based routing.

    • Supports millions of requests with no single point of failure.

    • Benefits include equal load distribution, auto-scaling, health checks, and SSL/TLS termination.

  4. 🚪 Ingress Controller - The Gatekeeper

    • Acts as the main entrance to the Kubernetes cluster.

    • Routes external traffic to internal services with path-based rules.

    • Think of it as a combination of airport security and GPS navigation.

  5. 📱💻🤖 Three Magical Services - Multi-Platform Magic

    • iPhone-SVC: Optimized for iOS users with two highly available pods.

    • Android-SVC: Tailored for Android with robust pods for reliability.

    • Desktop-SVC: Designed for web and desktop users with dedicated pods.

    • Each service has two pods for redundancy, load distribution, and high availability.

  6. 🔄 Deployment Component - The Update Manager

    • Features rolling updates, rollback capabilities, version control, and health monitoring.

    • Supports blue-green deployments for testing before switching.

  7. 🔐 AWS Certificate Manager (ACM) - The Security Guard

    • Manages SSL/TLS certificates for HTTPS encryption.

    • Provides free, auto-renewing certificates for secure communication.

  8. 🌍 Multi-AZ Deployment - The Safety Net

    • Nodes and pods are distributed across two availability zones for high availability and fault tolerance.

    • Ensures zero downtime and resilience against failures.

🎨 The Complete Journey - From Click to Response

  • User clicks the URL → DNS resolution via Route 53 → SSL handshake with ACM → Load balancing by ALB → Ingress Controller processes the request → Routes to the appropriate service based on the URL→ Pod processes the request → Response travels back to the user.
                        Internet Traffic
                              ↓
                   ┌──────────────────────┐
                   │   Route 53 (DNS)     │
                   │  abhimishra-devops   │
                   └──────────────────────┘
                              ↓
                   ┌──────────────────────┐
                   │  Application Load    │
                   │   Balancer (ALB)     │
                   │   Port: 80, 443      │
                   └──────────────────────┘
                              ↓
         ┌────────────────────────────────────────┐
         │  AWS Load Balancer Controller (v2.13)  │
         │  (Manages ALB via Kubernetes Ingress)  │
         └────────────────────────────────────────┘
                              ↓
                   Kubernetes Ingress
                              ↓
    ┌─────────────┬────────────────┬─────────────┐
    │   iPhone    │    Android     │   Desktop   │
    │   Service   │    Service     │   Service   │
    │ (ClusterIP) │  (ClusterIP)   │ (ClusterIP) │
    └─────────────┴────────────────┴─────────────┘
                              ↓
    ┌─────────────┬────────────────┬─────────────┐
    │ iPhone Pods │  Android Pods  │Desktop Pods │
    │  (Replicas) │   (Replicas)   │ (Replicas)  │
    └─────────────┴────────────────┴─────────────┘
         │    │           │    │         │    │
    ┌────┴────┴──────────┴────┴────────┴────┴────┐
    │         EKS Cluster (Multi-AZ)              │
    │    ap-south-1a    │    ap-south-1b         │
    │  2 Worker Nodes   │   2 Worker Nodes       │
    │  (t2.medium EC2)  │  (t2.medium EC2)       │
    └────────────────────────────────────────────┘

Traffic Flow Explained

Let me walk you through what happens when a user accesses your application:

Step 1: DNS Resolution

  • User types iphone.abhimishra-devops.com in browser

  • Route 53 resolves this to ALB's DNS name

  • Example: k8s-app1ns-abhishek-xxxxx.ap-south-1.elb.amazonaws.com

Step 2: ALB Processing

  • ALB receives HTTPS request on port 443

  • Performs TLS termination using ACM certificate

  • Checks routing rules based on hostname/path

Step 3: Ingress Controller Sync

  • AWS Load Balancer Controller continuously syncs Ingress resources

  • Updates ALB listener rules, target groups, and health checks

  • Ensures Kubernetes state matches AWS infrastructure

Step 4: Service Routing

  • Request forwarded to appropriate ClusterIP service

  • Service load-balances across healthy pod endpoints

  • Uses round-robin or least-connection algorithm

Step 5: Pod Response

  • Pod processes the request

  • Generates response

  • Returns through same path: Pod → Service → ALB → User

Key Components

Amazon EKS Cluster

I remember when I set up an EKS cluster for the first time, it took me a little time to understand the network configurations. But once I properly configured the subnets and security groups, everything started running smoothly.

Configuration:

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: Abhishek-ingress-demo
  region: ap-south-1
  version: "1.28"

availabilityZones:
  - ap-south-1a
  - ap-south-1b

managedNodeGroups:
  - name: ng-1
    instanceType: t2.medium
    desiredCapacity: 4
    minSize: 2
    maxSize: 6
    availabilityZones:
      - ap-south-1a
      - ap-south-1b
    volumeSize: 20
    volumeType: gp3
    privateNetworking: true
    iam:
      withAddonPolicies:
        autoScaler: true
        externalDNS: true
        certManager: true
        albIngress: true

Why These Settings?

  • Multi-AZ Deployment: Ensures high availability (if one AZ fails, other continues)

  • t2.medium Instances: Balanced CPU/memory for small-to-medium workloads

  • Private Networking: Worker nodes in private subnets for security

  • 4 Worker Nodes: 2 per AZ provides redundancy and load distribution

2. AWS Application Load Balancer

Specifications:

  • Type: Internet-facing Application Load Balancer

  • Listeners:

    • Port 80 (HTTP) → Redirects to 443

    • Port 443 (HTTPS) → Forwards to target groups

  • Target Type: IP-based (direct to pod IPs)

  • Health Checks: Configured per service

  • Availability Zones: Spans ap-south-1a and ap-south-1b

ALB Configuration Details:

# Ingress annotations configure ALB behavior
annotations:
  # Internet-facing ALB
  alb.ingress.kubernetes.io/scheme: internet-facing

  # IP mode for direct pod routing
  alb.ingress.kubernetes.io/target-type: ip

  # Custom ALB name
  alb.ingress.kubernetes.io/load-balancer-name: abhishek-demo-alb

  # SSL certificate from ACM
  alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:...

  # Enable both HTTP and HTTPS
  alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'

  # Redirect HTTP to HTTPS
  alb.ingress.kubernetes.io/ssl-redirect: '443'

3. Target Groups

The ALB creates three target groups (one per service):

Target Group 1: iPhone Service

  • Name: k8s-app1ns-iphonese-xxxxx

  • Port: 80

  • Protocol: HTTP

  • Target Type: IP

  • Health Check Path: /

  • Healthy Threshold: 2

  • Unhealthy Threshold: 2

  • Timeout: 5 seconds

  • Interval: 15 seconds

  • Registered Targets: Pod IPs across both AZs

Why IP Target Type?

  • Direct routing to pod IPs (no extra hop through node)

  • Better performance and lower latency

  • Automatic registration/deregistration as pods scale

  • Native Kubernetes networking integration

4. OIDC & IRSA Integration

What is OIDC?

OpenID Connect (OIDC) lets your Kubernetes pods securely access AWS services without needing to store access keys. Instead of hardcoding credentials, the pods can temporarily take on IAM roles making things safer and easier to manage.

Implementation:

# EKS cluster automatically creates OIDC identity provider
# Format: https://oidc.eks.REGION.amazonaws.com/id/CLUSTER_ID

# Example OIDC URL:
https://oidc.eks.ap-south-1.amazonaws.com/id/A1B2C3D4E5F6...

IRSA (IAM Roles for Service Accounts) Setup:

# Create IAM role with trust policy for OIDC
eksctl create iamserviceaccount \
  --cluster=Abhishek-ingress-demo \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --attach-policy-arn=arn:aws:iam::ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \
  --approve \
  --region=ap-south-1

Trust Relationship:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.ap-south-1.amazonaws.com/id/CLUSTER_ID"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.ap-south-1.amazonaws.com/id/CLUSTER_ID:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller"
        }
      }
    }
  ]
}

Benefits:

✅ No hardcoded AWS credentials in pods
✅ Automatic credential rotation
✅ Fine-grained permissions per service account
✅ Audit trail in CloudTrail
✅ Principle of least privilege

5. AWS Load Balancer Controller

What Does It Do?

The AWS Load Balancer Controller is a Kubernetes controller that manages AWS Elastic Load Balancers for a Kubernetes cluster.

Key Responsibilities:

  • Watches Ingress resources - Monitors for new/updated/deleted Ingress objects

  • Creates ALBs - Automatically provisions Application Load Balancers

  • Configures listener rules - Sets up path-based and host-based routing

  • Manages target groups - Registers/deregisters pod IPs dynamically

  • Updates security groups - Ensures proper network access

  • Implements health checks - Configures ALB health check parameters

Installation via Helm:

# Add EKS Helm repository
helm repo add eks https://aws.github.io/eks-charts
helm repo update

# Install controller
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=Abhishek-ingress-demo \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller \
  --set region=ap-south-1 \
  --set vpcId=vpc-xxxxx \
  --version 1.13.0

Verification:

kubectl get deployment -n kube-system aws-load-balancer-controller

# Expected output:
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           5m

Prerequisites

🛠️ Technology Stack Breakdown

CategoryTechnologyReal-Life AnalogyWhy We Use It
🏗️ OrchestrationAmazon EKSShopping Mall BuildingManaged infrastructure
💻 ComputeEC2 t3.mediumStore SpacesWhere apps actually run
⚖️ Load BalancingAWS ALBReception DeskDistributes traffic smartly
🎛️ IngressLB ControllerTraffic CopConnects K8s to AWS
🌐 DNSRoute 53GPS SystemConverts names to addresses
🔒 SecurityACMID Badge SystemSSL certificates
🎫 PermissionsIRSAKey Card SystemSecure access control
📝 IaCeksctlConstruction BlueprintAutomate everything

Required Tools & Versions

ToolVersionInstallation Link
AWS CLIv2.xInstall Guide
kubectlv1.28+Install Guide
eksctlv0.160+Install Guide
Helmv3.xInstall Guide

AWS Requirements

1. AWS Account Setup:

# Configure AWS CLI
aws configure

# Verify configuration
aws sts get-caller-identity

Expected Output:

{
    "UserId": "AIDAXXXXXXXXXXXXXXXXX",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/your-username"
}

2. Required IAM Permissions:

Your AWS user/role needs permissions for:

  • EKS cluster creation and management

  • EC2 instance provisioning and networking

  • IAM role and policy management

  • Certificate Manager certificate provisioning

  • Route 53 hosted zone management

  • Elastic Load Balancing operations

3. Route 53 Hosted Zone:

# Create hosted zone (if not exists)
aws route53 create-hosted-zone \
  --name abhimishra-devops.com \
  --caller-reference $(date +%s)

# Note the Name Servers and update your domain registrar

4. ACM Certificate:

# Request certificate
aws acm request-certificate \
  --domain-name abhimishra-devops.com \
  --subject-alternative-names *.abhimishra-devops.com \
  --validation-method DNS \
  --region ap-south-1

# Add CNAME records to Route 53 for validation
# Wait for status: ISSUED

Knowledge Prerequisites

  • Basic Kubernetes Concepts: Pods, Services, Deployments, Namespaces, ConfigMaps, Secrets

  • AWS Services Familiarity: VPC, Subnets, Security Groups, EC2 instances, IAM roles and policies

  • Basic networking concepts

  • Command Line Comfort: Bash/Shell scripting, YAML syntax, Git basics


Implementation Guide

Phase 1: EKS Cluster Provisioning

Step 1.1: Create EKS Configuration File

Create eks-config.yaml:

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: Abhishek-ingress-demo
  region: ap-south-1
  version: "1.28"

# VPC Configuration
vpc:
  cidr: 10.0.0.0/16
  nat:
    gateway: Single  # Use HighlyAvailable for production
  clusterEndpoints:
    publicAccess: true
    privateAccess: true

# IAM OIDC Provider (required for IRSA)
iam:
  withOIDC: true

# Managed Node Group
managedNodeGroups:
  - name: ng-1
    instanceType: t2.medium
    desiredCapacity: 4
    minSize: 2
    maxSize: 6
    volumeSize: 20
    volumeType: gp3
    availabilityZones:
      - ap-south-1a
      - ap-south-1b
    privateNetworking: true
    labels:
      role: worker
      environment: production
    tags:
      k8s.io/cluster-autoscaler/enabled: "true"
      k8s.io/cluster-autoscaler/Abhishek-ingress-demo: "owned"
    iam:
      withAddonPolicies:
        autoScaler: true
        externalDNS: true
        certManager: true
        albIngress: true
        cloudWatch: true

# CloudWatch Logging
cloudWatch:
  clusterLogging:
    enableTypes:
      - api
      - audit
      - authenticator
      - controllerManager
      - scheduler

Step 1.2: Deploy the Cluster

# Create cluster (takes ~15-20 minutes)
eksctl create cluster -f eks-config.yaml

# Monitor creation progress
eksctl utils describe-stacks \
  --region=ap-south-1 \
  --cluster=Abhishek-ingress-demo

Step 1.3: Verify Cluster Creation

# Update kubeconfig
aws eks update-kubeconfig \
  --region ap-south-1 \
  --name Abhishek-ingress-demo

# Check nodes
kubectl get nodes -o wide

# Expected output:
NAME                                          STATUS   ROLES    AGE   VERSION
ip-10-0-1-100.ap-south-1.compute.internal    Ready    <none>   5m    v1.28.x
ip-10-0-1-101.ap-south-1.compute.internal    Ready    <none>   5m    v1.28.x
ip-10-0-2-100.ap-south-1.compute.internal    Ready    <none>   5m    v1.28.x
ip-10-0-2-101.ap-south-1.compute.internal    Ready    <none>   5m    v1.28.x

# Verify node labels
kubectl get nodes --show-labels | grep topology

Cluster Architecture Created:

VPC: 10.0.0.0/16
├── ap-south-1a
│   ├── Public Subnet: 10.0.0.0/24 (NAT Gateway, ALB)
│   ├── Private Subnet: 10.0.1.0/24 (Worker Nodes)
│   └── 2 Worker Nodes (t2.medium)
└── ap-south-1b
    ├── Public Subnet: 10.0.2.0/24 (ALB)
    ├── Private Subnet: 10.0.3.0/24 (Worker Nodes)
    └── 2 Worker Nodes (t2.medium)

Phase 2: IAM and Load Balancer Controller Setup

Step 2.1: Download IAM Policy

# Download official IAM policy
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.13.3/docs/install/iam_policy.json

# Review policy (optional)
cat iam_policy.json | jq

Key Permissions in Policy:

  • elasticloadbalancing:* - Manage ALBs and target groups

  • ec2:DescribeInstances - Discover worker nodes

  • ec2:DescribeSecurityGroups - Manage security groups

  • iam:CreateServiceLinkedRole - Create service-linked roles

  • wafv2:* - WAF integration (optional)

Step 2.2: Create IAM Policy in AWS

# Create policy
aws iam create-policy \
  --policy-name AWSLoadBalancerControllerIAMPolicy \
  --policy-document file://iam_policy.json

# Save the policy ARN from output
# Example: arn:aws:iam::123456789012:policy/AWSLoadBalancerControllerIAMPolicy

Step 2.3: Create IAM Service Account with IRSA

# Replace ACCOUNT_ID with your AWS account ID
eksctl create iamserviceaccount \
  --cluster=Abhishek-ingress-demo \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --attach-policy-arn=arn:aws:iam::<ACCOUNT_ID>:policy/AWSLoadBalancerControllerIAMPolicy \
  --override-existing-serviceaccounts \
  --region=ap-south-1 \
  --approve

Step 2.4: Verify Service Account

# Check service account
kubectl get sa -n kube-system | grep aws-load-balancer

# Describe service account (verify IAM role annotation)
kubectl describe sa aws-load-balancer-controller -n kube-system

Expected Annotation:

Annotations:  eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/eksctl-Abhishek-ingress-demo-addon-iamserviceaccount-kube-system-aws-load-balancer-controller

Step 2.5: Install AWS Load Balancer Controller

# Add EKS Helm chart repository
helm repo add eks https://aws.github.io/eks-charts
helm repo update

# Search for chart
helm search repo eks/aws-load-balancer-controller

# Install controller
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=Abhishek-ingress-demo \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller \
  --set region=ap-south-1 \
  --set vpcId=$(aws eks describe-cluster --name Abhishek-ingress-demo --query 'cluster.resourcesVpcConfig.vpcId' --output text) \
  --version 1.13.0

# Wait for deployment
kubectl rollout status deployment aws-load-balancer-controller -n kube-system

Step 2.6: Verify Controller Installation

# Check deployment
kubectl get deployment -n kube-system aws-load-balancer-controller

# Expected:
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           2m

# Check controller logs
kubectl logs -n kube-system deployment/aws-load-balancer-controller --tail=50

# Look for successful startup messages

Phase 3: Deploy Application Services

Step 3.1: Create Namespace

# 01-ns.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: app1-ns
  labels:
    name: app1-ns
    environment: production
kubectl apply -f demo-01/01-ns.yaml

# Set default namespace
kubectl config set-context --current --namespace=app1-ns

Step 3.2: Deploy iPhone Service

# 02-iphone.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: iphone-deployment
  namespace: app1-ns
  labels:
    app: iphone
spec:
  replicas: 2
  selector:
    matchLabels:
      app: iphone
  template:
    metadata:
      labels:
        app: iphone
    spec:
      containers:
      - name: iphone-app
        image: stacksimplify/kubenginx:1.0.0
        ports:
        - containerPort: 80
          protocol: TCP
        env:
        - name: APP_NAME
          value: "iPhone Application"
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: iphone-service
  namespace: app1-ns
  labels:
    app: iphone
spec:
  type: ClusterIP
  selector:
    app: iphone
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
kubectl apply -f demo-01/02-iphone.yaml

Step 3.3: Deploy Android Service

# 03-android.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: android-deployment
  namespace: app1-ns
  labels:
    app: android
spec:
  replicas: 2
  selector:
    matchLabels:
      app: android
  template:
    metadata:
      labels:
        app: android
    spec:
      containers:
      - name: android-app
        image: stacksimplify/kubenginx:2.0.0
        ports:
        - containerPort: 80
        env:
        - name: APP_NAME
          value: "Android Application"
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
  name: android-service
  namespace: app1-ns
spec:
  type: ClusterIP
  selector:
    app: android
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
kubectl apply -f demo-01/03-android.yaml

Step 3.4: Deploy Desktop Service

# 04-desktop.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: desktop-deployment
  namespace: app1-ns
  labels:
    app: desktop
spec:
  replicas: 2
  selector:
    matchLabels:
      app: desktop
  template:
    metadata:
      labels:
        app: desktop
    spec:
      containers:
      - name: desktop-app
        image: stacksimplify/kubenginx:3.0.0
        ports:
        - containerPort: 80
        env:
        - name: APP_NAME
          value: "Desktop Application"
---
apiVersion: v1
kind: Service
metadata:
  name: desktop-service
  namespace: app1-ns
spec:
  type: ClusterIP
  selector:
    app: desktop
  ports:
  - port: 80
    targetPort: 80
kubectl apply -f demo-01/04-desktop.yaml

Step 3.5: Verify All Deployments

# Check all pods
kubectl get pods -n app1-ns -o wide

# Expected output:
NAME                                  READY   STATUS    NODE
iphone-deployment-xxxxx-yyyyy        1/1     Running   ip-10-0-1-100...
iphone-deployment-xxxxx-zzzzz        1/1     Running   ip-10-0-2-100...
android-deployment-xxxxx-yyyyy       1/1     Running   ip-10-0-1-101...
android-deployment-xxxxx-zzzzz       1/1     Running   ip-10-0-2-101...
desktop-deployment-xxxxx-yyyyy       1/1     Running   ip-10-0-1-100...
desktop-deployment-xxxxx-zzzzz       1/1     Running   ip-10-0-2-100...

# Check services
kubectl get svc -n app1-ns

# Check endpoints
kubectl get endpoints -n app1-ns

Three Routing Strategies Explained

Demo 1: Path-Based Routing

Use Case: Route different URL paths to different microservices using a single domain.

Example Scenario:

abhimishra-devops.com/iphone   → iPhone App
abhimishra-devops.com/android  → Android App
abhimishra-devops.com/         → Desktop App (default)

Ingress Configuration

# 05-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: abhishek-ingress-demo1
  namespace: app1-ns
  annotations:
    # ALB Configuration
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/load-balancer-name: abhishek-demo-alb

    # Health Check Settings
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
    alb.ingress.kubernetes.io/healthcheck-port: traffic-port
    alb.ingress.kubernetes.io/healthcheck-path: /
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: '15'
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '5'
    alb.ingress.kubernetes.io/healthy-threshold-count: '2'
    alb.ingress.kubernetes.io/unhealthy-threshold-count: '2'

    # Tags
    alb.ingress.kubernetes.io/tags: Environment=production,Project=ingress-demo

spec:
  ingressClassName: alb
  rules:
  - http:
      paths:
      # iPhone Service - matches /iphone and /iphone/*
      - path: /iphone
        pathType: Prefix
        backend:
          service:
            name: iphone-service
            port:
              number: 80

      # Android Service - matches /android and /android/*
      - path: /android
        pathType: Prefix
        backend:
          service:
            name: android-service
            port:
              number: 80

      # Desktop Service - default path, matches everything else
      - path: /
        pathType: Prefix
        backend:
          service:
            name: desktop-service
            port:
              number: 80

Deploy Path-Based Ingress

# Apply Ingress configuration
kubectl apply -f demo-01/05-ingress.yaml

# Wait for ALB creation (2-3 minutes)
kubectl get ingress -n app1-ns -w

# Check Ingress status
kubectl describe ingress abhishek-ingress-demo1 -n app1-ns

Get ALB DNS Name

# Extract ALB DNS
ALB_DNS=$(kubectl get ingress abhishek-ingress-demo1 -n app1-ns -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')

echo "ALB DNS: $ALB_DNS"

# Example output:
# k8s-app1ns-abhishek-xxxxxxxxxxxxx.ap-south-1.elb.amazonaws.com

Test Path-Based Routing

# Test iPhone service
curl http://$ALB_DNS/iphone
# Output: iPhone Application Page

# Test Android service
curl http://$ALB_DNS/android
# Output: Android Application Page

# Test Desktop service (default)
curl http://$ALB_DNS/
# Output: Desktop Application Page

# Test with verbose output
curl -v http://$ALB_DNS/iphone

How Path Matching Works

  • Prefix PathType: Matches URL path and all sub-paths

    • /iphone matches: /iphone, /iphone/, /iphone/details, etc.

    • /android matches: /android, /android/app, /android/store, etc.

  • Path Priority: Kubernetes evaluates paths from most specific to least specific

    • Longer paths evaluated first

    • /iphone evaluated before /

  • Default Route: Path / catches all unmatched requests

Real-World Applications

example.com/api/v1      → API v1 microservice
example.com/api/v2      → API v2 microservice
example.com/admin       → Admin dashboard
example.com/docs        → Documentation site
example.com/            → Main frontend application

Demo 2: TLS Termination with HTTPS

Use Case: Secure your applications with SSL/TLS certificates for encrypted HTTPS traffic.

Prerequisites: Create ACM Certificate

Step 1: Request Certificate

# Request certificate for domain and wildcard subdomain
aws acm request-certificate \
  --domain-name abhimishra-devops.com \
  --subject-alternative-names *.abhimishra-devops.com \
  --validation-method DNS \
  --region ap-south-1

# Note the CertificateArn from output

Step 2: Validate Domain

# Get validation records
aws acm describe-certificate \
  --certificate-arn arn:aws:acm:ap-south-1:ACCOUNT_ID:certificate/CERT_ID \
  --region ap-south-1

# Create CNAME records in Route 53 for validation
# ACM provides Name and Value for CNAME record

Step 3: Wait for Certificate Issuance

# Check certificate status
aws acm describe-certificate \
  --certificate-arn arn:aws:acm:ap-south-1:ACCOUNT_ID:certificate/CERT_ID \
  --query 'Certificate.Status' \
  --output text

# Wait until output shows: ISSUED

Ingress with TLS Configuration

# 05-ingress-tls.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: abhishek-ingress-demo2
  namespace: app1-ns
  annotations:
    # ALB Configuration
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/load-balancer-name: abhishek-demo-alb-tls

    # SSL/TLS Configuration
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-south-1:ACCOUNT_ID:certificate/CERT_ID
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: '443'
    alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS-1-2-2017-01

    # Security Headers
    alb.ingress.kubernetes.io/actions.ssl-redirect: |
      {
        "Type": "redirect",
        "RedirectConfig": {
          "Protocol": "HTTPS",
          "Port": "443",
          "StatusCode": "HTTP_301"
        }
      }

spec:
  ingressClassName: alb
  rules:
  - http:
      paths:
      - path: /iphone
        pathType: Prefix
        backend:
          service:
            name: iphone-service
            port:
              number: 80
      - path: /android
        pathType: Prefix
        backend:
          service:
            name: android-service
            port:
              number: 80
      - path: /
        pathType: Prefix
        backend:
          service:
            name: desktop-service
            port:
              number: 80

Deploy TLS-Enabled Ingress

# First, delete previous Ingress
kubectl delete ingress abhishek-ingress-demo1 -n app1-ns

# Apply TLS Ingress
kubectl apply -f demo-02/05-ingress-tls.yaml

# Wait for ALB update
kubectl get ingress -n app1-ns -w

Configure Route 53 DNS

# Get new ALB DNS
ALB_DNS=$(kubectl get ingress abhishek-ingress-demo2 -n app1-ns -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')

# Create A record (ALIAS) in Route 53
aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "abhimishra-devops.com",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "Z1234567890ABC",
          "DNSName": "'$ALB_DNS'",
          "EvaluateTargetHealth": true
        }
      }
    }]
  }'

Test HTTPS Access

# Test HTTPS endpoints
curl https://abhimishra-devops.com/iphone
curl https://abhimishra-devops.com/android
curl https://abhimishra-devops.com/

# Verify HTTP to HTTPS redirect
curl -I http://abhimishra-devops.com
# Should return: HTTP/1.1 301 Moved Permanently
# Location: https://abhimishra-devops.com/

# Test SSL certificate
openssl s_client -connect abhimishra-devops.com:443 -servername abhimishra-devops.com

What Happens with TLS Termination

  1. Client Request: Browser sends HTTPS request to abhimishra-devops.com

  2. DNS Resolution: Route 53 resolves to ALB

  3. TLS Handshake: ALB performs SSL/TLS handshake using ACM certificate

  4. Decryption: ALB decrypts HTTPS traffic

  5. Backend Communication: ALB sends HTTP (unencrypted) to pods

  6. Response Encryption: ALB encrypts response before sending to client

Benefits

✅ Offload encryption/decryption from application pods
✅ Centralized certificate management
✅ Automatic certificate renewal by ACM
✅ Better performance (ALB optimized for SSL/TLS)
✅ Compliance with security standards


Demo 3: Host-Based (Subdomain) Routing

Use Case: Route traffic to different services based on subdomain/hostname.

Example Scenario:

iphone.abhimishra-devops.com   → iPhone Service
android.abhimishra-devops.com  → Android Service
abhimishra-devops.com          → Desktop Service (main domain)

Create Wildcard ACM Certificate

# Verify your certificate includes wildcard
aws acm list-certificates --region ap-south-1

# Certificate should cover:
# - abhimishra-devops.com
# - *.abhimishra-devops.com

Ingress with Host-Based Routing

# 05-ingress-host.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: abhishek-ingress-demo3
  namespace: app1-ns
  annotations:
    # ALB Configuration
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/load-balancer-name: abhishek-demo-alb-host

    # SSL/TLS Configuration
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-south-1:ACCOUNT_ID:certificate/CERT_ID
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: '443'

    # Additional Settings
    alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=3600

spec:
  ingressClassName: alb
  rules:
  # Rule 1: iPhone subdomain
  - host: iphone.abhimishra-devops.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: iphone-service
            port:
              number: 80

  # Rule 2: Android subdomain
  - host: android.abhimishra-devops.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: android-service
            port:
              number: 80

  # Rule 3: Main domain (Desktop)
  - host: abhimishra-devops.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: desktop-service
            port:
              number: 80

Deploy Host-Based Ingress

# Delete previous Ingress
kubectl delete ingress abhishek-ingress-demo2 -n app1-ns

# Apply host-based Ingress
kubectl apply -f demo-03/05-ingress-host.yaml

# Verify
kubectl get ingress -n app1-ns
kubectl describe ingress abhishek-ingress-demo3 -n app1-ns

Configure Route 53 for Subdomains

# Get ALB DNS
ALB_DNS=$(kubectl get ingress abhishek-ingress-demo3 -n app1-ns -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')

echo "Creating Route 53 records for:"
echo "- iphone.abhimishra-devops.com"
echo "- android.abhimishra-devops.com"
echo "- abhimishra-devops.com"

Create records using AWS CLI:

# Create CNAME for iPhone subdomain
aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "iphone.abhimishra-devops.com",
        "Type": "CNAME",
        "TTL": 300,
        "ResourceRecords": [{"Value": "'$ALB_DNS'"}]
      }
    }]
  }'

# Create CNAME for Android subdomain
aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "android.abhimishra-devops.com",
        "Type": "CNAME",
        "TTL": 300,
        "ResourceRecords": [{"Value": "'$ALB_DNS'"}]
      }
    }]
  }'

# Create A record (ALIAS) for main domain
aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "abhimishra-devops.com",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "ZXXXXXXXXXXXX",
          "DNSName": "'$ALB_DNS'",
          "EvaluateTargetHealth": true
        }
      }
    }]
  }'

Test Host-Based Routing

# Test iPhone subdomain
curl https://iphone.abhimishra-devops.com
# Output: iPhone Application Page

# Test Android subdomain
curl https://android.abhimishra-devops.com
# Output: Android Application Page

# Test main domain
curl https://abhimishra-devops.com
# Output: Desktop Application Page

# Verify with headers
curl -v https://iphone.abhimishra-devops.com

How Host-Based Routing Works

  1. DNS Resolution: Each subdomain resolves to same ALB DNS

  2. Host Header: Browser sends Host: iphone.abhimishra-devops.com header

  3. ALB Routing: ALB checks Host header and matches Ingress rule

  4. Target Group: Routes to corresponding target group

  5. Service: ClusterIP service forwards to appropriate pods

Real-World Use Cases

api.company.com        → API microservices
admin.company.com      → Admin dashboard
blog.company.com       → Blog application
docs.company.com       → Documentation
app.company.com        → Main web application
mobile.company.com     → Mobile-optimized version

Security Implementation

When I first started setting up security for the project, I really struggled with getting SSL/TLS certificates to work properly. It felt complicated and time-consuming. But once I integrated AWS Certificate Manager (ACM), everything became much easier. ACM handled the certificates smoothly no more manual setup or renewal headaches.

It was a big relief, and honestly, it taught me how powerful managed services can be when it comes to simplifying security.

1. Network Security Architecture

VPC Design

Production VPC (10.0.0.0/16)
│
├── Availability Zone: ap-south-1a
│   ├── Public Subnet (10.0.0.0/24)
│   │   ├── NAT Gateway
│   │   ├── ALB (public-facing)
│   │   └── Internet Gateway
│   │
│   └── Private Subnet (10.0.1.0/24)
│       ├── Worker Node 1 (EKS)
│       ├── Worker Node 2 (EKS)
│       └── Application Pods
│
└── Availability Zone: ap-south-1b
    ├── Public Subnet (10.0.2.0/24)
    │   └── ALB (multi-AZ)
    │
    └── Private Subnet (10.0.3.0/24)
        ├── Worker Node 3 (EKS)
        ├── Worker Node 4 (EKS)
        └── Application Pods

Security Groups Configuration

ALB Security Group:

# Inbound Rules
- Port 80 (HTTP) from 0.0.0.0/0
- Port 443 (HTTPS) from 0.0.0.0/0

# Outbound Rules
- All traffic to Worker Node Security Group on pod ports

Worker Node Security Group:

# Inbound Rules
- All traffic from ALB Security Group
- Port 443 from EKS Control Plane
- Ports 1025-65535 from same security group (pod-to-pod)

# Outbound Rules
- All traffic (0.0.0.0/0) for internet access via NAT

EKS Control Plane Security Group:

# Managed by AWS EKS
# Allows communication between control plane and worker nodes

2. IAM Security Best Practices

Principle of Least Privilege

Load Balancer Controller Policy (Minimal):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "elasticloadbalancing:CreateLoadBalancer",
        "elasticloadbalancing:CreateTargetGroup",
        "elasticloadbalancing:CreateListener",
        "elasticloadbalancing:DeleteLoadBalancer",
        "elasticloadbalancing:DeleteTargetGroup",
        "elasticloadbalancing:DeleteListener",
        "elasticloadbalancing:ModifyLoadBalancerAttributes",
        "elasticloadbalancing:ModifyTargetGroup",
        "elasticloadbalancing:RegisterTargets",
        "elasticloadbalancing:DeregisterTargets",
        "elasticloadbalancing:DescribeLoadBalancers",
        "elasticloadbalancing:DescribeTargetGroups",
        "elasticloadbalancing:DescribeListeners",
        "elasticloadbalancing:DescribeTags"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances",
        "ec2:DescribeSubnets",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeVpcs",
        "ec2:CreateSecurityGroup",
        "ec2:CreateTags"
      ],
      "Resource": "*"
    }
  ]
}

IRSA Implementation

Why IRSA over Instance Profiles?

FeatureInstance ProfileIRSA
ScopeAll pods on nodeSpecific pod
Credential RotationManualAutomatic
Audit TrailNode-levelPod-level
Blast RadiusHighLow
ComplianceDifficultEasy

3. SSL/TLS Security

Certificate Configuration

ACM Certificate Best Practices:

# Use strong encryption
alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS-1-2-2017-01

# Supported TLS versions: 1.2, 1.3
# Cipher suites: Strong encryption only
# Perfect Forward Secrecy: Enabled

HTTP to HTTPS Redirect

annotations:
  # Automatic redirect
  alb.ingress.kubernetes.io/ssl-redirect: '443'

  # Custom redirect action
  alb.ingress.kubernetes.io/actions.ssl-redirect: |
    {
      "Type": "redirect",
      "RedirectConfig": {
        "Protocol": "HTTPS",
        "Port": "443",
        "StatusCode": "HTTP_301"
      }
    }

4. Application Security

Pod Security Standards

# Pod Security Context
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: myapp:latest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
        - ALL

Network Policies

# Restrict pod-to-pod communication
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-network-policy
  namespace: app1-ns
spec:
  podSelector:
    matchLabels:
      app: iphone
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: alb-ingress
    ports:
    - protocol: TCP
      port: 80
  egress:
  - to:
    - podSelector: {}
    ports:
    - protocol: TCP
      port: 443

Cost Optimization

Reducing infrastructure costs was a key goal during this project. One of the most effective strategies I implemented was consolidating multiple Classic Load Balancers into a single Application Load Balancer (ALB) using Kubernetes Ingress. This not only simplified traffic routing but also led to noticeable savings.

Cost Breakdown Analysis

Before: Multiple Load Balancers Approach

Monthly Costs:
├── Classic Load Balancer 1 (iPhone)     $18.00
├── Classic Load Balancer 2 (Android)    $18.00
├── Classic Load Balancer 3 (Desktop)    $18.00
├── Data Transfer (1 TB)                 $90.00
├── 3 Static IPs                         $10.80
└── Total                               $154.80/month

After: Single ALB with Ingress

Monthly Costs:
├── Application Load Balancer            $18.00
├── LCU Hours (Load Balancer Capacity)   $22.00
├── Data Transfer (1 TB)                 $90.00
└── Total                               $130.00/month

💰 Monthly Savings: $24.80 (16% reduction)
💰 Annual Savings: $297.60

Additional Cost Optimizations

1. Use Spot Instances for Worker Nodes

# eks-config.yaml
managedNodeGroups:
  - name: spot-ng
    instanceTypes:
      - t3.medium
      - t3a.medium
      - t2.medium
    spot: true
    desiredCapacity: 4
    minSize: 2
    maxSize: 8

Savings: Up to 70% on EC2 costs

Regular t2.medium: $0.0464/hour × 4 nodes × 730 hours = $135.50/month
Spot t3.medium: $0.0139/hour × 4 nodes × 730 hours = $40.65/month
Monthly Savings: $94.85 (70% reduction)

2. Right-Size Worker Nodes

# Monitor resource usage
kubectl top nodes
kubectl top pods -n app1-ns

# If CPU usage < 30%, downsize to t2.small
# If CPU usage > 80%, upsize to t3.large

3. Use Cluster Autoscaler

# Auto-scale based on demand
apiVersion: v1
kind: ConfigMap
metadata:
  name: cluster-autoscaler-priority-expander
  namespace: kube-system
data:
  priorities: |-
    10:
      - .*-spot-.*
    50:
      - .*-ondemand-.*

Savings: Scale down during off-peak hours

Peak hours (8 hrs/day): 4 nodes
Off-peak (16 hrs/day): 2 nodes
Average: 2.67 nodes instead of 4
Savings: ~33% on compute costs

4. Use gp3 EBS Volumes

storageClass:
  volumeType: gp3
  # gp3: $0.08/GB-month
  # gp2: $0.10/GB-month
  # Savings: 20% on storage costs

Total Cost Optimization Summary

Original Monthly Cost:                    $289.80
├── Load Balancers:        $154.80
├── EC2 (4 × t2.medium):   $135.00

Optimized Monthly Cost:                   $170.65
├── Single ALB:            $40.00
├── EC2 Spot (avg 2.67):   $40.65
├── Data Transfer:         $90.00

💰 Total Monthly Savings: $119.15 (41% reduction)
💰 Annual Savings: $1,429.80

Testing & Verification

1. Infrastructure Validation

Verify EKS Cluster

# Cluster status
eksctl get cluster --name Abhishek-ingress-demo --region ap-south-1

# Node status
kubectl get nodes -o wide

# Verify multi-AZ distribution
kubectl get nodes -o custom-columns=NAME:.metadata.name,ZONE:.metadata.labels."topology\.kubernetes\.io/zone"

# Expected output:
NAME                                    ZONE
ip-10-0-1-100.compute.internal         ap-south-1a
ip-10-0-1-101.compute.internal         ap-south-1a
ip-10-0-2-100.compute.internal         ap-south-1b
ip-10-0-2-101.compute.internal         ap-south-1b

Verify Load Balancer Controller

# Controller pods running
kubectl get pods -n kube-system -l app.kubernetes.io/name=aws-load-balancer-controller

# Controller logs (should show no errors)
kubectl logs -n kube-system deployment/aws-load-balancer-controller --tail=100

# Webhook configuration
kubectl get validatingwebhookconfiguration
kubectl get mutatingwebhookconfiguration

2. Application Testing

Pod Health

# All pods running
kubectl get pods -n app1-ns

# Pod resource usage
kubectl top pods -n app1-ns

# Pod logs
kubectl logs -f deployment/iphone-deployment -n app1-ns
kubectl logs -f deployment/android-deployment -n app1-ns
kubectl logs -f deployment/desktop-deployment -n app1-ns

Service Endpoints

# Verify services
kubectl get svc -n app1-ns

# Check endpoints (should show pod IPs)
kubectl get endpoints -n app1-ns

# Describe service
kubectl describe svc iphone-service -n app1-ns

3. Ingress & ALB Testing

Ingress Status

# Get Ingress details
kubectl get ingress -n app1-ns
kubectl describe ingress abhishek-ingress-demo3 -n app1-ns

# Check ALB in AWS Console
aws elbv2 describe-load-balancers \
  --names abhishek-demo-alb-host \
  --region ap-south-1

# Verify target groups
aws elbv2 describe-target-groups \
  --load-balancer-arn arn:aws:elasticloadbalancing:ap-south-1:ACCOUNT_ID:loadbalancer/app/abhishek-demo-alb-host/xxxxx

# Check target health
aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:ap-south-1:ACCOUNT_ID:targetgroup/k8s-app1ns-iphonese-xxxx/yyyy

4. DNS Testing

DNS Resolution

# Test DNS propagation
dig abhimishra-devops.com
dig iphone.abhimishra-devops.com
dig android.abhimishra-devops.com

# Using nslookup
nslookup abhimishra-devops.com
nslookup iphone.abhimishra-devops.com

# Check TTL
 abhimishra-devops.com

5. Functional Testing

Path-Based Routing

ALB_DNS="abhimishra-devops.com"

# Test all paths
echo "Testing iPhone service..."
curl -s https://$ALB_DNS/iphone | grep -i "iphone"

echo "Testing Android service..."
curl -s https://$ALB_DNS/android | grep -i "android"

echo "Testing Desktop service..."
curl -s https://$ALB_DNS/ | grep -i "desktop"

# Verify response codes
curl -I https://$ALB_DNS/iphone
# Should return: HTTP/2 200

Host-Based Routing

# Test subdomains
curl -s https://iphone.abhimishra-devops.com | grep -i "iphone"
curl -s https://android.abhimishra-devops.com | grep -i "android"
curl -s https://abhimishra-devops.com | grep -i "desktop"

# Test with specific headers
curl -H "Host: iphone.abhimishra-devops.com" https://$ALB_DNS

SSL/TLS Testing

# Test certificate
openssl s_client -connect abhimishra-devops.com:443 -servername abhimishra-devops.com < /dev/null

# Check certificate expiry
echo | openssl s_client -connect abhimishra-devops.com:443 2>/dev/null | openssl x509 -noout -dates

# Verify TLS version
nmap --script ssl-enum-ciphers -p 443 abhimishra-devops.com

# Test HTTP to HTTPS redirect
curl -I http://abhimishra-devops.com
# Should return: 301 Moved Permanently
# Location: https://abhimishra-devops.com/

6. Load Testing

Simple Load Test

# Install Apache Bench (if not installed)
sudo apt-get install apache2-utils  # Ubuntu/Debian
# or
brew install apache2  # macOS

# Run load test (100 requests, 10 concurrent)
ab -n 100 -c 10 https://abhimishra-devops.com/

# More aggressive test (1000 requests, 50 concurrent)
ab -n 1000 -c 50 https://abhimishra-devops.com/iphone

# Monitor pod CPU/memory during load test
watch -n 1 kubectl top pods -n app1-ns

Troubleshooting

Issue 1: Ingress Not Creating ALB

Symptoms:

kubectl get ingress -n app1-ns
# NAME                       CLASS   HOSTS   ADDRESS   PORTS   AGE
# abhishek-ingress-demo3     alb     *                 80      10m
# ↑ ADDRESS column empty after 5+ minutes

Solution 1: Check Controller Logs

kubectl logs -n kube-system deployment/aws-load-balancer-controller

# Common error messages and fixes:

# Error: "AccessDenied: User is not authorized to perform: elasticloadbalancing:CreateLoadBalancer"
# Fix: Update IAM policy for service account

# Error: "InvalidSubnetID.NotFound"
# Fix: Verify subnet tags

Solution 2: Verify Subnet Tags

# Public subnets MUST have this tag for internet-facing ALB:
kubernetes.io/role/elb = 1

# Private subnets MUST have this tag for internal ALB:
kubernetes.io/role/internal-elb = 1

# Add missing tags
aws ec2 create-tags \
  --resources subnet-xxxxx \
  --tags Key=kubernetes.io/role/elb,Value=1

# Verify cluster tag also exists:
kubernetes.io/cluster/Abhishek-ingress-demo = shared

Solution 3: Check IAM Service Account

# Verify IRSA annotation
kubectl describe sa aws-load-balancer-controller -n kube-system | grep role-arn

# Should show:
# eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/...

# If missing, recreate service account:
eksctl delete iamserviceaccount \
  --cluster=Abhishek-ingress-demo \
  --name=aws-load-balancer-controller \
  --namespace=kube-system

eksctl create iamserviceaccount \
  --cluster=Abhishek-ingress-demo \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --attach-policy-arn=arn:aws:iam::ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \
  --approve

Issue 2: 503 Service Unavailable

Symptoms:

curl https://abhimishra-devops.com
# HTTP/1.1 503 Service Temporarily Unavailable

Solution 1: Check Pod Status

# List all pods
kubectl get pods -n app1-ns

# Common pod issues:
# - CrashLoopBackOff: Check logs
# - ImagePullBackOff: Verify image exists
# - Pending: Check node resources

# Fix CrashLoopBackOff
kubectl logs <pod-name> -n app1-ns --previous
kubectl describe pod <pod-name> -n app1-ns

# Check pod events
kubectl get events -n app1-ns --sort-by='.lastTimestamp'

Solution 2: Verify Service Endpoints

# Check if service has endpoints
kubectl get endpoints -n app1-ns

# Example output:
NAME              ENDPOINTS                           AGE
iphone-service    10.0.1.50:80,10.0.2.51:80          1h
android-service   10.0.1.52:80,10.0.2.53:80          1h
desktop-service   10.0.1.54:80,10.0.2.55:80          1h

# If ENDPOINTS column is empty:
# - Check pod labels match service selector
# - Verify pods are in Running state
# - Check service port matches container port

# Verify label matching:
kubectl get pods -n app1-ns --show-labels
kubectl get svc iphone-service -n app1-ns -o yaml | grep selector

Solution 3: Check Target Group Health

# In AWS Console: EC2 → Target Groups → Select TG → Targets tab
# Or via CLI:

TG_ARN=$(aws elbv2 describe-target-groups \
  --query 'TargetGroups[?contains(TargetGroupName, `iphone`)].TargetGroupArn' \
  --output text)

aws elbv2 describe-target-health --target-group-arn $TG_ARN

# Unhealthy reasons:
# - Target.FailedHealthChecks: Health check failing
# - Target.NotRegistered: Pod IP not registered
# - Target.InvalidState: Pod not ready

# Fix health check issues:
kubectl exec -it <pod-name> -n app1-ns -- curl localhost:80
# Should return 200 OK

Issue 3: SSL Certificate Errors

Symptoms:

  • Browser shows "Your connection is not private"

  • Certificate warning messages

  • NET::ERR_CERT_AUTHORITY_INVALID

Solution 1: Verify Certificate Status

# Check ACM certificate status
aws acm describe-certificate \
  --certificate-arn arn:aws:acm:ap-south-1:ACCOUNT_ID:certificate/CERT_ID \
  --region ap-south-1

# Status should be: ISSUED
# If PENDING_VALIDATION, complete DNS validation:

# Get validation CNAME records
aws acm describe-certificate \
  --certificate-arn arn:aws:acm:ap-south-1:ACCOUNT_ID:certificate/CERT_ID \
  --query 'Certificate.DomainValidationOptions[].ResourceRecord' \
  --output table

# Add CNAME records to Route 53

Solution 2: Check Domain Match

# Certificate domain must match Ingress host

# View certificate domains
aws acm describe-certificate \
  --certificate-arn arn:aws:acm:ap-south-1:ACCOUNT_ID:certificate/CERT_ID \
  --query 'Certificate.SubjectAlternativeNames'

# Should include:
# - abhimishra-devops.com
# - *.abhimishra-devops.com (for subdomains)

# If mismatch, request new certificate with correct domains

Issue 4: DNS Not Resolving

Symptoms:

curl https://iphone.abhimishra-devops.com
# curl: (6) Could not resolve host: iphone.abhimishra-devops.com

Solution 1: Verify Route 53 Records

# Check if CNAME/A record exists
aws route53 list-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --query "ResourceRecordSets[?Name=='iphone.abhimishra-devops.com.']"

# If missing, create CNAME record
ALB_DNS=$(kubectl get ingress abhishek-ingress-demo3 -n app1-ns -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')

aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "iphone.abhimishra-devops.com",
        "Type": "CNAME",
        "TTL": 300,
        "ResourceRecords": [{"Value": "'$ALB_DNS'"}]
      }
    }]
  }'

Solution 2: Check DNS Propagation

# Test DNS resolution
dig iphone.abhimishra-devops.com

# Use different DNS servers
dig @8.8.8.8 iphone.abhimishra-devops.com  # Google DNS
dig @1.1.1.1 iphone.abhimishra-devops.com  # Cloudflare DNS

# Wait for TTL expiration (usually 300 seconds)
# Then test again

Issue 5: High Latency

Symptoms:

curl -w "@curl-format.txt" -o /dev/null -s https://abhimishra-devops.com
# time_total: 2.5s (should be < 0.5s)

Solution 1: Check Target Type

# Verify using IP mode (faster than instance mode)
kubectl get ingress abhishek-ingress-demo3 -n app1-ns -o yaml | grep target-type
# Should show: ip

# If instance mode, change to IP:
kubectl annotate ingress abhishek-ingress-demo3 -n app1-ns \
  alb.ingress.kubernetes.io/target-type=ip \
  --overwrite

Solution 2: Optimize Health Checks

annotations:
  alb.ingress.kubernetes.io/healthcheck-interval-seconds: '15'
  alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '5'
  alb.ingress.kubernetes.io/success-codes: '200'

Solution 3: Enable HTTP/2

annotations:
  alb.ingress.kubernetes.io/load-balancer-attributes: http2.enabled=true

Conclusion

What You've Accomplished

Congratulations! 🎉 By completing this project, you have successfully:

Built Production-Ready Infrastructure

  • Deployed a multi-AZ EKS cluster with high availability

  • Configured AWS Load Balancer Controller for automated ALB management

  • Implemented secure IAM roles using IRSA

Mastered Three Routing Strategies

  • Path-based routing for microservices architecture

  • TLS termination with AWS Certificate Manager

  • Host-based routing for multi-domain applications

Implemented Enterprise Security

  • SSL/TLS encryption for all traffic

  • Private networking with worker nodes in private subnets

  • Fine-grained IAM permissions at pod level

  • Security group configurations for network isolation

Optimized for Cost

  • Reduced load balancer costs by 67%

  • Implemented efficient resource utilization

  • Learned strategies for further cost optimization

Gained Real-World Experience

  • Troubleshooting common Kubernetes and AWS issues

  • Monitoring and logging best practices

  • Load testing and performance optimization

Key Takeaways

Technical Skills Gained:

  • Kubernetes Expertise: Ingress, Services, Deployments, Namespaces

  • AWS Services: EKS, ALB, Route 53, ACM, IAM, VPC

  • Infrastructure as Code: Declarative manifests, version control

  • DevOps Practices: CI/CD readiness, monitoring, troubleshooting

  • Security Best Practices: TLS, IRSA, network policies, least privilege

Business Value Delivered:

  • Cost Savings: 40-67% reduction in infrastructure costs

  • Improved Security: Enterprise-grade encryption and access control

  • Better Performance: Multi-AZ deployment with low latency

  • Easier Management: Centralized configuration and monitoring

  • Scalability: Ready for auto-scaling and high traffic

Next Steps for Enhancement

1. Implement Auto-Scaling:

# Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: iphone-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: iphone-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

2. Add CI/CD Pipeline:

  • GitHub Actions for automated deployments

  • ArgoCD for GitOps workflow

  • Helm charts for application packaging

3. Implement Service Mesh:

  • Istio or AWS App Mesh for advanced traffic management

  • Mutual TLS between services

  • Circuit breakers and retries

4. Enhanced Monitoring:

  • Prometheus for metrics collection

  • Grafana for visualization

  • ELK stack for centralized logging

5. Disaster Recovery:

  • Multi-region deployment

  • Automated backups with Velero

  • Cross-region failover strategy

Resources for Further Learning

Official Documentation:

Community Resources:

Certifications to Consider:

  • AWS Certified Solutions Architect - Associate

  • Certified Kubernetes Administrator (CKA)

  • Certified Kubernetes Application Developer (CKAD)

Project Repository

GitHub: AWS-EKS-Kubernetes-Ingress-with-ALB-Routing

Project Structure:

AWS-EKS-Kubernetes-Ingress-with-ALB-Routing/
├── demo-01/                    # Path-based routing
│   ├── 01-ns.yaml
│   ├── 02-iphone.yaml
│   ├── 03-android.yaml
│   ├── 04-desktop.yaml
│   └── 05-ingress.yaml
├── demo-02/                    # TLS termination
│   ├── 01-ns.yaml
│   ├── 02-iphone.yaml
│   ├── 03-android.yaml
│   ├── 04-desktop.yaml
│   └── 05-ingress-tls.yaml
├── demo-03/                    # Host-based routing
│   ├── 01-ns.yaml
│   ├── 02-iphone.yaml
│   ├── 03-android.yaml
│   ├── 04-desktop.yaml
│   └── 05-ingress-host.yaml
├── eks-config.yaml             # EKS cluster configuration
├── iam_policy.json             # IAM policy for LB controller
├── README.md                   # Project documentation
└── report first project.pdf    # Detailed project report

Clone and Deploy:

# Clone repository
git clone https://github.com/Abhi-mishra998/AWS-EKS-Kubernetes-Ingress-with-ALB-Routing.git
cd AWS-EKS-Kubernetes-Ingress-with-ALB-Routing

# Follow implementation steps in README.md

Final Thoughts

This project represents a production-grade implementation that you can confidently showcase in your portfolio or use as a foundation for real-world applications. The skills and knowledge gained here are directly applicable to:

  • Enterprise Kubernetes deployments

  • Cloud-native application architectures

  • DevOps automation and infrastructure management

  • Cost optimization initiatives

  • Security and compliance requirements

Remember, the journey doesn't end here. Cloud technologies evolve rapidly, and continuous learning is key to staying relevant in the DevOps and cloud engineering space.

Cleanup Instructions

Important: Complete Cleanup to Avoid Charges

# Step 1: Delete Ingress resources (this triggers ALB deletion)
kubectl delete ingress --all -n app1-ns

# Wait for ALB deletion (2-3 minutes)
echo "Waiting for ALB deletion..."
sleep 180

# Step 2: Delete namespace (deletes all resources in namespace)
kubectl delete namespace app1-ns

# Step 3: Uninstall Load Balancer Controller
helm uninstall aws-load-balancer-controller -n kube-system

# Step 4: Delete EKS Cluster
eksctl delete cluster --name Abhishek-ingress-demo --region ap-south-1

# Step 5: Clean Up IAM Resources
eksctl delete iamserviceaccount \
  --cluster=Abhishek-ingress-demo \
  --name=aws-load-balancer-controller \
  --namespace=kube-system

# Delete IAM policy (optional - if not used elsewhere)
aws iam delete-policy \
  --policy-arn arn:aws:iam::ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy

# Step 6: Clean Up Route 53 (delete CNAME/A records)
# Step 7: Delete ACM Certificates (if not in use)

Quick Reference Commands

# ========================================
# EKS CLUSTER MANAGEMENT
# ========================================

# Create cluster
eksctl create cluster -f eks-config.yaml

# Update kubeconfig
aws eks update-kubeconfig --region ap-south-1 --name Abhishek-ingress-demo

# Get cluster info
eksctl get cluster --name Abhishek-ingress-demo --region ap-south-1

# Delete cluster
eksctl delete cluster --name Abhishek-ingress-demo --region ap-south-1

# ========================================
# KUBECTL COMMANDS
# ========================================

# Get resources
kubectl get nodes
kubectl get pods -n app1-ns
kubectl get svc -n app1-ns
kubectl get ingress -n app1-ns

# Describe resources
kubectl describe ingress <ingress-name> -n app1-ns
kubectl describe pod <pod-name> -n app1-ns

# View logs
kubectl logs -f deployment/<deployment-name> -n app1-ns
kubectl logs -n kube-system deployment/aws-load-balancer-controller

# Resource usage
kubectl top nodes
kubectl top pods -n app1-ns

# ========================================
# ALB & INGRESS
# ========================================

# Get ALB DNS
kubectl get ingress <ingress-name> -n app1-ns -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'

# Watch Ingress creation
kubectl get ingress -n app1-ns -w

# ========================================
# AWS CLI COMMANDS
# ========================================

# List Load Balancers
aws elbv2 describe-load-balancers --region ap-south-1

# List Target Groups
aws elbv2 describe-target-groups --region ap-south-1

# Check Target Health
aws elbv2 describe-target-health --target-group-arn <TG_ARN>

# ========================================
# TESTING
# ========================================

# Test HTTP endpoint
curl http://<ALB_DNS>/iphone

# Test HTTPS endpoint
curl https://<DOMAIN>/iphone

# Check SSL certificate
openssl s_client -connect <DOMAIN>:443 -servername <DOMAIN>

# Load test
ab -n 100 -c 10 https://<DOMAIN>/
  • Abhishek Mishra

🌩️Cloud & DevOps Engineer | AWS & Oracle Cloud Certified
Passionate about Cloud-Native Technologies, Kubernetes, and Infrastructure Automation

🔗 Connect with me:

🚀 I specialize in building secure, scalable cloud-native architectures using AWS, Kubernetes, and DevOps best practices. I love solving real-world problems through automation, open-source collaboration, and continuous learning.

  • Special Thanks To
    This project wouldn’t be possible without the incredible contributions, documentation, and community support from:

    • 🛡️ AWS Load Balancer Controller Team – for their detailed and reliable documentation on managing ALBs in Kubernetes

    • 🌐 Kubernetes SIG Network – for defining robust Ingress specifications and advancing Kubernetes networking standards

    • ⚙️ eksctl Community – for simplifying cluster provisioning and management with a powerful CLI tool

    • ☁️ AWS EKS Team – for delivering a powerful managed Kubernetes experience and seamless AWS integration

    • 💡 Open Source Contributors – for driving innovation and making DevOps accessible to all through collaborative development

    • 💬 GitHub Discussions & Community Forums – for practical insights, real-world troubleshooting, and peer-to-peer learning

This project helped me deepen my understanding of Kubernetes networking, ALB routing, and Infrastructure as Code (IaC) workflows. Your work inspires engineers like me to build better systems every day.