Einführung
Ein Init-Container wird vor den eigentlichen Anwendungscontainern in einem Pod ausgeführt. Jeder Init-Container muss erfolgreich abgeschlossen sein, bevor Kubernetes den nächsten Init-Container oder einen regulären Container startet. Dies macht Init-Container nützlich für die Vorbereitung von Dateien, die Überprüfung von Abhängigkeiten oder die Durchführung kleinerer Einrichtungsaufgaben, die nicht dauerhaft neben der Anwendung laufen müssen.
In diesem Lab fügen Sie einen Init-Container hinzu, der eine Startdatei in ein gemeinsam genutztes emptyDir-Volume schreibt. Sie bestätigen, dass der Anwendungscontainer die Datei lesen kann, untersuchen den Status und die Protokolle des Init-Containers und wenden dasselbe Muster anschließend in einer Deployment-Vorlage an.
Einen Namespace für Init-Container vorbereiten
In diesem Schritt bereiten Sie einen sauberen Namespace für das Üben mit Init-Containern vor.
Beginnen Sie im Verzeichnis /home/labex/project. Sie werden die Pod- und Deployment-Manifeste in diesem Verzeichnis erstellen.
mkdir -p /home/labex/project
cd /home/labex/project
Überprüfen Sie, ob der Kubernetes API-Server erreichbar ist. Falls die VM gerade erst gestartet wurde und der Node noch nicht bereit ist, warten Sie einige Sekunden und führen Sie den Befehl erneut aus.
kubectl get nodes --request-timeout=5s
Die erwartete Ausgabe sieht in etwa so aus:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Init-Container laufen innerhalb von Pods. Warten Sie daher, bis der Cluster-Networking-Pod bereit ist, bevor Sie Workloads erstellen.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Erwartete Ausgabe:
pod/calico-node-... condition met
Erstellen Sie einen Namespace namens ckad-prep-init:
kubectl create namespace ckad-prep-init
Setzen Sie diesen Namespace als aktuellen Kontext-Namespace:
kubectl config set-context --current --namespace=ckad-prep-init
Bestätigen Sie den aktuellen Namespace:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Erwartete Ausgabe:
ckad-prep-init
Gemeinsam genutzte Daten vor dem Start der Anwendung vorbereiten
In diesem Schritt erstellen Sie einen Pod, in dem ein Init-Container eine Datei vorbereitet, bevor der Anwendungscontainer startet.
Das emptyDir-Volume wird erstellt, wenn der Pod einem Node zugewiesen wird, und wird von allen Containern im selben Pod gemeinsam genutzt. Sowohl der Init-Container als auch der App-Container mounten dieses Volume unter /work. Der Init-Container schreibt /work/startup.txt und beendet sich dann. Erst nachdem er erfolgreich beendet wurde, startet Kubernetes den App-Container.
Erstellen Sie init-file-pod.yaml:
cat > init-file-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: init-file-demo
labels:
app: init-file-demo
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: shared-work
emptyDir: {}
initContainers:
- name: prepare-startup-file
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo init-started; echo prepared-by-init > /work/startup.txt; echo init-finished'
volumeMounts:
- name: shared-work
mountPath: /work
containers:
- name: app
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo app-started; cat /work/startup.txt; sleep 3600'
volumeMounts:
- name: shared-work
mountPath: /work
EOF
Wenden Sie das Manifest an:
kubectl apply -f init-file-pod.yaml
Erwartete Ausgabe:
pod/init-file-demo created
Warten Sie, bis der Pod bereit ist:
kubectl wait --for=condition=Ready pod/init-file-demo --timeout=120s
Erwartete Ausgabe:
pod/init-file-demo condition met
Lesen Sie die Datei aus dem Inneren des App-Containers. Dies beweist, dass der Init-Container die Daten auf dem gemeinsam genutzten Volume vorbereitet hat, bevor die App startete.
kubectl exec init-file-demo -c app -- cat /work/startup.txt
Erwartete Ausgabe:
prepared-by-init
Status und Protokolle des Init-Containers überprüfen
In diesem Schritt überprüfen Sie den Nachweis, dass der Init-Container abgeschlossen wurde, bevor der App-Container weiterlief.
Init-Container erscheinen unter .status.initContainerStatuses, während reguläre Container unter .status.containerStatuses aufgeführt werden. Der Init-Container sollte den Grund Completed haben, da er erfolgreich beendet wurde.
kubectl get pod init-file-demo -o 'jsonpath={.status.initContainerStatuses[0].name}{" "}{.status.initContainerStatuses[0].state.terminated.reason}{"\n"}'
Erwartete Ausgabe:
prepare-startup-file Completed
Überprüfen Sie nun den Status des regulären Anwendungscontainers. Er sollte bereit sein und laufen.
kubectl get pod init-file-demo -o 'jsonpath={.status.containerStatuses[0].name}{" "}{.status.containerStatuses[0].ready}{" "}{.status.containerStatuses[0].state.running.startedAt}{"\n"}'
Die erwartete Ausgabe enthält:
app true ...
Lesen Sie die Protokolle des Init-Containers. Auch wenn der Init-Container bereits beendet ist, bleiben seine Protokolle über kubectl logs -c verfügbar.
kubectl logs init-file-demo -c prepare-startup-file
Erwartete Ausgabe:
init-started
init-finished
Lesen Sie die Protokolle des App-Containers. Die App startet erst, nachdem der Init-Container die Datei geschrieben hat, daher enthalten ihre Protokolle den vorbereiteten Wert.
kubectl logs init-file-demo -c app
Die erwartete Ausgabe enthält:
app-started
prepared-by-init
Einen Init-Container zu einem Deployment hinzufügen
In diesem Schritt verwenden Sie dasselbe Init-Container-Muster innerhalb einer Deployment-Vorlage.
Für Anwendungs-Workloads platzieren Sie Init-Container normalerweise in der Pod-Vorlage eines Controllers, anstatt eigenständige Pods zu erstellen. Wenn das Deployment einen Pod erstellt, führt Kubernetes für jeden aus dieser Vorlage erstellten Pod zuerst den Init-Container aus.
Erstellen Sie init-deployment.yaml:
cat > init-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: init-web
spec:
replicas: 1
selector:
matchLabels:
app: init-web
template:
metadata:
labels:
app: init-web
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: web-content
emptyDir: {}
initContainers:
- name: render-index
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo deployment-init > /site/index.txt'
volumeMounts:
- name: web-content
mountPath: /site
containers:
- name: web
image: busybox:1.36
command:
- /bin/sh
- -c
- 'cat /site/index.txt; sleep 3600'
volumeMounts:
- name: web-content
mountPath: /site
EOF
Wenden Sie das Deployment an:
kubectl apply -f init-deployment.yaml
Erwartete Ausgabe:
deployment.apps/init-web created
Warten Sie, bis das Deployment verfügbar ist:
kubectl wait --for=condition=Available deployment/init-web --timeout=120s
Erwartete Ausgabe:
deployment.apps/init-web condition met
Suchen Sie den vom Deployment erstellten Pod:
web_pod="$(kubectl get pods -l app=init-web -o 'jsonpath={.items[0].metadata.name}')"
echo "$web_pod"
Die erwartete Ausgabe zeigt einen generierten Pod-Namen:
init-web-...
Lesen Sie die Protokolle des App-Containers aus diesem Pod:
kubectl logs "$web_pod" -c web
Erwartete Ausgabe:
deployment-init
Überprüfen Sie den Abschlussstatus des Init-Containers innerhalb des vom Deployment erstellten Pods:
kubectl get pod "$web_pod" -o 'jsonpath={.status.initContainerStatuses[0].name}{" "}{.status.initContainerStatuses[0].state.terminated.reason}{"\n"}'
Erwartete Ausgabe:
render-index Completed
Zusammenfassung
Sie haben Init-Container zu einem Pod und einer Deployment-Vorlage hinzugefügt. Sie haben ein emptyDir-Volume verwendet, um vorbereitete Dateien mit dem App-Container zu teilen, den Status abgeschlossener Init-Container überprüft, Init- und App-Protokolle gelesen und bestätigt, dass dasselbe Muster auch für Controller-verwaltete Anwendungs-Pods funktioniert.


