Skip to main content

Ingress: Routing

Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource.

Ingress - Kubernetes Official Docs

*Kubernetes Official Docs

Ingress provides a single entry point that routes requests to different services based on:

  • Hostnames (e.g., app.example.com)
  • Paths (e.g., /api, /web)
  • TLS Settings (for HTTPS)
  • Annotations (for additional behavior like rewrites, redirects, etc.)

There are many use cases that utilize ingress such as TLS, Force HTTPS, Force Redirect, Basic Authentication, Rate Limiting, IP Whitelisting, etc. But for now lets focus on basic implementation that is for traffic routing.

Enable Minikube Ingress Addons

To enable ingress in minikube we need to enable the addons first.

➜ minikube addons enable ingress
💡 ingress is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
💡 After the addon is enabled, please run "minikube tunnel" and your ingress resources would be available at "127.0.0.1"
▪ Using image registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.3
▪ Using image registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.3
▪ Using image registry.k8s.io/ingress-nginx/controller:v1.11.2
🔎 Verifying ingress addon...
🌟 The 'ingress' addon is enabled

To validate if ingress controller already running we can use command kubectl get pods -n ingress-nginx. It can take up to a minute before you see these pods running.

➜ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-fmhdk 0/1 Completed 0 2m40s
ingress-nginx-admission-patch-zxmgn 0/1 Completed 0 2m40s
ingress-nginx-controller-bc57996ff-rz4wd 1/1 Running 0 2m40s

Create Ingress

Lets expose our simple-go service to outside using ingress we defined below. Create new file ingress.yaml and put the ingress definition there.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-ingress
spec:
ingressClassName: nginx
rules:
- host: simple-go.mine
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: simple-go
port:
number: 8080

This will create ingress object with name simple-ingress using nginx. There are others ingressClassName such as Traefik, HAProxy, Istio, etc. But in this case we will use nginx.

In the rules section we can define rules for this ingress. An Ingress rule defines how incoming HTTP(S) traffic is routed inside a Kubernetes cluster.

  • host: Specifies which domain should match (optional).
  • paths.path: Defines the URL path that should be routed.
  • paths.pathType: Type of path matching (more details below). For full list of path type you can read further here: Path Type Example.
  • backend.service.name: The name of the Kubernetes service to route traffic to.
  • backend.service.port.number: The service port to forward traffic to.

So in our ingress definition we want to match all traffic for domain simple-go.mine to service with name simple-go and port 8080.

Lets apply our ingress definition and validate if on the list.

➜ kubectl apply -f ingress.yaml 
ingress.networking.k8s.io/simple-ingress created
➜ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
simple-ingress nginx simple-go.mine 192.168.49.2 80 15s

Test Ingress

Because I'm using MacOS (Minikube with Docker Driver) I need to do tunneling first using command minikube tunnel. It will tunnel all localhost traffic for port 80 and 443 to the minikube.

➜ minikube tunnel
✅ Tunnel successfully started

📌 NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible ...

❗ The service/ingress simple-ingress requires privileged ports to be exposed: [80 443]
🔑 sudo permission will be asked for it.
🏃 Starting tunnel for service simple-ingress.

After tunneling started we then can access is using the curl command below.

curl --resolve "simple-go.mine:80:127.0.0.1" -i http://simple-go.mine
HTTP/1.1 200 OK
Date: Fri, 31 Jan 2025 03:37:49 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 65
Connection: keep-alive

[{"id":1,"content":"Hello!"},{"id":2,"content":"Good Morning!"}]

You can try to change the path and domain to see what changes does it makes.

References