Guide

Ingress: Route a Hostname to a Service

Part 4 of 7By Amith Kumar7 min read
Part 4 of 7k3s: Kubernetes on One VM
  1. 1Install k3s and Your First Pod
  2. 2Pods, Deployments and Self-Healing
  3. 3Services and Networking
  4. 4Ingress: Route a Hostname to a Service
  5. 5Config and Secrets
  6. 6Persistent Storage, Limits and Probes
  7. 7Operations, Upgrades and Backup
Verified 22 Jul 2026 · Ubuntu 24.04 LTS · nginx 1.27

A Kubernetes Ingress that routes a hostname

A Kubernetes Ingress is a rule that maps a hostname or path to a Service, so many sites can share one entry point instead of each grabbing a node port. This is the payoff chapter, run on the live k3s node: you install the Traefik ingress controller you skipped at setup, write an Ingress that sends beacon.example.com to the Beacon Service, and then open the app in a browser served entirely by the cluster.

A Service exposes pods to the cluster; an Ingress decides which Service a request should reach based on its host, and it is the last piece Beacon needs to face the outside world.

Key takeaways
  • An Ingress resource is only a set of routing rules. A controller such as Traefik must be running to act on them.
  • Rules match on hostname and path, so one address can serve many apps by sending each host to its own Service.
  • The controller watches the API for Ingress objects and reconfigures itself the moment one changes.
  • A request that matches no rule gets a 404 from the controller, which is a clean signal that routing, not the app, turned it away.

On a single slice you often already run something on ports 80 and 443, such as a plain web server. That is why chapter one disabled the bundled controller and load balancer. So here the Traefik controller is installed as an internal Service and reached with a port-forward, which keeps it clear of anything else on the host. The Ingress rules and the routing are exactly the same as a setup that owns the public ports. Only the last hop, how traffic first reaches Traefik, differs.

Prerequisites

Before you start
  • The beacon Service from part three, backed by three healthy pods.
  • A cluster that can still reach the internet, since installing the controller pulls the Traefik chart and image.
  • Nothing extra bound inside the cluster on port 8081, the local port used for the port-forward at the end.

Install the ingress controller

Because you disabled the bundled Traefik in chapter one, install it now on your own terms. k3s ships a helm-controller, so applying a small HelmChart object installs the Traefik chart with no separate helm binary.

kubectl apply -f - <<'EOF'
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: traefik
  namespace: kube-system
spec:
  repo: https://traefik.github.io/charts
  chart: traefik
  targetNamespace: kube-system
EOF
kubectl -n kube-system rollout status deploy/traefik

Give it a moment and kubectl -n kube-system get deploy traefik reports the controller ready. Its Service asks for a load balancer, but because you disabled k3s's built-in one, the external address stays pending. That is deliberate and harmless here: you never wanted Traefik on the host's public ports. You reach it through a port-forward instead, which is all a single learning slice needs.

Checkpoint

You should see the traefik Deployment in kube-system reporting one pod ready. A pending external IP on its Service is expected, not an error, since the built-in load balancer is off.

Write the Ingress rule

Save this as beacon-ingress.yaml. It says that any request for the host beacon.example.com on path / should go to the beacon Service on port 80.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: { name: beacon }
spec:
  rules:
    - host: beacon.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: beacon
                port: { number: 80 }

Apply it and read the object back.

kubectl apply -f beacon-ingress.yaml
kubectl get ingress beacon
kubectl describe ingress beacon
kubectl apply creating an Ingress, kubectl get ingress showing the host beacon.example.com on the traefik class, and describe listing the rule that sends that host to the beacon Service

kubectl get ingress beacon shows the host beacon.example.com on the traefik class. kubectl describe prints the rule and, under Backends, the three pod IPs the Service resolves to. The Ingress does not carry traffic itself. It is a record in the API that the controller reads and turns into live routing. Delete the Traefik controller and this object still exists, but nothing acts on it.

Curl the app through the Ingress

Traefik here listens inside the cluster, so forward a local port to it and send a request with the ingress hostname in the Host header.

kubectl -n kube-system port-forward svc/traefik 8081:80 &
curl -sI -H "Host: beacon.example.com" http://127.0.0.1:8081/
curl -sI http://127.0.0.1:8081/
A port-forward to the Traefik controller, then a curl with the ingress hostname returning HTTP 200 with the nginx server header, proving the request routed through the Ingress to the pods
The Beacon cluster status board served by the nginx Deployment and reached through the Traefik Ingress, showing three replicas behind one Service, open in a browser

The first curl carries the right Host header and returns HTTP/1.1 200 OK with a Server: nginx header, which proves the request travelled through Traefik, matched the rule, and landed on a Beacon pod. The second curl has no matching host and gets a 404 straight from Traefik, before any app is involved. That contrast is the point of an Ingress: the same controller, the same port, but the hostname decides where a request goes.

Reading the result

A 200 with an nginx server header means the whole path worked: Traefik matched the host, the Service load-balanced to a pod, and the pod served the page. A 404 from Traefik means routing rejected the request, which is different from the app returning its own error.

See Beacon live in a browser

This is the moment the series was building toward. With the port-forward still running, open http://127.0.0.1:8081/ in a browser with the same host header, or point a beacon.example.com line at it in your hosts file and visit that. Up comes the Beacon status board, the exact page you saw promised in chapter one, now genuinely served by Kubernetes: three nginx pods behind one Service, routed by a hostname through the Traefik Ingress, with no public port opened on the host by hand.

Nothing about this page is a mock. The bytes came from a pod, chosen by the Service, reached through the Ingress. You are looking at your own cluster answering a browser. That is real Kubernetes, running on one slice, doing the one job a web app exists to do.

Going further: TLS and many hosts on one ingress

The same Ingress scales past one site. Add more entries under rules, each with its own host and its own backend Service, and the single controller routes them all from one entry point.

TLS slots in the same way: an Ingress can terminate HTTPS by referencing a secret that holds a certificate and key for the host, and the controller then serves that host over 443. Certificates are their own topic, covered in the TLS and Certificates series, and they pair cleanly with an Ingress once the plain routing works. On a slice that owns its public ports, you would let Traefik bind 80 and 443 directly instead of port-forwarding, and everything above the last hop stays identical.

Frequently asked questions

Why does my Ingress do nothing after I apply it?

An Ingress needs a controller. If no controller is running, the rules sit in the API with nothing to enforce them. Install Traefik or another controller, confirm its pod is Running, then the routing takes effect. In this series you install Traefik yourself because chapter one disabled the bundled one.

Do I need a NodePort if I have an Ingress?

No. Once traffic reaches the Service through the Ingress, a NodePort is redundant for that path. Ingress backends target the Service directly. Keep a NodePort only if you have a separate reason to expose a fixed node port, such as a quick internal test.

Can one Ingress serve several hostnames?

Yes. Add more entries under rules, each with its own host and backend Service. That is the main reason to use an Ingress: many sites share one entry point, and each hostname routes to its own app without extra ports.

How does TLS fit in?

An Ingress can terminate HTTPS by referencing a TLS secret that holds a certificate and key for the host. The controller then serves that host over 443. Certificates are their own topic, covered in the TLS and Certificates series, and pair cleanly with an Ingress once routing works.

What you have, and what comes next

You installed a controller, wrote an Ingress that maps a hostname to a Service, curled the app through it for a 200 while a non-matching host got a clean 404, and opened Beacon live in a browser served by the cluster. That is real host-based routing on a single node, the same model a large cluster uses.

The app serves a fixed page today. Real apps need settings and secrets that differ by environment. The next chapter feeds the pod its configuration through a ConfigMap and a Secret, and shows the app reading them with the secret kept out of view.


Run k3s on your own slice

Run Kubernetes on a single slice

Real Kubernetes for the price of one box. Launch a slice, install k3s from this guide, and run deployments, ingress and storage with self-healing.

Get early access

This guide is provided for educational purposes and offered as is, without warranty of any kind. The commands change the configuration of a server you control, and some can lock you out if run out of order. Test on a non-production machine, keep a second session open, and take a snapshot or backup before you begin. You are responsible for changes made to your own systems; ServerCake accepts no liability for any loss, downtime, lockout, or damage arising from following this guide or running the accompanying script.

Was this guide helpful?
Share

Spotted something out of date or have a question?

Built by the ServerCake team

Cloud that speaks India.

ServerCake is India's KYC-verified cloud: VMs and managed databases priced in ₹, billed with GST, on India-resident infrastructure. Reserve your spot for early access.

Reserve your spot