Beim Ausfall einer Kubernetes Node bleiben Pods im Terminating Status hängen

Kubernetes ist eigentlich dazu da, eine Infrastruktur in Code zu gießen, sie einfach skalieren zu können und dass sich das System im Problemfall “selbst heilt”. Das funtkioniert in der Regel auch ganz gut, aber besonders die “Selbstheilung” hat so ihre Grenzen. In meinem Fall handelt es sich um gemountete Volumes / PCVs, die nur einmal verwendet werden dürfen. Sprich, immer nur genau ein Pod darf dieses Volume mounten.

Das ist z.b. bei Ceph oder NFS mounts der Fall.

In meinem lokalen Cluster aus mehreren Intel NUCs habe ich nun das Problem, dass wenn eine Node ausfällt/vom Strom getrennt wird, dass die Node zwar sehr schnell als fehlend markiert wird und nach 5 Minuten dann auch die Pods das gleiche Schicksal ereilt. Wenn Kubernetes aber nun versucht, die Pods auf einer anderen Node neu zu starten, dann scheitert es daran, dass Kubernetes an dieser Stelle nicht genau weiß, ob die Pods wirklich weg sind oder nur die Infrastruktur selbst nicht richtig kommuniziert. Daher geht es davon aus, dass die Mounts noch beim alten Pod aktiv sind, bis es die endgültige Meldung bekommt, dass der alte Pod wirklich weg ist. Da die Node aber zu diesemn Zeitpunkt keinen Strom mehr hat, kann sie auch nie melden, dass der Pod nicht mehr läuft. Und so wartet Kubernetes einfach bzw. verharrt in diesem unklaren Zustand.

Man kann nun anfangen, die Pods manuell mit einem Force zu löschen, dann werden sie nach einiger Zeit ihre Resourcen wieder frei geben und der neue Pod kann starten. Um dies auch zu automatisieren, kann man sich aber auch mit einem Cron Job innerhalb des Clusters behelfen. Und das sieht dann so aus:

Service Account und RBAC Rolle anlegen:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: cleanup-bot
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cleanup-bot-role
rules:
- apiGroups: [""]
  resources: ["pods", "nodes"]
  verbs: ["get", "list", "delete"]
- apiGroups: ["storage.k8s.io"]
  resources: ["volumeattachments"]
  verbs: ["list", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cleanup-bot-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cleanup-bot-role
subjects:
- kind: ServiceAccount
  name: cleanup-bot
  namespace: default

Wenn das eingerichtet ist, kann man den Cronjob so anlegen:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: pod-cleanup-dead-nodes
  namespace: default
spec:
  schedule: "*/10 * * * *" # alle 10 Minuten
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: cleanup-bot
          containers:
          - name: cleanup
            image: bitnami/kubectl:latest
            command:
            - /bin/sh
            - -c
            - |
              for node in $(kubectl get nodes --no-headers | awk '$2 == "NotReady" {print $1}'); do
                echo "Cleaning up pods on $node"
                kubectl get pods --all-namespaces --field-selector spec.nodeName=$node -o json \
                  | jq -r '.items[] | select(.metadata.deletionTimestamp != null) | "kubectl delete pod -n \(.metadata.namespace) \(.metadata.name) --grace-period=0 --force"' \
                  | sh
              done
          restartPolicy: OnFailure

Dieser Cronjob schaut alle 10 Minuten nach, ob es Nodes gibt, die im Status “NotReady” sind. Für alle Nodes in diesem Status werden die Pods auf dieser Node ausgelesen und einzeln per kubectl und keiner Grace-Period gelöscht.

In meinem Fall hat dies genau die Lösung gebracht, die ich gesucht habe. Erst ist die Node nicht mehr erreichbar, dann failen die Pods und Kubernetes versucht sie neu auf anderen Nodes zu starten, scheitert aber daran wegen der noch offenen Volume Mounts. Nach max. 10 Minuten kommt der Cronjob und beendet alle Pods hart und löst damit den Volume mount auf, worauf sich nach kurzer Zeit die “neuen” Pods aus ihrem Pending Status befreien und korrekt hochfahren.

Published by

bytelude

Softwareentwickler, Technik Fanatiker, Apple Fan, Kinoliebhaber, Prokrastinations-Spezialist

Leave a Reply

Your email address will not be published. Required fields are marked *