22: Ingress Basics
22: Ingress Basics
Objective
Understand what a Kubernetes Ingress is, how it differs from a LoadBalancer Service, and how to use the managed NGINX Ingress Controller provided by the AKS application routing add-on to expose an application via HTTP.
Theory
What Is Ingress?
An Ingress is a Kubernetes resource that manages external HTTP/HTTPS access to Services within the cluster. Unlike a LoadBalancer Service that provides a dedicated external IP per Service, an Ingress allows you to:
- Route traffic to multiple Services through a single external IP
- Route based on hostname and URL path
- Terminate TLS/SSL at the edge
- Apply annotations for advanced traffic management (rewrites, rate limiting, etc.)
Ingress vs LoadBalancer Service
| Feature | LoadBalancer Service | Ingress |
|---|---|---|
| External IP | One per Service | One shared across many Services |
| Routing | By port only | By hostname and/or path |
| Protocol | TCP/UDP (any) | HTTP/HTTPS |
| TLS termination | Not built-in | Built-in |
| Cost | One Azure LB per Service | One Azure LB for all Ingress routes |
IngressClass
Kubernetes supports multiple Ingress Controllers in the same cluster. The IngressClass specifies which controller should handle a particular Ingress resource.
AKS Application Routing Add-on
AKS provides a managed NGINX Ingress Controller through the application routing add-on:
- Deployed automatically in the
app-routing-systemnamespace - Managed and updated by AKS — no manual Helm chart management
- IngressClassName:
webapprouting.kubernetes.azure.com - Provides an Azure Load Balancer with a public IP
Rules: Host and Path
An Ingress rule consists of:
- Host — the hostname to match (e.g.,
myapp.example.com) - Path — the URL path to match (e.g.,
/api) - pathType — how the path is matched:
Prefix— matches the path prefix (e.g.,/apimatches/api,/api/users,/api/v2)Exact— matches the exact path only (e.g.,/apimatches only/api, not/api/users)
Ingress Architecture
graph LR
Internet["Internet<br/>(Browser / curl)"]
LB["Azure Load Balancer<br/>(Public IP)"]
subgraph AKS["AKS Cluster"]
subgraph ARS["app-routing-system namespace"]
IC["NGINX Ingress Controller"]
end
subgraph NS["student-XX namespace"]
ING["Ingress Resource<br/>host: basic-XX.IP.nip.io<br/>path: /"]
SVC["Service<br/>echo-server-XX"]
P1["Pod 1"]
P2["Pod 2"]
end
IC -->|"matches host/path"| ING
ING -->|"routes to"| SVC
SVC --> P1
SVC --> P2
end
Internet --> LB
LB --> IC
style ARS fill:#e1f5fe,stroke:#0288d1,stroke-width:1px
style NS fill:#e8f5e9,stroke:#388e3c,stroke-width:1px
Practical Tasks
Task 1: Get the NGINX Ingress Controller External IP
First, verify the managed NGINX Ingress Controller is running:
kubectl get pods -n app-routing-system
Get the external IP of the NGINX Ingress Controller:
INGRESS_IP=$(kubectl get svc -n app-routing-system nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "Ingress IP: $INGRESS_IP"
Save this IP — you will use it for the hostname with nip.io (a wildcard DNS service that maps <anything>.<IP>.nip.io to that IP).
Task 2: Create an Echo Server Deployment and Service
Create a file called echo-server.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-server-XX
namespace: student-XX
labels:
app: echo-server-XX
spec:
replicas: 2
selector:
matchLabels:
app: echo-server-XX
template:
metadata:
labels:
app: echo-server-XX
spec:
containers:
- name: echo
image: hashicorp/http-echo
args:
- "-text=Hello from student-XX!"
ports:
- containerPort: 5678
resources:
requests:
cpu: "50m"
memory: "32Mi"
limits:
cpu: "100m"
memory: "64Mi"
---
apiVersion: v1
kind: Service
metadata:
name: echo-server-XX
namespace: student-XX
spec:
selector:
app: echo-server-XX
ports:
- port: 80
targetPort: 5678
Deploy:
kubectl apply -f echo-server.yaml
kubectl get pods -n student-XX -l app=echo-server-XX
Task 3: Create an Ingress Resource
Create a file called echo-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo-ingress-XX
namespace: student-XX
spec:
ingressClassName: webapprouting.kubernetes.azure.com
rules:
- host: basic-XX.INGRESS_IP.nip.io # Replace INGRESS_IP with actual IP
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: echo-server-XX
port:
number: 80
Important: Replace
INGRESS_IPin the host field with the actual IP address from Task 1. For example, if the IP is20.73.100.50, the host becomesbasic-XX.20.73.100.50.nip.io.
Apply the Ingress:
kubectl apply -f echo-ingress.yaml
Task 4: Verify the Ingress
Check the Ingress status:
kubectl get ingress -n student-XX
Wait until the ADDRESS column shows an IP address. This may take a minute.
Test with curl:
curl http://basic-XX.$INGRESS_IP.nip.io
Expected output:
Hello from student-XX!
You can also open this URL in your browser.
Clean Up
kubectl delete -f echo-ingress.yaml
kubectl delete -f echo-server.yaml
Useful Commands
| Command | Description |
|---|---|
kubectl get ingress -n student-XX |
List Ingress resources in your namespace |
kubectl describe ingress echo-ingress-XX -n student-XX |
Detailed Ingress info including rules and events |
kubectl get svc -n app-routing-system |
Check the NGINX Ingress Controller Service |
kubectl get ingressclass |
List available IngressClasses in the cluster |
kubectl logs -n app-routing-system -l app=nginx --tail=50 |
View NGINX Ingress Controller logs |
Common Problems
| Problem | Possible Cause | Solution |
|---|---|---|
| Ingress shows no ADDRESS | Ingress Controller has not picked it up yet | Wait a minute; verify IngressClassName is correct |
| 404 Not Found | Host or path does not match any Ingress rule | Verify the host header matches the Ingress rule; check curl is using the correct hostname |
| Wrong IngressClass | Using a different IngressClassName | Must use webapprouting.kubernetes.azure.com for the managed NGINX controller |
| 503 Service Unavailable | Backend Service has no healthy endpoints | Check that the Service selector matches Pod labels and Pods are Running |
| nip.io does not resolve | DNS resolution issue | Try using the IP directly with a Host header: curl -H "Host: basic-XX.IP.nip.io" http://IP |
Best Practices
- Always specify
ingressClassName— Without it, the Ingress may not be picked up by any controller, or the wrong controller may handle it. - Use meaningful hostnames — Even with nip.io for testing, structure hostnames to identify the application and environment.
- Prefer
PrefixpathType for most use cases —Exactis rarely needed and can cause confusion when sub-paths do not match. - Monitor Ingress Controller logs — When debugging routing issues, the NGINX Ingress Controller logs in
app-routing-systemprovide detailed information. - One Ingress per application — While you can combine rules, separate Ingress resources per application are easier to manage and debug.
Summary
In this exercise you learned:
- An Ingress provides HTTP/HTTPS routing to Services through a single external IP
- The difference between an Ingress and a LoadBalancer Service
- AKS provides a managed NGINX Ingress Controller via the application routing add-on
- The IngressClassName for the managed controller is
webapprouting.kubernetes.azure.com - How to create an Ingress with host-based routing using nip.io for DNS
- How to verify and troubleshoot Ingress resources