Skip to content

4. Ingress

A Service gives a set of pods one stable virtual address inside the cluster. The Ingress is the ingress of the palette: the door from the outside world, routing HTTP requests by host and path to Services β€” the Kubernetes counterpart of the Nginx edge of lab 3.

The path of a request

flowchart LR
    curl["curl localhost/catalog/events/1"] -->|"host :80 β†’ node :30080 (kind.yaml)"| node[control-plane node]
    node -->|NodePort Service| traefik[Traefik pod]
    traefik -->|"rule /catalog β†’ Service catalog:8082"| svc[Service catalog]
    svc -->|"one of the READY endpoints"| p1[catalog pod 1]
    svc --> p2[catalog pod 2]

Traefik watches the Kubernetes API: when an Ingress (or a pod's readiness) changes, its routing table changes within seconds, with no reload. It sends traffic directly to the ready pod endpoints of the Service, so a pod that fails its readiness probe stops receiving requests from the edge too.

The rule

k8s/base/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: boxoffice
spec:
  ingressClassName: traefik
  rules:
    - http:
        paths:
          - path: /catalog
            pathType: Prefix
            backend:
              service:
                name: catalog
                port:
                  name: http

The Gateway API is the successor of Ingress: the same idea, split by role β€” the platform team owns the Gateway (ports, TLS), each service team owns its HTTPRoute β€” with features Ingress only had as vendor annotations (header matching, traffic splitting by weight, timeouts). Enable it in Traefik, which then creates a GatewayClass named traefik and a default Gateway named traefik-gateway listening on its web entry point:

# the Gateway API is a set of CRDs: install the version the Traefik chart recommends
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.2/standard-install.yaml
helm upgrade traefik traefik/traefik --version 42.0.0 --namespace traefik --reuse-values \
  --set providers.kubernetesGateway.enabled=true \
  --set gateway.listeners.web.namespacePolicy.from=All
kubectl get gatewayclass,gateway -A     # ACCEPTED / PROGRAMMED = True
k8s/base/catalog-route.yaml
# Alternative to ingress.yaml with the Gateway API (use one or the other for /catalog)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: catalog
spec:
  parentRefs:
    - name: traefik-gateway          # the default Gateway created by the Traefik chart
      namespace: traefik
      sectionName: web
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /catalog
      backendRefs:
        - name: catalog
          port: 8082

To switch, replace ingress.yaml with catalog-route.yaml in k8s/base/kustomization.yaml, apply again and delete the old rule (kubectl apply never deletes what you removed from the files):

kubectl apply -k k8s/overlays/local
kubectl -n boxoffice delete ingress boxoffice
curl -s -o /dev/null -w '%{http_code}\n' localhost/catalog/events/1   # 200, now through the HTTPRoute

Use either the Ingress or the HTTPRoute for /catalog, not both.

Ingress, Service of type LoadBalancer, or API gateway?

A LoadBalancer Service gives one service its own external address (in the cloud, one cloud load balancer each β€” and one bill each). An Ingress shares one entry point among many services with HTTP routing. An API gateway (Spring Cloud Gateway in lab 4) adds application concerns β€” authentication, rate limits per user, request transformation. A typical production path is cloud load balancer β†’ Ingress/Gateway β†’ API gateway β†’ services.

Check the routing

curl -s -o /dev/null -w '%{http_code}\n' localhost/catalog/events/1        # 200: routed
curl -s -o /dev/null -w '%{http_code}\n' localhost/nothing-here            # 404: no rule matches
for i in $(seq 1 6); do curl -s -D - -o /dev/null localhost/catalog/events/1 | grep -i x-instance; done

If catalog still sets the X-Instance header of lab 3, the last command shows the requests spread over the pods: the pod name is the container hostname.

Next: Measure it