Begriff
Init Container
Warum wichtig?
Dieser Begriff ist ein Knoten im SengakujiWorks-Wissensnetz. Nutze Level 0 für die erste Einordnung, Level 1 für Praxis, Level 2 für technische Struktur und Level 3 für Grenzen, Fallstricke und Expertenkontext.
Bevor deine Haupt-App startet (z. B. WordPress), müssen oft Dinge erledigt werden.
- "Ist die Datenbank schon da?" (Warten).
- "Habe ich Schreibrechte auf dem Ordner?" (Rechte fixen).
- "Config-Datei generieren."
Dafür gibt es Init Container.
Sie sind wie das Vorprogramm.
Sie starten vor dem eigentlichen Container.
Erst wenn sie erfolgreich fertig sind (
Exit 0), startet der nächste. Wenn ein Init Container scheitert, startet der Pod nicht.
Merksatz: Ein spezialisierter Container in einem Pod, der vor den App-Containern ausgeführt wird, um Initialisierungsaufgaben zu erledigen, die Sequenzierung erfordern oder spezielle Rechte benötigen.
YAML:
spec:
initContainers:
- name: wait-for-db
image: busybox
command: ['sh', '-c', 'until nslookup mydb; do echo waiting; sleep 2; done']
containers:
- name: wordpress
image: wordpress
Hier startet WordPress niemals, bevor mydb im DNS auflösbar ist. Das verhindert Crash-Loops der Haupt-App.
1. Security Separation
Init Container können ein anderes Image nutzen als die Haupt-App.
Beispiel: Deine App ist ein winziges "Distroless" Image ohne Shell, ohne curl, ohne chmod. (Super sicher).
Aber du musst beim Start Dateien herunterladen oder Rechte ändern.
Lösung: Init Container nutzt ein "fettes" Image (Ubuntu) mit allen Tools. Er macht die Arbeit auf dem Shared Volume (emptyDir). Er beendet sich.
Die Haupt-App startet und nutzt die Dateien.
Die Hacker-Tools (curl, sh) sind im Haupt-Container, der 24/7 läuft, nicht vorhanden.
2. Sequenziell vs. Parallel
Normale Container (Sidecars) starten parallel.
Init Container starten streng sequenziell.
Init 1 -> fertig -> Init 2 -> fertig -> Main App.
Das macht komplexe Boot-Sequenzen deterministisch ("Erst Schema-Migration, dann Cache-Warmup, dann Start").
Wenn Init 1 crasht, wird er neu gestartet (Restart Policy), Init 2 kommt gar nicht dran.
3. Immutable Fields
Achtung: Du kannst Init Container im laufenden Betrieb nicht ändern (z. B. Image Tag ändern), außer du löscht den Pod (Recreate).
Das image Feld ist zwar im Deployment änderbar, aber der Pod Restart ist zwingend.
IPC (Inter-Process Communication) via Shared Memory
Wenn Init Container Dateien an den Main-Container weiterreichen wollen, geschieht dies meist über emptyDir-Volumes, die an den Pod-Lebenszyklus gebunden sind (Die klassische Asset-Pipeline).
Aber Volumes rufen I/O Flaschenhälse auf Disk-Ebene hervor.
Bei speicherkritischen Initialisierungen können App- und Init Container sich einen emptyDir-Mount mit medium: Memory (ein tmpfs Laufwerk) teilen. Alternativ teilt man den UNIX-Standard "IPC Namespace" des Pods (hostIPC in extremen Fällen oder Kubernetes-native Features). Der Init-Prozess berechnet Hashes, packt sie in ein UNIX Domain Socket oder Memory Map und beendet sich, woraufhin die App in Millisekunden zustandslose In-Memory Cache Starts hinlegen kann – ganz ohne Disk-Persistenz.
The Chown Hell (Berechtigungs-Eskalation umgehen)
Ein massives Problem bei Kubernetes-Deployments (Kubelet Restarts) sind langwierige Startup-Zeiten durch Dateisystemrechte.
Oft wird ein Init Container missbraucht (command: ["chown", "-R", "1000:1000", "/data"]), um sicherzustellen, dass ein gemountetes extern blockierendes NFS-Volume die richtige ID für den non-root Laufzeit-Container besitzt.
Ist dieses Verzeichnis voller Millionen kleiner Dateien, blockiert dieser rekursive chown-Aufruf beim Pod-Boot für Minuten. Bei Crash-Loops akkumuliert sich dieser Delay exponentiell. Die Profilösung umgeht Init-Container an dieser Stelle durch fsGroup Security-Context Settings, in denen der Kubelet-Daemon (und nicht der Init Container) das Mapping bereits beim Mounten transparent vom Host OS abwickelt.
K8s API Polling statt Dummem Sleep
Ein brutaler Anti-Pattern im Init Container ist der statische sleep 10 oder das bloße Warten via DNS Resolve auf DB-Hostnamen.
DNS ist oft sofort da (weil Kubernetes den Service angelegt hat), auch wenn der DB-Pod dahinter noch hart in der CrashLoopBackOff Schleife hängt.
Ein elitärer Init-Befehl ist ein direkter K8s API-Call (via Service-Account Token). Der initContainer führt ein leichtgewichtiges kubectl wait aus:
kubectl wait --for=condition=Ready pod -l app=database -n data --timeout=60s.
Dies fragt exakt den echten Runtime-Zustand des Ziel-Pods vom Control Plane ab und synchronisiert den Boot des Services frame-genau mit der tatsächlichen Verfügbarkeit der Abhängigkeit (Event-driven anstatt Polling-Overkill).
Quick-Check
Was teilen sie sich?
Init Container und App Container teilen sich das Netzwerk (IP) und Volumes. Sie teilen sich nicht das Dateisystem (jedes hat eigenes Image), außer gemountete Volumes.Unterschied zu PostStartHook?
PostStart läuft asynchron (parallel zum App-Start). Es garantiert nicht, dass es fertig ist, bevor die App Anfragen annimmt. Init Container blockieren den Start. Das ist sicherer für Abhängigkeiten.Sidecars in K8s 1.28?
Neu gibt es "Sidecar Containers" (Init Container mitrestartPolicy: Always). Sie starten vor der App, laufen aber weiter. Das löst das Problem von Service-Mesh-Proxies (die laufen müssen, bevor die App netzwerkt).