In this lab, we moved beyond a simple LoadBalancer and implemented Layer 7 routing using NGINX Ingress on:
- Azure Kubernetes Service (AKS)
- NGINX Ingress Controller
By the end, we achieved:
http://<PUBLIC-IP>/hello
http://<PUBLIC-IP>/api
Using:
- One public IP
- One Ingress controller
- Multiple backend services
๐ Why Use Ingress Instead of LoadBalancer?
With a normal Service:
type: LoadBalancer
You get:
1 Service = 1 Public IP
That becomes expensive and hard to manage.
With Ingress:
1 Public IP
โ Multiple routes
โ Multiple services
This is how real microservices platforms operate.
๐งฑ Architecture
Internet
โ
Azure LoadBalancer (created by ingress)
โ
NGINX Ingress Controller
โ
hello-service
api-service
The LoadBalancer is automatically created when installing the Ingress controller.
1๏ธโฃ Install NGINX Ingress Controller
We deployed the official controller:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
Check readiness:
kubectl get pods -n ingress-nginx
Verify service:
kubectl get svc -n ingress-nginx
Wait until:
ingress-nginx-controller LoadBalancer <EXTERNAL-IP>
That IP becomes your single entry point.
2๏ธโฃ Deploy Two Applications
A. Hello App
Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-app
spec:
replicas: 2
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: <ACR_LOGIN_SERVER>/hello-aks:v1
ports:
- containerPort: 3000
Service:
apiVersion: v1
kind: Service
metadata:
name: hello-service
spec:
selector:
app: hello
ports:
- port: 80
targetPort: 3000
B. API App (NGINX Demo)
Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-app
spec:
replicas: 2
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: nginx
ports:
- containerPort: 80
Service:
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
selector:
app: api
ports:
- port: 80
targetPort: 80
3๏ธโฃ Create the Ingress Resource
Hereโs the initial Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /hello
pathType: Prefix
backend:
service:
name: hello-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
Apply it:
kubectl apply -f app-ingress.yaml
4๏ธโฃ Testing the Routes
Test:
curl http://<INGRESS-IP>/hello
curl http://<INGRESS-IP>/api
Result:
/hello โ โ
Works
/api โ โ 404 Not Found
๐ Why Did /api Return 404?
Important lesson:
Ingress forwarded:
/api โ api-service
But the nginx container only serves /.
It does NOT serve /api.
So nginx tried to serve /api as a file โ it didnโt exist โ 404.
This was NOT an Ingress failure.
It was backend path behavior.
5๏ธโฃ Fixing with Rewrite Annotation
We added:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Updated Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /hello
pathType: Prefix
backend:
service:
name: hello-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
Now:
/api โ rewritten to /
Test again:
/hello โ Hello from AKS + ACR ๐
/api โ nginx welcome page
Success โ
๐ง What You Learned
Ingress Controls:
| Feature | Controlled By |
|---|---|
| Path matching | pathType |
| Routing | backend service |
| URL rewrite | annotation |
| TLS | ingress spec |
Key Insight:
Ingress does NOT automatically rewrite URLs.
You must explicitly define it.
๐ก Real-World Pattern
Typical SaaS architecture:
/api โ backend-service
/ โ frontend-service
All behind:
- One public IP
- One Ingress
- TLS termination at Ingress
๐ Current Architecture
Internet
โ
LoadBalancer
โ
NGINX Ingress
โ
hello-service
api-service
You now have:
- Layer 7 routing
- Single entry point
- Microservice-ready architecture
- Production-aligned pattern
๐ฎ Next Evolution Steps
To move toward production-grade architecture:
- Add HTTPS with cert-manager
- Use custom domain
- Add rate limiting
- Add canary deployments
- Add autoscaling
- Replace nginx API with real backend
- Move to Application Gateway + WAF
๐ฏ Final Takeaway
Youโve moved from:
Basic Service Exposure
To:
Production-Style Ingress Routing
Thatโs a major step in Kubernetes maturity.

Top comments (0)