A Kubernetes Ingress gives an HTTP route to a Service through the cluster's ingress controller. It is useful when a workload already has a stable Service and needs host or path routing without creating a separate external load balancer for every Service.

Ingress rules are stored as networking.k8s.io/v1 API objects. The ingressClassName value selects the controller that should implement the rule. A host rule matches the request's Host header, so an IP-only request can reach the controller without matching the application.

The backend Service and a reachable Traefik controller must already exist. DNS and TLS are separate from creating and testing the HTTP route, and the Service must be in the same namespace as the Ingress.

Steps to create a Kubernetes Ingress:

  1. List the available Ingress classes.
    $ kubectl get ingressclass
    NAME                CONTROLLER                      PARAMETERS   AGE
    traefik (default)   traefik.io/ingress-controller   <none>       2m37s

    The traefik class belongs to the Traefik controller. If it is absent, Traefik's Helm chart installation instructions provide defaults with the traefik class, Kubernetes Ingress support and HTTP on port 80. The ingressClassName field replaces the older kubernetes.io/ingress.class annotation for normal Ingress selection.

  2. Confirm that Service web exposes port 80 in the default namespace.
    $ kubectl get service web --namespace default
    NAME   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
    web    ClusterIP   10.43.36.200   <none>        80/TCP    2m28s

    The rule targets the Service port, which can differ from the Pod's listening port. The commands use the default namespace throughout.
    Related: How to create a Kubernetes Service

  3. Check that the Service has ready endpoints.
    $ kubectl describe endpointslice --namespace default -l kubernetes.io/service-name=web
    Name:         web-vj5lx
    Namespace:    default
    ##### snipped #####
    AddressType:  IPv4
    Ports:
      Name     Port  Protocol
      ----     ----  --------
      <unset>  80    TCP
    Endpoints:
      - Addresses:  10.42.0.7
        Conditions:
          Ready:    true
        Hostname:   <unset>
        TargetRef:  Pod/web-85787c857b-p2nvb
        NodeName:   ingress-create-node
        Zone:       <unset>
    Events:         <none>

    An Ingress can be created before endpoints exist, but the backend cannot serve requests until the Service has ready Pods.
    Related: How to troubleshoot a Kubernetes Service

  4. Create Ingress web for app.example.com with the traefik class.

    This rule exposes every application path to clients that can reach Traefik. HTTP provides no encryption, and the Ingress adds no authentication. If the route exposes an unintended application, kubectl delete ingress web --namespace default removes this route without deleting the Service or Pods.

    $ kubectl create ingress web --namespace default --class=traefik --rule="app.example.com/*=web:80"
    ingress.networking.k8s.io/web created

    The /* rule creates a Prefix path for /, matching the root and its child paths.

  5. Inspect the saved Ingress rule and backend mapping.
    $ kubectl describe ingress web --namespace default
    Name:             web
    Labels:           <none>
    Namespace:        default
    Address:          172.21.0.2
    Ingress Class:    traefik
    Default backend:  <default>
    Rules:
      Host             Path  Backends
      ----             ----  --------
      app.example.com
                       /   web:80 (10.42.0.7:80)
    Annotations:       <none>
    Events:            <none>

    The Address field may stay empty until the controller publishes an address. A populated address does not prove that the backend answers HTTP requests.

  6. Set the controller address reachable from your client.
    $ INGRESS_ADDRESS=172.21.0.2

    The value here is the observed Address. Other clusters may advertise a different IP or hostname, or require the controller's load balancer endpoint. The Service's ClusterIP is not the Ingress address.

  7. Request the root path through Traefik with the app.example.com Host header.
    $ curl -fsS -H 'Host: app.example.com' "http://$INGRESS_ADDRESS/"
    Hostname: web-85787c857b-p2nvb
    IP: 127.0.0.1
    IP: ::1
    IP: 10.42.0.7
    IP: fe80::b016:8fff:fe41:7335
    RemoteAddr: 10.42.0.6:48248
    GET / HTTP/1.1
    Host: app.example.com
    ##### snipped #####

    This backend returns its Pod hostname and request details. The response identifies web-85787c857b-p2nvb, the ready endpoint above; another application will return its own content. The Host header tests the rule before DNS is configured. The -f option makes HTTP errors fail the command. Traefik can take a few seconds to load a new rule; if the first request returns 404, retry after that interval. A persistent failure belongs in How to troubleshoot Kubernetes Ingress.

Share this guide