Zum Inhalt

Lab 20: Ingress auf Minikube

Dieses Lab demonstriert, wie man einen Ingress verwendet, um HTTP-Traffic anhand von Hostnamen und Pfaden an unterschiedliche Services zu routen. Der Ingress ist der klassische Layer-7-Einstiegspunkt in den Cluster: ein einzelner Endpunkt, hinter dem beliebig viele Services liegen.

Lernziele

Nach diesem Lab kannst du:

  • das Ingress-Addon in Minikube aktivieren und den Ingress-Controller prüfen,
  • einen Ingress anlegen, der per Host routet,
  • einen Ingress per Pfad auf mehrere Services aufteilen (Fanout),
  • den Zugriff von außen über Tunnel bzw. minikube ip testen,
  • typische Fehler (Connection reset, falscher curl) erkennen und beheben.

Voraussetzungen

Aktiviere das Ingress-Addon in Minikube:

minikube addons enable ingress

Prüfe, dass der Controller läuft, bevor du weitermachst:

kubectl get pods -n ingress-nginx

Der Pod ingress-nginx-controller-... muss Running und READY 1/1 sein.

1. Anwendung starten

01-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-demo
  labels:
    app: nginx-ingress
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-ingress
  template:
    metadata:
      labels:
        app: nginx-ingress
    spec:
      containers:
        - name: nginx
          image: nginx:1.29.4
          ports:
            - containerPort: 80
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 20
          lifecycle:
            postStart:
              exec:
                command: ["/bin/sh", "-c", "echo \"Hello from $(hostname)\" > /usr/share/nginx/html/index.html"]
          volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "200m"
              memory: "256Mi"
      volumes:
        - name: html
          emptyDir: {}

Hinweis: Jeder Pod schreibt beim Start seinen eigenen Hostnamen in die index.html. So siehst du beim Testen direkt, welcher der beiden Pods deine Anfrage beantwortet hat – praktisch, um Load-Balancing zu beobachten.

02-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-svc
spec:
  selector:
    app: nginx-ingress
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP

03-ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    # Dies weist den Standard NGINX Controller an (wichtig für Minikube)
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-ingress-svc
            port:
              number: 80

Wende alle YAML-Dateien in diesem Ordner an:

kubectl apply -f .

2. Ingress inspizieren

Bevor du testest, schau dir an, was Kubernetes aus deinem Manifest gemacht hat:

kubectl get ingress
kubectl describe ingress nginx-ingress

Achte auf zwei Dinge:

  • Die Spalte ADDRESS muss nach kurzer Zeit eine IP zeigen. Bleibt sie leer, ist der Controller noch nicht bereit.
  • Unter Rules im describe-Output siehst du das Mapping Host → Pfad → Service:Port. Genau diese Regel wertet der Controller bei jedem Request aus.

3. Zugriff testen

Da wir einen Hostnamen (nginx.example.com) definiert haben, müssen wir sicherstellen, dass dieser auf die IP des Ingress-Controllers aufgelöst wird.

Methode A: Minikube Tunnel (Empfohlen für Mac/Windows)

Starte den Tunnel in einem separaten Terminal. Er sorgt dafür, dass Services vom Typ LoadBalancer (den der Ingress Controller nutzt) eine IP bekommen und routet Traffic.

minikube tunnel

Füge dann den Eintrag zu deiner /etc/hosts hinzu (sudo benötigt), damit nginx.example.com auf 127.0.0.1 zeigt, ODER teste direkt mit curl:

curl --resolve nginx.example.com:80:127.0.0.1 http://nginx.example.com

Windows (PowerShell): curl ist ein Alias für Invoke-WebRequest und kennt --resolve nicht. Nutze stattdessen curl.exe. Auf macOS/Linux funktioniert curl direkt.

curl.exe --resolve nginx.example.com:80:127.0.0.1 http://nginx.example.com

Wiederhole den Request mehrmals: Mal antwortet nginx-ingress-demo-...-abcde, mal ein anderer Pod – das ist das Load-Balancing des Service.

Methode B: Minikube IP (Linux)

echo "$(minikube ip) nginx.example.com" | sudo tee -a /etc/hosts
curl http://nginx.example.com

Troubleshooting

  • curl: (56) Connection was reset – Tunnel läuft nicht oder nicht als Admin. Starte minikube tunnel als Administrator in einem separaten Terminal.
  • Invoke-WebRequest: ... --resolve (PowerShell)curl ist nur ein Alias. Nutze curl.exe statt curl.
  • ADDRESS bei kubectl get ingress bleibt leer – Controller noch nicht bereit. Prüfe kubectl get pods -n ingress-nginx.
  • 404 Not Found vom NGINX-Controller – der Host-Header passt nicht zur host:-Regel. --resolve setzt den Host korrekt.

Als robuste Alternative zum Tunnel (besonders unter Windows mit Docker-Driver) kannst du den Controller per Port-Forward erreichen:

kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller 8080:80
curl.exe --resolve nginx.example.com:8080:127.0.0.1 http://nginx.example.com:8080

4. Aufgabe: Pfad-basiertes Routing (Fanout)

Ein einzelner Ingress kann anhand des Pfads auf verschiedene Services verteilen. Das ist das typische Fanout-Muster: example.com/shop geht zu Service A, example.com/blog zu Service B.

Deine Aufgabe:

  1. Lege ein zweites Deployment plus Service an (z. B. nginx-blog / nginx-blog-svc). Nutze wieder nginx:1.29.4 und schreibe per postStart einen erkennbaren Text in die index.html (z. B. Hello from the BLOG).
  2. Erweitere 03-ingress.yaml so, dass unter demselben Host nginx.example.com zwei Pfade existieren:
  3. /shop → bestehender nginx-ingress-svc
  4. /blog → neuer nginx-blog-svc
  5. Wende alles an und teste beide Pfade:
curl --resolve nginx.example.com:80:127.0.0.1 http://nginx.example.com/shop
curl --resolve nginx.example.com:80:127.0.0.1 http://nginx.example.com/blog

Tipp: Im rules-Block können mehrere paths-Einträge stehen. Mit der Annotation nginx.ingress.kubernetes.io/rewrite-target: / wird der Pfad-Präfix vor dem Weiterleiten an den Backend-Service entfernt – sonst bekäme NGINX im Container die URL /shop und würde 404 liefern.

Lösungs-Skizze für den Ingress

Erst nach eigenem Versuch ansehen:

spec:
  ingressClassName: nginx
  rules:
  - host: nginx.example.com
    http:
      paths:
      - path: /shop
        pathType: Prefix
        backend:
          service:
            name: nginx-ingress-svc
            port:
              number: 80
      - path: /blog
        pathType: Prefix
        backend:
          service:
            name: nginx-blog-svc
            port:
              number: 80

5. Aufräumen

kubectl delete -f .

Das Ingress-Addon kannst du laufen lassen oder mit minikube addons disable ingress wieder deaktivieren.