23: Ingress Path-Based Routing
23: Ingress Path-Based Routing
Objective
Learn how to use path-based routing in a Kubernetes Ingress to route different URL paths to different backend Services through a single hostname, implementing a common microservices pattern.
Theory
Path-Based Routing
Path-based routing allows a single hostname to serve multiple applications, each on a different URL path. This is a fundamental pattern in microservices architectures:
/approutes to the main application Service/adminroutes to the admin panel Service/apiroutes to the API backend Service
This approach provides several advantages:
- Single Load Balancer — One external IP and one Azure Load Balancer for all services, reducing cost
- Unified hostname — Users access different services through the same domain
- Simplified DNS — Only one DNS record needed instead of one per service
- Centralized TLS — One TLS certificate covers all paths
Path-Based Routing Architecture
graph LR
Client["Client<br/>(Browser / curl)"]
LB["Azure Load Balancer"]
subgraph AKS["AKS Cluster"]
IC["NGINX Ingress Controller"]
subgraph Ingress["Ingress: paths-XX.IP.nip.io"]
R1["/app → echo-app-XX"]
R2["/admin → echo-admin-XX"]
end
subgraph AppService["echo-app-XX"]
AP1["Pod: App 1"]
AP2["Pod: App 2"]
end
subgraph AdminService["echo-admin-XX"]
AD1["Pod: Admin 1"]
end
IC --> Ingress
R1 --> AppService
R2 --> AdminService
end
Client --> LB --> IC
style Ingress fill:#e1f5fe,stroke:#0288d1,stroke-width:1px
style AppService fill:#c8e6c9,stroke:#2e7d32,stroke-width:1px
style AdminService fill:#fff9c4,stroke:#f9a825,stroke-width:1px
How Path Matching Works
With pathType: Prefix:
| Request Path | Rule Path | Matches? |
|---|---|---|
/app |
/app |
Yes |
/app/ |
/app |
Yes |
/app/dashboard |
/app |
Yes |
/application |
/app |
No (different path segment) |
/admin |
/app |
No |
/admin/settings |
/admin |
Yes |
Practical Tasks
Task 1: Get the Ingress Controller IP
INGRESS_IP=$(kubectl get svc -n app-routing-system nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "Ingress IP: $INGRESS_IP"
Task 2: Create Two Backend Deployments and Services
Create a file called path-routing-apps.yaml:
# App Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-app-XX
namespace: student-XX
labels:
app: echo-app-XX
spec:
replicas: 2
selector:
matchLabels:
app: echo-app-XX
template:
metadata:
labels:
app: echo-app-XX
spec:
containers:
- name: echo
image: hashicorp/http-echo
args:
- "-text=This is the APP service (student-XX)"
ports:
- containerPort: 5678
resources:
requests:
cpu: "50m"
memory: "32Mi"
limits:
cpu: "100m"
memory: "64Mi"
---
apiVersion: v1
kind: Service
metadata:
name: echo-app-XX
namespace: student-XX
spec:
selector:
app: echo-app-XX
ports:
- port: 80
targetPort: 5678
---
# Admin Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-admin-XX
namespace: student-XX
labels:
app: echo-admin-XX
spec:
replicas: 1
selector:
matchLabels:
app: echo-admin-XX
template:
metadata:
labels:
app: echo-admin-XX
spec:
containers:
- name: echo
image: hashicorp/http-echo
args:
- "-text=This is the ADMIN service (student-XX)"
ports:
- containerPort: 5678
resources:
requests:
cpu: "50m"
memory: "32Mi"
limits:
cpu: "100m"
memory: "64Mi"
---
apiVersion: v1
kind: Service
metadata:
name: echo-admin-XX
namespace: student-XX
spec:
selector:
app: echo-admin-XX
ports:
- port: 80
targetPort: 5678
Deploy and verify:
kubectl apply -f path-routing-apps.yaml
kubectl get pods -n student-XX -l 'app in (echo-app-XX, echo-admin-XX)'
kubectl get svc -n student-XX
Task 3: Create an Ingress with Path-Based Routing
Create a file called path-routing-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-routing-XX
namespace: student-XX
spec:
ingressClassName: webapprouting.kubernetes.azure.com
rules:
- host: paths-XX.INGRESS_IP.nip.io # Replace INGRESS_IP with actual IP
http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: echo-app-XX
port:
number: 80
- path: /admin
pathType: Prefix
backend:
service:
name: echo-admin-XX
port:
number: 80
Important: Replace
INGRESS_IPwith the actual IP from Task 1.
Apply the Ingress:
kubectl apply -f path-routing-ingress.yaml
Task 4: Verify Path-Based Routing
Wait for the Ingress to get an address:
kubectl get ingress path-routing-XX -n student-XX
Test each path:
# Test /app path
curl http://paths-XX.$INGRESS_IP.nip.io/app
# Test /admin path
curl http://paths-XX.$INGRESS_IP.nip.io/admin
# Test root path (should return 404 — no rule for /)
curl http://paths-XX.$INGRESS_IP.nip.io/
Expected results:
/appreturns:This is the APP service (student-XX)/adminreturns:This is the ADMIN service (student-XX)/returns: 404 Not Found (no matching rule)
Clean Up
kubectl delete -f path-routing-ingress.yaml
kubectl delete -f path-routing-apps.yaml
Common Problems
| Problem | Possible Cause | Solution |
|---|---|---|
| Both paths return the same response | Service names or selectors are mixed up | Verify each Service points to the correct Deployment with kubectl describe svc |
| 404 on a valid path | Host header does not match the Ingress rule | Ensure the hostname in the URL matches exactly; check with curl -v |
/app works but /app/subpath does not |
Unexpected behavior | With pathType: Prefix, subpaths should work. Check the backend application handles subpaths |
Root path / returns 404 |
No rule defined for / |
Add a default backend or a path rule for / if needed |
Best Practices
- Order paths from most specific to least specific — NGINX evaluates paths by length, longest match first, but explicit ordering improves readability.
- Always test with curl — Browser caching can hide routing issues. Use
curl -vto see the actual request and response headers. - Be aware of trailing slashes —
/appand/app/may behave differently depending on the backend application. Test both. - Use path-based routing for related services — Services that belong to the same application domain (e.g., app + admin + API) are good candidates for path-based routing.
- Consider rewrite rules for backend compatibility — If your backend expects requests at
/but receives them at/app, you will need URL rewriting (covered in the next exercise).
Summary
In this exercise you learned:
- Path-based routing allows multiple Services to share a single hostname and external IP
- Each path in an Ingress rule routes to a different backend Service
pathType: Prefixmatches the path and all sub-paths- This pattern is commonly used in microservices architectures to reduce cost and simplify DNS
- Requests that do not match any path rule return 404
- How to create and test an Ingress with multiple path-based routing rules