Why Use Ingress Over LoadBalancer?
For any ecommerce website there will be more then 200 services
Problems with LoadBalancer services:
- 💰 Cost: Each service needs a separate external IP
- 🔀 Routing: No advanced routing capabilities
- 🛡️ Features: No WAF, SSL termination, path-based routing
Client Request
↓
[Ingress Controller] ← Watches Ingress Resources
↓
[Load Balancer] ← Configured by Controller
↓
[Services] → [Pods]
Components:
- Ingress Resource: YAML manifest defining routing rules
- Ingress Controller: Watches Ingress resources and configures load balancer
- Load Balancer: Routes traffic based on rules (nginx, HAProxy, etc.)
Ingress Controllers
Popular Ingress Controllers
- NGINX Ingress Controller (most common)
- HAProxy
- Traefik
- Citrix ADC
- F5 BIG-IP
- Ambassador
- Istio/Envoy (Service Mesh)
- 30+ officially supported controllers
How Ingress Controllers Work
Example: NGINX Ingress Controller
- Install NGINX Ingress Controller:
helm install nginx-ingress ingress-nginx/ingress-nginx
- Controller watches for Ingress resources
- Updates
nginx.confwith routing rules - NGINX pod handles traffic routing
Configuration Example:
Basic Ingress Resource

Key Fields:
apiVersion: networking.k8s.io/v1(previouslyextensions/v1beta1, deprecated in 1.22+)kind: Ingressspec.rules: Define routing rules
Host-Based Routing
Use Case: Route traffic based on domain name

Testing:
# Without host header (fails)
curl http://<INGRESS_IP>
# Output: 404 Not Found
# With host header (succeeds)
curl -H "Host: food.bar.com" http://<INGRESS_IP>
# Output: Success response from http-svc
Path-Based Routing
Use Case: Route to different services based on URL path

Testing:
# Route to http-svc
curl -H "Host: food.bar.com" http://<INGRESS_IP>/first
# Output: Response from http-svc
# Route to myapp-svc
curl -H "Host: food.bar.com" http://<INGRESS_IP>/second
# Output: Response from myapp-svc
what is Ingress Classes
Ingress Classes in Kubernetes define which controller should implement a given Ingress resource. Think of them as a way to tell Kubernetes: “This Ingress should be handled by this specific ingress controller.”
Why do we need Ingress Classes?
- In a cluster, you can have multiple ingress controllers (e.g., NGINX, Traefik, AWS ALB).
- Each controller watches for Ingress resources with its class name.
- This prevents conflicts and allows different routing strategies for different apps.
How It Works
- An Ingress resource has: YAMLspec:
ingressClassName: nginx-external
spec:
ingressClassName: nginx-external
The controller (e.g., NGINX) registers itself with an IngressClass object
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx-external
spec:
controller: k8s.io/ingress-nginx
When Kubernetes sees an Ingress with ingressClassName: nginx-external, it routes traffic using the NGINX ingress controller.
Why Ingress Classes?
- Multiple teams using different controllers
- Different controllers for different purposes (internal vs external)
- Mixing controller types (NGINX + HAProxy)
Basic Authentication
Use Case: Restrict access to authorized users only
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auth-ingress
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: ‘Authentication Required’
spec:
rules:
– host: secure.bar.com
http:
paths:
– path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
How Basic Auth Works in NGINX Ingress
auth-type: basic→ Enables HTTP Basic Authentication.auth-secret: basic-auth→ Refers to a Kubernetes Secret that stores username/password in htpasswd format.auth-realm→ Message shown in the browser login prompt.
If the user does not provide valid credentials, NGINX returns 401 Unauthorized.
Steps to Restrict Access
- Create the Secret with Credentials
htpasswd -c auth basic-user
# Enter password when prompted
kubectl create secret generic basic-auth --from-file=auth
- This creates a secret named
basic-authwith the fileauthcontainingusername:hashed-password.
Apply the Ingress
- Your Ingress references this secret, so only users with valid credentials can access the app.
Additional Hardening
- Use HTTPS: Basic Auth sends credentials in base64; without TLS, they can be intercepted.
- IP Whitelisting (optional)
nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.1.0/24"
Only allow specific IP ranges.
Rate Limiting
nginx.ingress.kubernetes.io/limit-connections: “10”
nginx.ingress.kubernetes.io/limit-rpm: “100”
TLS/SSL with Ingress
SSL/TLS Termination Types
1. SSL Passthrough
How it works:
Code
[Client] --HTTPS--> [Load Balancer] --HTTPS--> [Server]
(encrypted) (passthrough) (encrypted)
Characteristics:
- ✅ End-to-end encryption
- ❌ Load balancer can’t inspect traffic
- ❌ No WAF, path routing, or cookie management
- ❌ Only Layer 4 (TCP) load balancing
- ❌ Server handles all decryption (high load)
- ⚠️ Vulnerable to attacks (LB can’t detect malware)
Configuration:
YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ssl-passthrough
annotations:
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
rules:
- host: secure.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: secure-service
port:
number: 443
When to use:
- Regulatory compliance requires end-to-end encryption
- Don’t trust the load balancer layer
- Very specific security requirements
2. SSL Edge Termination (Offloading)
How it works:
Code
[Client] --HTTPS--> [Load Balancer] --HTTP--> [Server]
(encrypted) (decrypt) (plain)
Characteristics:
- ✅ Fastest performance (server doesn’t decrypt)
- ✅ Load balancer can inspect traffic
- ✅ WAF, routing, caching available
- ❌ Internal traffic is unencrypted
- ⚠️ Vulnerable to man-in-the-middle attacks internally
Configuration:
YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ssl-edge
spec:
tls:
- hosts:
- app.example.com
secretName: tls-secret
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80 # HTTP backend
Create TLS Secret:
bash
kubectl create secret tls tls-secret \
--cert=path/to/cert.crt \
--key=path/to/cert.key
When to use:
- Performance is critical
- Internal network is trusted
- Security is not the top priority
- High traffic applications
3. SSL Re-encrypt (Bridging) – RECOMMENDED
How it works:
Code
[Client] --HTTPS--> [Load Balancer] --HTTPS--> [Server]
(encrypted) (decrypt + (re-encrypted)
re-encrypt)
Characteristics:
- ✅ Secure end-to-end
- ✅ Load balancer can inspect traffic
- ✅ WAF, routing, security features available
- ✅ Detects malware and malicious requests
- ⚠️ Slightly slower (double encryption)
- ✅ Best balance of security and functionality
Configuration:
YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ssl-reencrypt
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
tls:
- hosts:
- app.example.com
secretName: frontend-tls-secret
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 443 # HTTPS backend
When to use:
- Security is important
- Need load balancer features (WAF, routing)
- Production environments
- Most common choice
Practical Examples
Example 1: Multi-Service Application
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-service-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
– host: myapp.example.com
http:
paths:
# Frontend
– path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
# API
– path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
# Admin
– path: /admin
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 3000
This Ingress manifest is an example of path-based routing in Kubernetes using the NGINX Ingress Controller. Let’s break it down:
✅ What It Does
- Ingress resource: Defines external access to multiple services inside your cluster.
- Host:
myapp.example.com→ All rules apply to this domain. - Annotation:
nginx.ingress.kubernetes.io/rewrite-target: /
This tells NGINX to strip the matched path and forward requests to the backend starting at /.
✅ Routing Logic
Under spec.rules:
- Path
/→ frontend-service (port 80)- Requests like
https://myapp.example.com/go to the frontend.
- Requests like
- Path
/api→ api-service (port 8080)- Requests like
https://myapp.example.com/apigo to the API service.
- Requests like
- Path
/admin→ admin-service (port 3000)- Requests like
https://myapp.example.com/admingo to the admin dashboard.
- Requests like
✅ Why Use rewrite-target: /?
Without this annotation:
- A request to
/api/userswould be sent to the backend as/api/users. With rewrite: - It becomes
/users(because the prefix/apiis stripped). This is useful if your backend expects root paths.
✅ Benefits
- Single domain for multiple services.
- No need for separate LoadBalancers.
- Easy to manage routing rules.
Example 2: Canary Deployment
Stable version
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-stable
spec:
rules:
– host: app.example.com
http:
paths:
– path: /
pathType: Prefix
backend:
service:
name: app-v1
port:
number: 80
Canary version (10% traffic)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-canary
annotations:
nginx.ingress.kubernetes.io/canary: “true”
nginx.ingress.kubernetes.io/canary-weight: “10”
spec:
rules:
– host: app.example.com
http:
paths:
– path: /
pathType: Prefix
backend:
service:
name: app-v2
port:
number: 80
You have two Ingress resources for the same host (app.example.com):
- Stable Version
- Routes all traffic to
app-v1(your stable version).
Canary Version
-
nginx.ingress.kubernetes.io/canary: "true"→ Marks this Ingress as a canary.nginx.ingress.kubernetes.io/canary-weight: "10"→ Sends 10% of traffic toapp-v2(your new version).
✅ Why Use This?
- Canary deployments allow you to gradually roll out a new version without impacting all users.
- If something goes wrong, you can easily revert by removing the canary Ingress.
✅ How It Works
- Both Ingresses share the same host (
app.example.com). - NGINX Ingress Controller uses the annotations to split traffic:
- 90% →
app-v1(stable) - 10% →
app-v2(canary)
- 90% →
Example 3: Rate Limiting;
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rate-limited-ingress
annotations:
nginx.ingress.kubernetes.io/limit-rps: “10” # 10 requests per second
nginx.ingress.kubernetes.io/limit-connections: “5”
spec:
rules:
– host: api.example.com
http:
paths:
– path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
This Ingress manifest is an example of rate limiting using NGINX Ingress Controller annotations. Here’s what it means:
✅ Purpose
To protect your API from abuse or overload by limiting:
- Requests per second (RPS) per client.
- Concurrent connections per client.
✅ Annotations Explained
nginx.ingress.kubernetes.io/limit-rps: “10”
Limits each client to 10 requests per second. If a client sends more than 10 requests in one second, extra requests are rejected with HTTP 503 (Service Unavailable).
nginx.ingress.kubernetes.io/limit-connections: “5”
Limits each client to 5 simultaneous connections. If a client tries to open more than 5 connections at once, extra connections are blocked.
✅ Why Use This?
- Prevent DDoS attacks or accidental overload.
- Ensure fair usage among clients.
- Protect backend services from excessive traffic.
✅ Important Notes
- Works only with NGINX Ingress Controller.
- Rate limiting is per client IP by default.
- Combine with:
- Authentication (Basic Auth, OAuth).
- IP Whitelisting for extra security.
Leave a Reply