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:

  • /app routes to the main application Service
  • /admin routes to the admin panel Service
  • /api routes 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_IP with 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:

  • /app returns: This is the APP service (student-XX)
  • /admin returns: 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

  1. Order paths from most specific to least specific — NGINX evaluates paths by length, longest match first, but explicit ordering improves readability.
  2. Always test with curl — Browser caching can hide routing issues. Use curl -v to see the actual request and response headers.
  3. Be aware of trailing slashes/app and /app/ may behave differently depending on the backend application. Test both.
  4. 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.
  5. 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: Prefix matches 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

results matching ""

    No results matching ""