Init-Container hinzufügen

KubernetesBeginner
Jetzt üben

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.