Pods auf Nodes verteilen
Ziel
In diesem Projekt geht es um den Scheduler und wie Pods auf Nodes verteilt werden. Sie werden:
- Node-Selektoren verwenden
- Node-Affinity und Pod-(Anti-)Affinity verwenden
- Taints und Tolerations testen
- Resource Requests und Limits setzen
Hilfsmittel
- Versuchen Sie, die unten stehenden Aufgaben mit Hilfe der Folien und der 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: Kubernetes Scheduling verstehen
Der Kubernetes Scheduler ist für die Zuweisung von Pods zu Nodes verantwortlich. Er berücksichtigt dabei verschiedene Kriterien wie Ressourcenverfügbarkeit, Scheduling-Richtlinien, Affinitäts- und Anti-Affinitätsspezifikationen, Taints und Tolerations.
- Erstellen Sie eine Deployment YAML-Datei
scheduling.yaml
und definieren Sie ein Deployment, das das nginx-Image verwendet und 10 Replikate spezifiziert:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-scheduling
spec:
replicas: 10
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
- Wenden Sie die Deployment-Datei an und überprüfen Sie, wie die Pods auf den Nodes verteilt werden
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f scheduling.yaml
kubectl get deployments
kubectl get pods -o wide
Aufgabe 2: Node-Selektoren verwenden
Node-Selektoren sind eine Möglichkeit, Pods auf bestimmte Nodes zu beschränken. Sie können verwendet werden, um Pods auf Nodes mit bestimmten Eigenschaften zu platzieren.
Aufgabe 2.1: Node mit Labels versehen
Der Training-Cluster hat drei Worker-Nodes, diese Nodes sind alle identisch:
k get nodes
NAME STATUS ROLES AGE VERSION
code-0-worker-wppfn-5k28c Ready <none> 3d1h v1.28.6
code-0-worker-wppfn-hx7qs Ready <none> 3d1h v1.28.6
code-0-worker-wppfn-v5vts Ready <none> 3d1h v1.28.6
Für diese Übung werden wir einen von ihnen als node-type=gpu
bezeichnen und ein Deployment darauf planen.
- Labeln Sie den ersten Node mit
node-type=gpu
:
kubectl label node <node_name> node-type=gpu
- Überprüfen Sie, ob der Node gelabelt wurde:
kubectl get nodes --show-labels
Aufgabe 2.2: Deployment mit Node-Selektor erstellen
- Kopieren Sie das Deployment aus Aufgabe 1 in die neue Datei
node-selector.yaml
und fügen Sie einen Node-Selektor hinzu, um die Pods auf den Node mit dem Labelnode-type=gpu
zu beschränken
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
nodeSelector:
node-type: gpu
containers:
- name: nginx
image: nginx
- Wenden Sie die Deployment-Datei an und überprüfen Sie, wie die Pods auf den Nodes verteilt werden
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f nodeselector.yaml
kubectl get pods -o wide
Aufgabe 3: Node-Affinity
Node-Affinity ist eine erweiterte Möglichkeit, Pods auf Nodes zu platzieren. Es ermöglicht Ihnen, Regeln zu definieren, die bestimmen, auf welchen Nodes ein Pod geplant werden soll.
Aufgabe 3.1: Deployment mit Node-Affinity
- Erstellen Sie eine Deployment-Datei
node-affinity.yaml
und fügen Sie das folgende Deployment hinzu:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-affinity
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25.4-alpine
- Erweitern Sie das Deployment, um eine Node-Affinität zu
node-type=gpu
zu haben
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
apiVersion: apps/v1
kind: Deployment
metadata:
name: gpu-nginx
labels:
exercise: node-affinity
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25.4-alpine
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-type
operator: In
values:
- gpu
- Wenden Sie das Deployment auf Ihrem Cluster an und beobachten Sie die Verteilung der Pods auf den Nodes
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f gpu-deployment.yaml
kubectl get pods -o wide
Aufgabe 4: Pod Resource Requests und Limits
Aufgabe 4.1: Ressourcen für einen Pod anfordern
- Erstellen Sie eine Pod-Datei
request-ressources.yaml
und fügen Sie den folgenden Pod-Manifest hinzu.
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-server
labels:
exercise: resources
spec:
containers:
- name: nginx
image: nginx:1.25.4-alpine
- Erweitern Sie das Pod-Manifest, um Ressourcenanforderungen und -limits für CPU und Speicher:
- Anforderungen: 0,5 CPU und 512Mi Speicher
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: Pod
metadata:
name: requests-demo
labels:
exercise: resources
spec:
containers:
- name: nginx
image: nginx:1.25.4-alpine
resources:
requests:
memory: "512Mi"
cpu: "500m"
- Wenden Sie das Pod-Manifest auf den Cluster an und überprüfen Sie, ob der Pod erstellt wurde und inspizieren Sie die Ressourcenanforderungen und -limits mit dem
kubectl describe pod
-Befehl
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f request-ressources.yaml
kubectl describe pod requests-demo
Aufgabe 4.2: Ressourcen für einen Pod begrenzen
- Erstellen Sie eine Datei
limit-ressources.yaml
mit folgendem Pod-Manifest:
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-server
labels:
exercise: resources
spec:
containers:
- name: nginx
image: nginx:1.25.4-alpine
- Erweitern Sie das Pod-Manifest, um Ressourcenlimits für CPU und Speicher:
- Begrenzen Sie die CPU auf 1 CPU und den Speicher auf 1Gi
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: Pod
metadata:
name: limit-demo
labels:
exercise: resources
spec:
containers:
- name: nginx
image: nginx:1.25.4-alpine
resources:
limits:
memory: "1Gi"
cpu: "1"
- Wenden Sie das Pod-Manifest auf den Cluster an und überprüfen Sie, ob der Pod erstellt wurde und inspizieren Sie die Ressourcenlimits mit dem
kubectl describe pod
-Befehl
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f limit-ressources.yaml
kubectl describe pod limit-demo
Aufgabe 4.3: Resourcenanforderungen und -limits verbinden
- Erstellen Sie eine Datei
requests-and-limits-demo.yaml
mit folgendem Pod-Manifest:
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-server
labels:
exercise: resources
spec:
containers:
- name: nginx
image: nginx:1.25.4-alpine
- Erweitern Sie das Pod-Manifest, um Ressourcenanforderungen und -limits für CPU und Speicher:
- Anforderungen: 0,5 CPU und 512Mi Speicher
- Begrenzen Sie die CPU auf 1 CPU und den Speicher auf 1Gi
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: Pod
metadata:
name: modify-demo
labels:
exercise: resources
spec:
containers:
- name: nginx
image: nginx:1.25.4-alpine
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1"
- Wenden Sie das Pod-Manifest auf den Cluster an und überprüfen Sie, ob der Pod erstellt wurde und inspizieren Sie die Ressourcenanforderungen und -limits mit dem
kubectl describe pod
-Befehl
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f modify-ressources.yaml
kubectl describe pod modify-demo
Aufgabe 4.4: Out of Memory (OOM) Error provozieren
Um zu verstehen, wie Kubernetes auf ein Pod reagiert, der seinen Speicherlimit überschreitet, erstellen Sie einen Pod, der absichtlich mehr Speicher verwendet als ihm zugewiesen ist.
- Erstellen Sie eine Datei
oom-example.yaml
und fügen Sie das folgende Pod-Manifest hinzu. Dieses Manifest enthält einen Container, der versucht, mehr Speicher zu verbrauchen, als sein Limit:
---
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
labels:
exercise: resources
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
requests:
memory: "100Mi"
limits:
memory: "200Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "500M", "--vm-hang", "1"]
- Wenden Sie das Pod-Manifest auf den Cluster an
- Beobachten Sie den Pod-Status mit dem Befehl
watch kubectl get pods
Der Pod sollte sich in einem CrashLoopBackOff
-Zustand befinden und der Befehl
kubectl describe pod memory-demo
sollte eine OOMKilled
-Meldung in den
Events des Pods anzeigen.
Clean Up
- Löschen Sie die erstellten Resourcen