Skip to content

Ingress — Full Reference

Reference: https://kubernetes.io/docs/concepts/services-networking/ingress/


Exam Priority — Quickest Path

No imperative command for Ingress — always YAML. Generate a scaffold from docs or dry-run an existing resource:

# Get the template from the docs page:
# kubernetes.io/docs/concepts/services-networking/ingress → Ctrl+F "pathType"

# Or copy an existing ingress as a starting point:
kubectl get ingress <name> -o yaml > ingress.yaml

The minimum YAML you need (memorise this structure):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /shop
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80

What Is Ingress and Why It Exists

You have services running inside the cluster. ClusterIP = internal only. NodePort = one port per service on every node, messy. LoadBalancer = needs a cloud provider.

Ingress is a single entry point that routes external HTTP/HTTPS traffic to different services based on rules.

External traffic
  Ingress (one IP, one entry point)
  /api   → api-service:80
  /web   → web-service:80
  /shop  → shop-service:80

Without Ingress: 3 services = 3 NodePorts = 3 different ports to manage, document, and secure. With Ingress: one entry point, routing rules decide where traffic goes.

Three separate things — all required:

Thing What it is Required?
Ingress resource The YAML you write. Just routing rules. Does nothing on its own. Yes
Ingress controller The actual software (nginx, traefik, etc.) that reads the rules and does the routing. Must be installed separately. Yes
Service Ingress routes TO a Service, not directly to pods. Yes

Creating an Ingress resource without an Ingress controller installed = nothing happens. The resource gets created, kubectl apply succeeds, but no traffic gets routed.


Ingress Resource — Full YAML

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress-resource
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"    # disable HTTPS redirect
    nginx.ingress.kubernetes.io/rewrite-target: /        # rewrite path before forwarding
spec:
  ingressClassName: nginx        # which ingress controller handles this — MUST match

  rules:
  - host: myapp.example.com      # optional — only route this hostname (omit for all traffic)
    http:
      paths:
      - path: /shop
        pathType: Prefix         # Prefix | Exact | ImplementationSpecific
        backend:
          service:
            name: nginx-service
            port:
              number: 80

  tls:                           # optional — TLS termination
  - hosts:
    - myapp.example.com
    secretName: my-tls-secret    # Secret with tls.crt and tls.key

ingressClassName — The #1 Mistake

# WRONG — this is YOUR resource name, not the controller class
ingressClassName: nginx-ingress-resource

# CORRECT — must match the installed controller's class name
ingressClassName: nginx

ingressClassName tells the Ingress controller "hey, you're responsible for this resource." If it doesn't match, the controller ignores your Ingress completely.

Find what's installed:

kubectl get ingressclass
Output:
NAME    CONTROLLER
nginx   k8s.io/ingress-nginx

Use nginx (or whatever name is shown) as your ingressClassName.

KillerCoda vs real cluster: KillerCoda's checker validates that your Ingress YAML has the right spec fields. It doesn't test actual traffic routing. So even with the wrong ingressClassName, you might pass the KillerCoda check — but in a real cluster, traffic would never route.


pathType — Three Options

pathType Behaviour
Prefix Matches the path and anything under it. /shop matches /shop, /shop/, /shop/products
Exact Matches only the exact path. /shop matches /shop only, not /shop/
ImplementationSpecific Behaviour depends on the Ingress controller

For the exam: Prefix is the most common. Use Exact when the question specifies it.


Annotations

Annotations are how you configure Ingress controller-specific behaviour. They live in metadata.annotations.

annotations:
  nginx.ingress.kubernetes.io/ssl-redirect: "false"      # disable HTTP→HTTPS redirect
  nginx.ingress.kubernetes.io/rewrite-target: /          # rewrite path to / before forwarding
  nginx.ingress.kubernetes.io/proxy-body-size: "10m"     # max request body size
  nginx.ingress.kubernetes.io/proxy-read-timeout: "60"   # timeout in seconds

Why strings for booleans? "false" not false. All annotation values are strings in Kubernetes. Even booleans must be quoted.


Routing Patterns

Single service (no host, no path matching)

spec:
  ingressClassName: nginx
  defaultBackend:
    service:
      name: my-service
      port:
        number: 80
All traffic → my-service.

Path-based fanout (one host, multiple services)

spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80
      - path: /web
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

Host-based routing (multiple hostnames)

spec:
  ingressClassName: nginx
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80
  - host: web.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

TLS termination

spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - myapp.example.com
    secretName: my-tls-secret     # kubectl create secret tls my-tls-secret --cert=... --key=...
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

The Exercise — Full Solution

Create nginx-ingress-resource: pathType Prefix, path /shop, backend service nginx-service port 80, ssl-redirect false.

# 1. Check what ingress controller class is installed
kubectl get ingressclass

# 2. Create the YAML
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress-resource
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /shop
        pathType: Prefix
        backend:
          service:
            name: nginx-service
            port:
              number: 80
EOF

# 3. Verify
kubectl get ingress nginx-ingress-resource
kubectl describe ingress nginx-ingress-resource

Inspecting Ingress

kubectl get ingress
kubectl get ingress -A                             # all namespaces
kubectl describe ingress my-ingress               # rules, backend, events
kubectl get ingressclass                          # what controllers are installed

kubectl describe ingress shows you the full routing table and any events (like the controller ignoring it due to wrong ingressClassName).


Docs Bookmark

URL: kubernetes.io/docs/concepts/services-networking/ingress

Ctrl+F for: pathType — takes you straight to the fanout example YAML. Copy it, edit 4-5 fields, apply.


Quick Reference

# No imperative command — always YAML
kubectl apply -f ingress.yaml
kubectl get ingress
kubectl describe ingress <name>
kubectl get ingressclass                          # find correct ingressClassName value
kubectl delete ingress <name>

# Generate from existing
kubectl get ingress <name> -o yaml > ingress.yaml

Minimum fields checklist: - apiVersion: networking.k8s.io/v1 - kind: Ingress - metadata.name - spec.ingressClassName ← must match kubectl get ingressclass output - spec.rules[].http.paths[].path - spec.rules[].http.paths[].pathType - spec.rules[].http.paths[].backend.service.name - spec.rules[].http.paths[].backend.service.port.number