Lesson  in  Kubernetes 101

Ingress

From the open port to professional HTTP routing: publish the application behind the Traefik Ingress controller that k3s ships with, with rules per host name.

The NodePort from the previous lesson works, but picture twenty applications: twenty random ports to document, no centralized TLS, no routes by name. Kubernetes's answer to incoming HTTP traffic is the Ingress: an object where you declare rules like "requests for host X go to Service Y", and an Ingress controller that makes them real.

The important detail: the Ingress object does nothing on its own, it needs a controller to interpret it. Here the playground plays in your favor: k3s ships Traefik as its Ingress controller out of the box, listening on port 80 of every node. Check it from the dev-machine tab:

kubectl get pods -n kube-system -l app.kubernetes.io/name=traefik
kubectl get ingressclass

That IngressClass called traefik (marked as default) is what will connect your rules with the controller.

Step 1: Backend and Service

An Ingress routes to Services, so first bring up the base. Again, with no guidance: create a Deployment web (1 replica of ghcr.io/iximiuz/labs/nginx:alpine, label app: web, port 80) and a ClusterIP Service web that selects it on port 80.

Hint: neither of the two pieces needs YAML

kubectl create knows how to create a Deployment and a Service directly, with the image, the port and the replicas as flags. And for the Service there is an even better shortcut: kubectl expose starts from an object that already exists and inherits its selector, which is exactly what you have to get right here.

Step 2: The Ingress

You can find the file at manifests/ingress.yaml:

ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  rules:
  - host: app.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web
            port:
              number: 80

The YAML, explained in questions and answers

Yet another API group?

Yes: networking.k8s.io/v1, the group of the networking resources (Ingress, NetworkPolicy). With this one you have seen the big four: core, apps, batch and networking.

What role does host play?

It is the condition of the rule: only HTTP requests whose Host header is app.local trigger it. That way a single entry point on port 80 can serve dozens of different applications, one per name.

What does pathType: Prefix mean?

How to compare the path with the URL of the request. Prefix matches / and everything hanging from it; the alternative, Exact, demands a literal match. Declaring it is mandatory.

Why is the backend a Service and not my Pods?

Because the Ingress delegates to the machinery you already know: the controller routes to the Service, and the Service spreads among its endpoints. Each piece does a single job.

Isn't it missing which controller it uses?

There is the ingressClassName field to choose it explicitly. We leave it out because k3s marks the traefik class as default; in a cluster with several controllers you would always declare it.

Apply it:

kubectl apply -f manifests/ingress.yaml
kubectl get ingress

Step 3: The test from outside

The host app.local does not exist in any DNS, so simulate what the browser would do by sending the header by hand. From dev-machine:

curl -H "Host: app.local" http://cplane-01/

And the negative test, which is where the Ingress makes sense: the same request without the right header.

curl -i http://cplane-01/

A 404 from Traefik. The controller receives everything that arrives on port 80, but only routes what matches some rule.

And to see it as a user would, open the app.local tab: there is your application. That tab points at port 80 of cplane-01 and adds the Host: app.local header for you, which is exactly what you just did by hand with curl -H. Without that rewrite it would get the same 404 as the negative test.

Summary

  • The Ingress declares HTTP rules (host and path toward a Service); the Ingress controller executes them.
  • Without a controller, an Ingress is just a decorative object. k3s solves this by shipping Traefik out of the box.
  • A single entry point on 80/443 replaces one NodePort per application, and it is where TLS gets centralized.
  • The book also covers the evolution of this idea, the Gateway API; with what you learned here, reading it will feel natural.
Next lesson
Gateway API