CV laden

DevOps

Kubernetes-Liveness ist kein Docker-Healthcheck

Compose wartet, bis php-fpm lauscht. Kubelet tötet einen Pod, der noch OPcache kompiliert. Readiness und Liveness sind andere Knöpfe.

Der erste Kubernetes-Deploy dieses Stacks sah aus wie ein Crash Loop. Lokal läuft Docker Compose: nginx, php, queue, mysql, redis, memcached. Ein Healthcheck auf /up nach dem FPM-Bind reicht. In Kubernetes tötete derselbe Check als Liveness den Pod im Warmup. Der erste Request kompiliert LaraBoom in OPcache. Das dauert länger als der Default-Probe.

Nutzer trafen 502 über den Service. Kubelet startete einen Prozess neu, der noch kompilierte. Readiness nimmt den Pod aus dem Service, bis er Traffic kann. Liveness startet einen hängenden Pod neu. Ein Probe für beides: langsamer Start sieht aus wie ein toter Prozess. Die Replica wird nie Ready.

Compose wartete. Kubelet tötete. Das ist der ganze Mismatch.

Readiness hält Traffic. Liveness tötet. Warmup darf nicht wie Tod aussehen.
Readiness hält Traffic. Liveness tötet. Warmup darf nicht wie Tod aussehen.

startupProbe besitzt die erste Minute

Ein Startup-Probe trifft /up alle fünf Sekunden mit hoher failureThreshold. Kubelet startet Liveness erst danach. Dann darf Liveness töten. Readiness bleibt auf nginx vor FPM, nicht auf einer Route, die noch Doctrine oder Eloquent bootet.

Rolling Update braucht maxUnavailable, das mindestens einen Ready-php-Pod lässt. SIGTERM beim Deploy ist dieselbe Story wie Compose: Worker müssen drainen. Liveness während des Drain macht 502 schlimmer.

Liveness zeigte zuerst auf dasselbe /up, das das Framework bootet. Der Probe fiel, während OPcache füllte, und wieder, während Worker drainten. Ein billiger TCP-Check auf den FPM-Listen-Port reicht für Liveness nach dem Startup. Readiness bleibt HTTP durch nginx, damit ein gebundenes FPM mit totem nginx keinen Traffic nimmt.

startupProbe deckt OPcache-Compile. Dann darf Liveness neu starten. Readiness sitzt auf nginx.
startupProbe deckt OPcache-Compile. Dann darf Liveness neu starten. Readiness sitzt auf nginx.

Wofür Compose bleibt

Diese Site bleibt auf Compose und VPS, bis es mehrere Nodes gibt. Kubernetes ist der nächste Schritt, keine Umbenennung der Compose-Datei. Probes, PodDisruptionBudget und ein echter Readiness-Pfad sind die Kosten. healthcheck aus dem Dockerfile in Liveness zu kopieren heißt, sie doppelt zu zahlen.

Ich habe auch gelernt, dass ein Queue-Worker-Pod den Web-Readiness-Pfad nicht teilen darf. Horizon kann leben, während FPM kein HTML liefert. Getrennte Probes, sonst klaut der Web-Service Queue-Pods. PDB auf php zählt Ready-Web-Pods, nicht jeden Container im Pod.

Was ich daraus mitnehme

Während des Warmup achte ich auf Ready gegen Restarts, nicht darauf, ob FPM gebunden hat. Ein Crash Loop bei kompilierendem OPcache ist Liveness aus Compose.

Einem Probe für Start, Live und Ready traue ich nicht. startupProbe deckt Compile. Liveness darf danach TCP auf FPM sein. Readiness ist nginx vor FPM.

Die Regel, die ich behalte: maxUnavailable lässt einen Ready-php-Pod. Liveness nicht während Drain. Dockerfile-healthcheck nicht in Liveness kopieren. Compose bleibt, bis es mehrere Nodes gibt.

Zurück zu Notizen