Pod Status
Ziel
In diesem Projekt geht es um fortgeschrittene Techniken rund um Pods. Sie werden:
- Pod Status verstehen
- mit Image Pull Secrets arbeiten
- Pod-Probes definieren
Hilfsmittel
- Versuchen Sie, die unten stehenden Aufgaben mit Hilfe der Folien und des Cheatsheets eigenständig zu lösen.
- Sollten Sie dabei Probleme haben, finden Sie bei jeder Aufgabe einen ausklappbaren Block, in dem der Lösungsweg beschrieben wird.
Aufgabe 1: Pod Status verstehen
Aufgabe 1.1: Pods mit einem erfolgreich abgeschlossenen Container
- Erstellen Sie eine YAML-Datei
completed.yaml
mit folgendem Inhalt:
---
apiVersion: v1
kind: Pod
metadata:
name: completed
labels:
exercise: pod-status
spec:
containers:
- name: completed
image: alpine
command:
- "true"
restartPolicy: Never
- Deployen Sie den Pod
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f completed.yaml
- Untersuchen Sie den Pod-Status (
.status.phase
) und die Pod-Status Conditions (.status.conditions
) mitkubectl get pod
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pod completed -o json | jq .status.phase
kubectl get pod completed -o json | jq .status.conditions
Der Pod hat vier verschiedene Zustände durchlaufen, die sind:
PodScheduled
bedeutet, dass der Pod einem Node zugewiesen wurde.Initialized
bedeutet, dass alle initContainers erfolgreich abgeschlossen wurden.
Da wir keine initContainer haben, ist die Bedingung erfüllt.
ContainersReady
bedeutet, dass alle Container im Pod bereit sind.Ready
bedeutet, dass der Pod Anfragen bearbeiten kann und allen passenden Services hinzugefügt werden sollten. Wie durchPodCompleted
angezeigt, hat unser Pod denReady
-Zustand bereits verlassen, weil der Containerprozess beendet wurde und die RestartPolicy einen Neustart verhinderte.
Leider ist die Reihenfolge der Bedingungen, wie sie in kubectl get pod
erscheinen, nicht immer korrekt.
Aufgabe 1.2: Pods mit fehlerhaftem Container mit Neustarts
- Erstellen Sie eine YAML-Datei
crashloopbackoff.yaml
mit folgendem Inhalt:
---
apiVersion: v1
kind: Pod
metadata:
name: crashloopbackoff
labels:
exercise: pod-status
spec:
containers:
- name: crashloopbackoff
image: alpine
command:
- "false"
restartPolicy: Always
- Deployen Sie den Pod
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f crashloopbackoff.yaml
- Untersuchen Sie den Pod-Status (
.status.phase
) und die Pod-Status Conditions (.status.conditions
) mitkubectl get pod
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pod crashloopbackoff -o json | jq .status.phase
kubectl get pod crashloopbackoff -o json | jq .status.conditions
Der Pod hat folgende Zustände durchlaufen:
PodScheduled
: Der Pod wurde erfolgreich geplantInitialized
: Der Pod hat den ZustandInitialized
erreicht, da es keine initContainers gibtContainersReady
: Der Pod ist nicht bereit, da der Containerprozess sofort beendet wird und damit auch der Container beendet wird-
Ready
: Der Pod ist nicht bereit, da die RestartPolicy und der beendete Containerprozess eine Endlosschleife verursachen -
Lassen Sie sich den ContainerStatus (
.status.containerStatuses
) mitkubectl get pod
ausgeben
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pod crashloopbackoff -o json | jq .status.containerStatuses
Der Container befindet sich in einem "CrashLoopBackOff"-Zustand, weil der
Container mit einem Non-Zero-Exit-Code beendet wurde und die restartPolicy
den Pod dazu zwingt, den Container neu zu starten, bis er in einem
"Ready"-Zustand ist. Wir können auch sehen, ob Kubernetes den Container bereits
mehrmals neu gestartet hat. Standardmäßig wird alle 5 Minuten ein Neustart
ausgelöst.
Aufgabe 1.3: Pods mit einem fehlerhaften Container ohne Neustarts
- Erstellen Sie eine YAML-Datei
error.yaml
mit folgendem Inhalt:
---
apiVersion: v1
kind: Pod
metadata:
name: error
labels:
exercise: pod-status
spec:
containers:
- name: error
image: alpine
command:
- "false"
restartPolicy: Never
- Deployen Sie den Pod
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f error.yaml
- Untersuchen Sie den Pod-Status (
.status.phase
) und die Pod-Status Conditions (.status.conditions
) mitkubectl get pod
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pod error -o json | jq .status.phase
Failed
bedeutet, dass alle Container im Pod beendet wurden und mindestens ein
Container mit einem Fehler beendet wurde. Das bedeutet, dass der Container
entweder mit einem Non-Zero-Status beendet wurde oder vom System beendet
wurde. In unserem Fall wurde der Containerbefehl false
mit einem Non-Zero-Status
beendet.
Der Pod hat folgende Zustände durchlaufen:
PodScheduled
: Der Pod wurde erfolgreich geplantInitialized
: Der Pod hat den ZustandInitialized
erreicht, da es keine initContainers gibtContainersReady
: Der Pod ist nicht bereit, da der Containerprozess sofort beendet wird und damit auch der Container beendet wird-
Ready
: Der Pod ist nicht bereit, da der Containerprozess mit einem Non-Zero-Exit-Code beendet wurde -
Lassen Sie sich den ContainerStatus (
.status.containerStatuses
) mitkubectl get pod
ausgeben
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pod error -o json | jq .status.containerStatuses
Der Container befindet sich in einem terminated
-Zustand, da der Prozess mit
ExitCode 1 beendet wurde.
Aufgabe 1.4: Pods mit nicht existierendem Container-Image
- Erstellen Sie eine YAML-Datei
imagepullbackoff.yaml
mit folgendem Inhalt:
---
apiVersion: v1
kind: Pod
metadata:
name: imagepullbackoff
labels:
exercise: pod-status
spec:
containers:
- name: imagepullbackoff
image: alpaine
restartPolicy: Always
- Deployen Sie den Pod
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f imagepullbackoff.yaml
- Untersuchen Sie den Pod-Status (
.status.phase
) und die Pod-Status Conditions (.status.conditions
) mitkubectl get pod
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pod imagepullbackoff -o json | jq .status.phase
kubectl get pod imagepullbackoff -o json | jq .status.conditions
Der Pod hat folgende Zustände durchlaufen:
Pending
bedeutet, dass der Pod akzeptiert wurde, aber mindestens einer der Container nicht eingerichtet und bereit zum Ausführen ist. Dies beinhaltet die Zeit, die ein Pod darauf wartet, geplant zu werden, sowie die Zeit, die zum Herunterladen von Container-Images über das Netzwerk benötigt wird.
In unserem Fall schlägt das Herunterladen von Container-Images über das Netzwerk fehl.
Die Pod-Status Conditions sind die gleichen wie in Aufgabe 2, außer dass der Loopback-Grund "imagepullbackoff" anstelle von "crashloopbackoff" ist.
- Lassen Sie sich den ContainerStatus (
.status.containerStatuses
) mitkubectl get pod
ausgeben
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pod imagepullbackoff -o json | jq .status.containerStatuses
Der Container befindet sich in einem "waiting"-Zustand, weil das Container-Image nicht gefunden wurde, aber Kubernetes wird versuchen, das Image erneut herunter zu laden.
- Führen Sie
kubectl describe
aus, um die Pod-Events zu untersuchen
Der Pod wurde geplant und Kubernetes hat versucht, das Image "alpaine"
herunterzuladen. Das schlägt jedoch fehl, da das Repository nicht existiert.
Der Status ErrImagePull
bedeutet, dass das Herunterladen des Images
fehlgeschlagen ist, was als nicht-permanenter Fehler interpretiert wird.
Deshalb ändert sich der Pod-Status in "ImagePullBackOff", was bedeutet, dass
Kubernetes versucht, das Image erneut herunterzuladen.
Aufgabe 2: Image Pull Secrets nutzen
Aufgabe 2.1: Pull Secret erstellen
- Verwenden Sie
kubectl create secret docker-registry
um ein Pull Secret mit dem Namenregistry.gitlab.com
und den folgenden Einstellungen zu erstellen:- docker-server:
registry.gitlab.com
- docker-username:
${COREWIRE_TRAINING_REGISTRY_USER}
- docker-password:
${COREWIRE_TRAINING_REGISTRY_TOKEN}
- docker-server:
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl create secret docker-registry registry.gitlab.com \
--docker-server=registry.gitlab.com \
--docker-username=${COREWIRE_TRAINING_REGISTRY_USER} \
--docker-password=${COREWIRE_TRAINING_REGISTRY_TOKEN}
- Untersuchen Sie das Secret mit
kubectl get secrets registry.gitlab.com -o yaml
Aufgabe 2.2: Pod erstellen
- Erstellen Sie eine Datei
pull-secret.yaml
mit der Beschreibung eines Pods, der:- das imagePullSecrets
registry.gitlab.com
verwendet - das Container-Image
registry.gitlab.com/corewire/hands-on/k8s/images/docker-demoapp:1.0.0
verwendet - den Port 5000 freigibt
- das imagePullSecrets
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: Pod
metadata:
name: pull-secret
spec:
imagePullSecrets:
- name: registry.gitlab.com
containers:
- name: demoapp
image: registry.gitlab.com/corewire/hands-on/k8s/images/docker-demoapp:1.0.0
ports:
- name: web
containerPort: 5000
- Deployen Sie den Pod
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f pull-secret.yaml
- Überprüfen Sie den Pod mit
kubectl get pod
und stellen Sie sicher, dass er sich im Zustand "Running" befindet - Lassen Sie sich den Pod mit
kubectl get pod pull-secret -o yaml
anzeigen und überprüfen Sie, ob das ImagePullSecret korrekt konfiguriert ist
Aufgabe 2.3: Zum Pod verbinden
- Verbinden Sie sich mit dem Pod durch Port-Forwarding.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl port-forward pods/pull-secret 8082:5000
- Überprüfen Sie, ob die Demoapp erreichbar ist.
Aufgabe 3: Probes (Optional)
Aufgabe 3.1: Web Server Liveness Probe
Sie erhalten ein Basismanifest für ein Webserver-Deployment. Ihre Aufgabe ist es, eine Liveness-Probe hinzuzufügen, um den Webserver-Container neu zu starten, wenn er nicht mehr reagiert.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
replicas: 2
selector:
matchLabels:
app: web-server
template:
metadata:
labels:
app: web-server
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
- Fügen Sie der Container-Spezifikation eine HTTP-Liveness-Probe hinzu, um den
Root-Pfad
/
auf Port80
zu überprüfen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
labels:
exercise: probes
spec:
replicas: 2
selector:
matchLabels:
app: web-server
template:
metadata:
labels:
app: web-server
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
- Wenden Sie das aktualisierte Manifest an
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f web-server.yaml
- Beobachten Sie das Deployment mit den Befehlen
kubectl get pods
undkubectl describe pod
Aufgabe 3.2: Datenbank-Readiness-Probe
Passen Sie das Basismanifest für ein MySQL-Datenbank-Deployment an, indem Sie eine Readiness-Probe hinzufügen. Diese Probe sollte sicherstellen, dass die Datenbank bereit ist, Verbindungen zu akzeptieren, bevor sie als bereit markiert wird.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-db
labels:
exercise: probes
spec:
replicas: 1
selector:
matchLabels:
app: mysql-db
template:
metadata:
labels:
app: mysql-db
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
ports:
- containerPort: 3306
- Fügen Sie der Container-Spezifikation eine Readiness-Probe hinzu, um die
Datenbankbereitschaft mit dem Befehl
mysqladmin ping
zu überprüfen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-db
labels:
exercise: probes
spec:
replicas: 1
selector:
matchLabels:
app: mysql-db
template:
metadata:
labels:
app: mysql-db
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
ports:
- containerPort: 3306
readinessProbe:
exec:
command:
- mysqladmin
- ping
- Wenden Sie das aktualisierte Manifest an
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f mysql-db.yaml
- Beobachten Sie das Deployment mit den Befehlen
kubectl get pods
undkubectl describe pod
Aufgabe 3.3: Exec Liveness Probe zur Selbstheilung
Das folgende Manifest startet eine benutzerdefinierte Anwendung basierend auf Alpine
Linux. Es enthält eine exec
Liveness-Probe, die das Vorhandensein einer
bestimmten Datei überprüft. Wenn die Datei nicht vorhanden ist, sollte die Probe
fehlschlagen und darauf hinweisen, dass die Anwendung in einem schlechten
Zustand ist.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: custom-app
labels:
exercise: probes
spec:
replicas: 1
selector:
matchLabels:
app: custom-app
template:
metadata:
labels:
app: custom-app
spec:
containers:
- name: alpine-app
image: alpine:latest
command: ["/bin/sh", "-c"]
args: ["touch /tmp/alive; sleep 15; rm -f /tmp/alive; sleep 600"]
livenessProbe:
exec:
command:
- cat
- /tmp/alive
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
- Wenden Sie das Manifest an
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f custom-app.yaml
- Überwachen Sie das Verhalten der Liveness-Probe mit dem Befehl
kubectl get events -w
- Untersuchen Sie den Status des Pods mit
kubectl describe pod
- Sie können auch mit den Eigenschaften
initialDelaySeconds
,periodSeconds
undfailureThreshold
spielen, um das Verhalten der Liveness-Probe besser zu verstehen
Aufgabe 3.4: Redis TCP Liveness Probe
- Passen Sie folgendes Basismanifest für ein Redis-Deployment an. Ihre Aufgabe ist es, eine TCP-Liveness-Probe hinzuzufügen, um sicherzustellen, dass der Redis-Server reagiert.
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-server
labels:
app: redis
exercise: probes
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:alpine
ports:
- containerPort: 6379
- Fügen Sie der Container-Spezifikation eine TCP-Liveness-Probe hinzu, um Port
6379
zu überprüfen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-server
labels:
app: redis
exercise: probes
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:alpine
ports:
- containerPort: 6379
livenessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 15
periodSeconds: 20
- Wenden Sie das aktualisierte Manifest an
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f redis-deployment.yaml
- Beobachten Sie das Deployment mit den Befehlen
kubectl get pods
undkubectl describe pod
Aufgabe 3.5: Startup Probes
Das Kubelet verwendet Startup-Probes, um zu wissen, wann eine Container-Anwendung gestartet ist. Wenn eine solche Probe konfiguriert ist, starten Liveness- und Readiness-Probes erst, wenn die Startup-Probe erfolgreich ist. Das stellt sicher, dass diese Probes nicht mit dem Anwendungsstart interferieren. Dies kann verwendet werden, um Liveness-Checks auf langsam startenden Containern zu übernehmen, um zu verhindern, dass sie vom Kubelet neugestartet werden, bevor sie vollständig gestartet sind.
- Sie erhalten ein Basismanifest für ein Deployment, das eine Anwendung startet, die 15 Sekunden benötigt, um vollständig zu starten
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: slow-startup-app
labels:
exercise: probes
spec:
replicas: 1
selector:
matchLabels:
app: slow-startup-app
template:
metadata:
labels:
app: slow-startup-app
spec:
containers:
- name: alpine-app
image: alpine:latest
command: ["/bin/sh", "-c"]
args: ["sleep 15; touch /tmp/alive; sleep infinity"]
livenessProbe:
exec:
command:
- cat
- /tmp/alive
initialDelaySeconds: 1
periodSeconds: 5
failureThreshold: 2
readinessProbe:
exec:
command:
- cat
- /tmp/alive
initialDelaySeconds: 1
periodSeconds: 2
failureThreshold: 5
- Wenden Sie das gegebenen Manifest an
- Beobachten Sie das Verhalten des Containers mit den Befehlen
kubectl get events -w
undkubectl describe pod
Sie sollten sehen, dass der Container neu gestartet wird, wenn die Liveness- und Readiness-Probes fehlschlagen, bevor die Startup-Probe erfolgreich ist.
- Fügen Sie der Container-Spezifikation eine Startup-Probe hinzu, um das Vorhandensein der Datei
/tmp/alive
zu überprüfen. Konfigurieren Sie die Probe mit:initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: slow-startup-app
labels:
exercise: probes
spec:
replicas: 1
selector:
matchLabels:
app: slow-startup-app
template:
metadata:
labels:
app: slow-startup-app
spec:
containers:
- name: alpine-app
image: alpine:latest
command: ["/bin/sh", "-c"]
args: ["sleep 15; touch /tmp/alive; sleep infinity"]
livenessProbe:
exec:
command:
- cat
- /tmp/alive
initialDelaySeconds: 1
periodSeconds: 5
failureThreshold: 2
readinessProbe:
exec:
command:
- cat
- /tmp/alive
initialDelaySeconds: 1
periodSeconds: 2
failureThreshold: 5
startupProbe:
exec:
command:
- cat
- /tmp/alive
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
- Wenden Sie das aktualisierte Manifest an
- Beobachten Sie das Verhalten des Containers mit den Befehlen
kubectl get events -w
undkubectl describe pod
Cleanup
- Löschen Sie alle Objekte die Sie erstellt haben mit
kubectl delete