Configuring Kubernetes Ingress with Amazon EKS and ALB: A Comprehensive Guide
Detailed Instructions for Kubernetes Ingress Setup on EKS Using ALB

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
👤 User Entry Point - The Beginning
User: Abhishek Mishra enters the URL in his browser.
Connection: Secure entry from the Internet to AWS VPC.
🎯 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.
⚖️ 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.
🚪 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.
📱💻🤖 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.
🔄 Deployment Component - The Update Manager
Features rolling updates, rollback capabilities, version control, and health monitoring.
Supports blue-green deployments for testing before switching.
🔐 AWS Certificate Manager (ACM) - The Security Guard
Manages SSL/TLS certificates for HTTPS encryption.
Provides free, auto-renewing certificates for secure communication.
🌍 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.comin browserRoute 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-xxxxxPort: 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
| Category | Technology | Real-Life Analogy | Why We Use It |
| 🏗️ Orchestration | Amazon EKS | Shopping Mall Building | Managed infrastructure |
| 💻 Compute | EC2 t3.medium | Store Spaces | Where apps actually run |
| ⚖️ Load Balancing | AWS ALB | Reception Desk | Distributes traffic smartly |
| 🎛️ Ingress | LB Controller | Traffic Cop | Connects K8s to AWS |
| 🌐 DNS | Route 53 | GPS System | Converts names to addresses |
| 🔒 Security | ACM | ID Badge System | SSL certificates |
| 🎫 Permissions | IRSA | Key Card System | Secure access control |
| 📝 IaC | eksctl | Construction Blueprint | Automate everything |
Required Tools & Versions
| Tool | Version | Installation Link |
| AWS CLI | v2.x | Install Guide |
| kubectl | v1.28+ | Install Guide |
| eksctl | v0.160+ | Install Guide |
| Helm | v3.x | Install 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 groupsec2:DescribeInstances- Discover worker nodesec2:DescribeSecurityGroups- Manage security groupsiam:CreateServiceLinkedRole- Create service-linked roleswafv2:*- 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
/iphonematches:/iphone,/iphone/,/iphone/details, etc./androidmatches:/android,/android/app,/android/store, etc.
Path Priority: Kubernetes evaluates paths from most specific to least specific
Longer paths evaluated first
/iphoneevaluated 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
Client Request: Browser sends HTTPS request to
abhimishra-devops.comDNS Resolution: Route 53 resolves to ALB
TLS Handshake: ALB performs SSL/TLS handshake using ACM certificate
Decryption: ALB decrypts HTTPS traffic
Backend Communication: ALB sends HTTP (unencrypted) to pods
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
DNS Resolution: Each subdomain resolves to same ALB DNS
Host Header: Browser sends
Host: iphone.abhimishra-devops.comheaderALB Routing: ALB checks Host header and matches Ingress rule
Target Group: Routes to corresponding target group
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?
| Feature | Instance Profile | IRSA |
| Scope | All pods on node | Specific pod |
| Credential Rotation | Manual | Automatic |
| Audit Trail | Node-level | Pod-level |
| Blast Radius | High | Low |
| Compliance | Difficult | Easy |
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:
Kubernetes Patterns Book
AWS re:Invent Videos
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:
GitHub: @Abhi-mishra998
- Project Repo: AWS-EKS-Kubernetes-Ingress-with-ALB-Routing
🚀 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.




