Kubernetes Ingress Updates Skalierung
Dieser Artikel baut auf dem vorherigen Deployment aus Compose-App nach Kubernetes übersetzen auf und ergänzt das, was mit Docker Compose gar nicht möglich war: externer Zugriff über Ingress, kontrollierte Updates ohne Downtime, Skalierung und persistente Daten.
Externer Zugriff mit Ingress
Port-Forwarding aus dem vorherigen Artikel funktioniert nur temporär und nur für eine Person gleichzeitig. Für dauerhaften externen Zugriff wird ein Ingress verwendet.
- Was ein Ingress macht
- Ein Ingress ist ein Regelwerk, das eingehenden HTTP(S)-Traffic anhand von Hostname oder Pfad an den passenden internen Service weiterleitet – vergleichbar mit einem Reverse Proxy wie Traefik oder Nginx, den man aus der Compose-Welt kennt.
- Ingress-Controller bei k3s
- k3s bringt Traefik als Ingress-Controller bereits vorinstalliert mit. Es muss nichts zusätzlich installiert werden.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
spec:
rules:
- host: web.lab.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
- Anwenden
kubectl apply -f web-ingress.yaml
- Hostnamen lokal auflösen
- Da
web.lab.localkeine echte Domain ist, muss der Hostname auf dem Client in/etc/hostseingetragen werden, zeigend auf die IP-Adresse vonk8s-server. echo "<SERVER_IP> web.lab.local" | sudo tee -a /etc/hosts
- Zugriff testen
curl http://web.lab.local
Health-Checks: Probes
Im vorherigen Artikel wurde festgestellt, dass es kein Äquivalent zu depends_on gibt. Die Kubernetes-Antwort darauf sind Probes – fortlaufende Prüfungen, ob ein Container tatsächlich funktioniert.
- Liveness Probe
- Prüft, ob der Container noch lebt. Schlägt sie fehl, wird der Container neu gestartet.
- Readiness Probe
- Prüft, ob der Container bereit ist, Traffic zu empfangen. Schlägt sie fehl, wird der Pod aus dem Service entfernt, aber nicht neu gestartet – er bekommt einfach so lange keinen Traffic, bis die Probe wieder erfolgreich ist.
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 20
- Warum das die depends_on-Lücke schließt
- Ein Service leitet Traffic nur an Pods weiter, deren Readiness Probe erfolgreich ist. Damit landet Traffic nie bei einer Instanz, die noch nicht bereit ist – unabhängig von der Startreihenfolge.
Rolling Updates
- Was bei einem Compose-Update passiert
docker compose up -dnach einem Image-Wechsel ersetzt Container ohne eingebaute Kontrolle darüber, wie viele gleichzeitig offline sind.
- Was ein Deployment stattdessen tut
- Standardmäßig verwendet ein Deployment die Update-Strategie
RollingUpdate: Es werden schrittweise neue Pods mit dem neuen Image gestartet und alte erst entfernt, wenn genügend neue bereit sind (erkennbar über die Readiness Probe).
- Image aktualisieren
kubectl set image deployment/web web=nginx:1.26
- Rollout beobachten
kubectl rollout status deployment/web
- Rollout-Historie ansehen
kubectl rollout history deployment/web
- Bei Problemen zurückrollen
kubectl rollout undo deployment/web
Skalierung
- Deployment skalieren
kubectl scale deployment/web --replicas=3
- Verteilung über die Nodes prüfen
kubectl get pods -o wide- Die drei Instanzen verteilen sich in der Regel automatisch über die verfügbaren Agent-Nodes.
- Warum die Datenbank nicht einfach genauso skaliert wird
- Würde
dbebenfalls auf drei Replicas skaliert, entstünden drei unabhängige PostgreSQL-Instanzen ohne gemeinsamen Datenbestand – das produziert Dateninkonsistenz, keine Hochverfügbarkeit. Zustandsbehaftete Anwendungen wie Datenbanken benötigen einen anderen Ansatz (StatefulSet), der über den Rahmen dieses Kurses hinausgeht, aber als Begriff hier bewusst fällt.
Persistente Daten: PersistentVolumeClaim
In der ursprünglichen Compose-Datei sorgte volumes: db_data:/var/lib/postgresql/data dafür, dass die Datenbank einen Container-Neustart übersteht. Das Kubernetes-Äquivalent ist ein PersistentVolumeClaim (PVC).
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: db-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
- Im db-Deployment einbinden
- Der Claim wird als Volume in den Pod eingehängt und im Container an den passenden Pfad gemountet.
spec:
containers:
- name: db
image: postgres:16
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: db-data
- Anwenden und prüfen
kubectl apply -f db-pvc.yamlkubectl get pvc
Übung: Rolling Update ohne Downtime beobachten
- Skaliert
webzunächst auf 3 Replicas. - Öffnet ein zweites Terminal und lasst dort fortlaufend Anfragen laufen, zum Beispiel mit
watch curl -s http://web.lab.local. - Startet im ersten Terminal ein Rolling Update auf ein anderes Image (
nginx:1.26) und beobachtet parallel im zweiten Terminal, ob Anfragen fehlschlagen. - Prüft mit
kubectl rollout status deployment/web, wann der Rollout abgeschlossen ist.
Übung: Rollback im Fehlerfall
- Führt absichtlich ein Update auf ein nicht existierendes Image durch (
nginx:kaputt). - Beobachtet mit
kubectl rollout status deployment/web, dass der Rollout hängen bleibt. - Macht das Update mit
kubectl rollout undo deployment/webrückgängig und bestätigt mitkubectl get pods, dass wieder die alte, funktionierende Version läuft.
Übung: Persistenz der Datenbank prüfen
- Bindet den PVC wie oben gezeigt ins
db-Deployment ein und wendet die Änderung an. - Legt über
kubectl exec -itin dendb-Pod eine Testtabelle oder einen Testeintrag in der Datenbank an. - Löscht den
db-Pod gezielt mitkubectl delete pod. - Prüft nach dem automatischen Neustart, ob der zuvor angelegte Datenbestand noch vorhanden ist.