Kubernetes Kubernetes

Deployments: Skalieren, Selbstheilung und Rolling Updates

Betreibe Replikas eines Pods, aktualisiere sie ohne Ausfallzeit und rolle zurück, wenn ein Release schiefgeht.

14 min Anfänger

Pods sind Wegwerfware, und ein einzelner Pod, der stirbt, bleibt tot. Ein Deployment behebt das: Du deklarierst, wie viele Kopien du willst und welches Image laufen soll, und Kubernetes hält so viele am Laufen und übernimmt die Updates für dich. Diese Anleitung behandelt das Erstellen eines Deployments, das Skalieren, das Aktualisieren ohne Ausfallzeit und das Zurückrollen.

Warum du selten einzelne Pods erstellst

Fällt ein Knoten aus oder wird ein Pod gelöscht, erstellt nichts einen eigenständigen Pod neu. In der Praxis erstellst du Pods fast nie direkt. Du erstellst ein Deployment, das ein ReplicaSet erstellt, das wiederum die Pods erstellt und pflegt. Das Deployment ergänzt, was dem ReplicaSet fehlt: kontrollierte Updates und Versionshistorie.

Ein Deployment schreiben

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80

Es gibt zwei metadata-Abschnitte, und es hilft, sie auseinanderzuhalten. Der obere beschreibt das Deployment. Der unter template beschreibt die Pods, die es erstellt, und das template ist schlicht ein Pod-Manifest ohne Namen. Der selector sagt dem Deployment, welche Pods zu ihm gehören, er muss also zu den Labels im Template passen, sonst lehnt Kubernetes das Manifest ab.

kubectl apply -f deployment.yaml
kubectl get deployment,replicaset,pods

Du siehst ein Deployment, ein ReplicaSet, benannt nach ihm plus einem Hash, und drei nach dem ReplicaSet benannte Pods.

Labels und Selector: wie Objekte einander finden

Labels sind Schlüssel-Wert-Paare, die du an jedes Objekt hängen kannst. Selector fragen sie ab, und so verbindet Kubernetes Dinge: Ein Deployment findet seine Pods, ein Service findet seine Backends, und eine Network Policy findet die Pods, die sie regelt.

kubectl get pods --show-labels
kubectl get pods -l app=web

Um zu sehen, wie sehr ein Selector zählt, entferne das Label von einem Pod:

kubectl label pod POD_NAME app-
kubectl get pods --show-labels

Das ReplicaSet zählt diesen Pod nicht mehr als seinen eigenen und startet einen Ersatz, um wieder auf drei zu kommen. Der umgelabelte Pod läuft weiter, aber nichts verwaltet ihn. Lösche ihn mit kubectl delete pod POD_NAME, damit er nicht herumliegt.

Skalieren und die Selbstheilung beobachten

kubectl scale deployment web --replicas=5
kubectl get pods -w

Lösche in einem anderen Terminal einen Pod und sieh zu, wie innerhalb von Momenten ein Ersatz erscheint. Um die Replikazahl dauerhaft zu ändern, bearbeite replicas im Manifest und wende es erneut an, da kubectl scale allein deine Datei veraltet zurücklässt. Die Pods eines Deployments wirst du nicht los, indem du sie löschst, da sie immer wiederkommen. Lösche das Deployment selbst oder skaliere es auf null.

Eine neue Version ausrollen

Eine Änderung an irgendetwas im Pod-Template, etwa dem Image, löst ein Rolling Update aus:

kubectl set image deployment/web nginx=nginx:1.26
kubectl rollout status deployment/web

Das Deployment erstellt ein zweites ReplicaSet für die neue Version und skaliert es dann schrittweise hoch, während es das alte herunterskaliert, sodass stets einige Pods Traffic bedienen. Standardmäßig erlaubt es bis zu 25 % zusätzliche Pods (maxSurge) und bis zu 25 % nicht verfügbare (maxUnavailable) während der Änderung. Du kannst das in der Spec anpassen:

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

Mit maxUnavailable: 0 wird ein alter Pod erst entfernt, wenn ein neuer bereit ist. Was „bereit“ heißt, entscheiden Readiness-Probes, die eine spätere Anleitung behandelt. Das Ändern der Replikazahl ist kein Rollout, da das Pod-Template unberührt bleibt.

Zurückrollen

Kubernetes behält die alten ReplicaSets, was das Zurückrollen schnell macht:

kubectl rollout history deployment/web
kubectl rollout undo deployment/web
kubectl rollout undo deployment/web --to-revision=1

undo kehrt zur vorherigen Revision zurück, und --to-revision wählt eine bestimmte. Die Zahl der behaltenen alten Revisionen setzt revisionHistoryLimit, standardmäßig 10. Eine Warnung: Liegen deine Manifeste in Git und etwas wie Argo CD wendet sie an, bevorzuge das Zurücknehmen des Commits gegenüber rollout undo. Das Undo ändert den Cluster, aber nicht Git, sodass beide voneinander abweichen, bis jemand abgleicht.

Beliebte Anleitungen