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-system namespace
  • 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., /api matches /api, /api/users, /api/v2)
    • Exact — matches the exact path only (e.g., /api matches 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_IP in the host field with the actual IP address from Task 1. For example, if the IP is 20.73.100.50, the host becomes basic-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

  1. Always specify ingressClassName — Without it, the Ingress may not be picked up by any controller, or the wrong controller may handle it.
  2. Use meaningful hostnames — Even with nip.io for testing, structure hostnames to identify the application and environment.
  3. Prefer Prefix pathType for most use casesExact is rarely needed and can cause confusion when sub-paths do not match.
  4. Monitor Ingress Controller logs — When debugging routing issues, the NGINX Ingress Controller logs in app-routing-system provide detailed information.
  5. 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

results matching ""

    No results matching ""