Einführung
Normalerweise wählt der Scheduler jeden geeigneten Node aus. Labels und Affinitäten beschreiben die Präferenzen eines Workloads, während Taints dafür sorgen, dass Nodes Pods ohne passende Tolerations abweisen.
In diesem Experiment wenden Sie diese Steuerungsmöglichkeiten schrittweise auf den vorbereiteten Node an. Mithilfe von Pod-Ereignissen unterscheiden Sie dabei zwischen einer zwingenden Planungsregel und einer optionalen Präferenz.
Merken Sie sich folgendes Modell: Labels beschreiben Nodes, Selektoren und Affinitäten formulieren die Anforderungen eines Pods, Taints legen fest, was ein Node ablehnt, und Tolerations erlauben einem Pod, eine passende Ablehnungsregel zu passieren. Keine dieser Mechanismen verschiebt einen bereits laufenden Pod direkt.
Den Node für die Platzierung labeln
In diesem Schritt fügen Sie beschreibende Labels hinzu und lassen sie als zusätzliche Spalten anzeigen.
Die Labels beziehen sich bewusst auf die Platzierung des Workloads und nicht auf die Identität der Anwendung. workload-zone=local beschreibt den Standort, während disk-class=fast eine verfügbare Eigenschaft angibt. Kubernetes überprüft die fachliche Bedeutung dieser Werte nicht; erst Ihre Planungsregeln verleihen ihnen eine konkrete Bedeutung.
cd /home/labex/project/pod-scheduling
kubectl create namespace practice-scheduling
kubectl label node labex-v135 workload-zone=local disk-class=fast
kubectl get nodes -L workload-zone,disk-class
Labels sind Informationen, die von Selektoren und Affinitäten verwendet werden. Sie verschieben bestehende Pods nicht automatisch, sofern ein Controller nicht Ersatz-Pods erstellt.
Die Option -L fügt für jeden Label-Schlüssel eine eigene Spalte hinzu. Wenn in der Node-Zeile local und fast angezeigt werden, kann der Scheduler die Regeln aus den folgenden Schritten auswerten.
NAME STATUS ROLES ... VERSION WORKLOAD-ZONE DISK-CLASS
labex-v135 Ready control-plane ... v1.35.5 local fast
Damit wird außerdem bestätigt, dass die aktualisierte Umgebung Kubernetes v1.35.5 ausführt. Die beiden benutzerdefinierten Spalten stammen aus den Labels, die Sie gerade hinzugefügt haben.
Einen Node mit nodeSelector voraussetzen
In diesem Schritt erstellen Sie einen Pod mit der einfachsten Regel für eine exakte Platzierung.
nodeSelector ist eine Zuordnung zwingend erforderlicher Gleichheitsbedingungen. Der Pod kann nur auf einem Node eingeplant werden, bei dem jeder Schlüssel den angeforderten Wert besitzt. Das eignet sich für einfache, verbindliche Platzierungsvorgaben.
cd /home/labex/project/pod-scheduling
cat <<'EOF' > selected-pod.yaml
apiVersion: v1
kind: Pod
metadata: {name: selected-pod, namespace: practice-scheduling}
spec:
nodeSelector: {disk-class: fast}
containers:
- {name: worker, image: busybox:1.36, imagePullPolicy: IfNotPresent, command: ["sh", "-c", "while true; do sleep 30; done"]}
EOF
Wenden Sie die Pod-Konfiguration an, warten Sie, bis der Pod bereit ist, und prüfen Sie den zugewiesenen Node in der Spalte NODE:
kubectl apply -f selected-pod.yaml
kubectl wait --for=condition=Ready pod/selected-pod -n practice-scheduling --timeout=120s
kubectl get pod selected-pod -n practice-scheduling -o wide
nodeSelector ist zwingend: Wenn kein Node alle angeforderten Labels besitzt, bleibt der Pod im Status „Pending“.
Der ausgewählte Node sollte labex-v135 sein. Der erfolgreiche Planungsvorgang zeigt, dass disk-class=fast auf dem Node die Anforderung des Pods erfüllt.
pod/selected-pod condition met
NAME READY STATUS ... NODE
selected-pod 1/1 Running ... labex-v135
Die Spalte NODE zeigt das Ergebnis der Planung. Der im Manifest angegebene nodeSelector erklärt, warum dieser Node geeignet war.
Erforderliche und bevorzugte Affinität vergleichen
In diesem Schritt erstellen Sie einen Pod, der die lokale Zone voraussetzt und schnelle Datenträger bevorzugt.
Die Node-Affinität ist ausdrucksstärker als nodeSelector. Der erforderliche Abschnitt schließt Nodes aus, die nicht passen. Der bevorzugte Abschnitt weist passenden Nodes dagegen ein Gewicht zu, macht diese Präferenz aber nicht verbindlich.
Die langen Feldnamen beschreiben den Zeitpunkt der Auswertung: Die Regel wird während der Planung berücksichtigt und während der Ausführung ignoriert. Wenn sich ein Label später ändert, entfernt Kubernetes den laufenden Pod nicht allein aufgrund dieser Affinitätsregel.
cd /home/labex/project/pod-scheduling
cat <<'EOF' > affinity-pod.yaml
apiVersion: v1
kind: Pod
metadata: {name: affinity-pod, namespace: practice-scheduling}
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions: [{key: workload-zone, operator: In, values: [local]}]
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions: [{key: disk-class, operator: In, values: [fast]}]
containers:
- {name: worker, image: busybox:1.36, imagePullPolicy: IfNotPresent, command: ["sh", "-c", "while true; do sleep 30; done"]}
EOF
Wenden Sie die Pod-Konfiguration an und warten Sie auf die Einplanung:
kubectl apply -f affinity-pod.yaml
kubectl wait --for=condition=Ready pod/affinity-pod -n practice-scheduling --timeout=120s
kubectl get pod affinity-pod -n practice-scheduling -o wide
Erforderliche Regeln filtern die geeigneten Nodes. Bevorzugte Regeln bewerten anschließend die verbleibenden Nodes. IgnoredDuringExecution bedeutet, dass spätere Änderungen an Labels keinen laufenden Pod entfernen.
Auch in der resultierenden Tabelle wird labex-v135 angezeigt. In diesem Cluster mit nur einem Node bestimmt die erforderliche Regel workload-zone=local, ob der Node geeignet ist. Die bevorzugte Regel für schnelle Datenträger veranschaulicht die Syntax für die Bewertung, ohne für den Vergleich einen zweiten Node anlegen zu müssen.
Einen Taint und eine Toleration verwenden
In diesem Schritt versehen Sie den Node mit einem Taint, beobachten, wie ein Pod ohne passende Toleration im Status „Pending“ bleibt, und erstellen anschließend einen zugelassenen Pod.
Der Taint hat den Schlüssel practice-reserved, den Wert true und den Effekt NoSchedule. Dieser Effekt verhindert die Einplanung neuer Pods ohne passende Toleration, entfernt jedoch keine Pods, die bereits auf dem Node laufen.
kubectl taint node NODE key=value:effect fügt einem Node diese Regel hinzu. Der folgende Aufruf von kubectl run erstellt einen eigenständigen Pod ohne Toleration. Durch das Warten auf die Bedingung PodScheduled erhält der Scheduler zehn Sekunden Zeit, das erwartete Fehlschlagen zu zeigen.
cd /home/labex/project/pod-scheduling
kubectl taint node labex-v135 practice-reserved=true:NoSchedule
kubectl run blocked-pod -n practice-scheduling --image=busybox:1.36 --image-pull-policy=IfNotPresent --restart=Never -- sh -c 'sleep 3600'
kubectl wait --for=condition=PodScheduled pod/blocked-pod -n practice-scheduling --timeout=10s || true
kubectl events -n practice-scheduling --for pod/blocked-pod
Das Zeitlimit ist in diesem Fall erwartungsgemäß erreicht. || true sorgt dafür, dass die Lektion trotzdem fortgesetzt wird. Das Planungsereignis sollte einen nicht tolerierten Taint erwähnen und damit erklären, warum der Pod im Status „Pending“ bleibt.
error: timed out waiting for the condition on pods/blocked-pod
LAST SEEN TYPE REASON OBJECT MESSAGE
... Warning FailedScheduling Pod/blocked-pod 0/1 nodes are available: 1 node(s) had untolerated taint(s)...
Hier ist „Pending“ das korrekte Versuchsergebnis. Der Scheduler hat den Pod ausgewertet, aber keinen Node gefunden, den der Pod verwenden durfte.
Erstellen Sie nun eine passende Toleration. Eine Toleration erlaubt die Einplanung trotz des Taints; sie wählt den Node jedoch nicht selbst aus.
cat <<'EOF' > tolerated-pod.yaml
apiVersion: v1
kind: Pod
metadata: {name: tolerated-pod, namespace: practice-scheduling}
spec:
nodeSelector: {workload-zone: local}
tolerations:
- {key: practice-reserved, operator: Equal, value: "true", effect: NoSchedule}
containers:
- {name: worker, image: busybox:1.36, imagePullPolicy: IfNotPresent, command: ["sh", "-c", "while true; do sleep 30; done"]}
EOF
kubectl apply -f tolerated-pod.yaml
kubectl wait --for=condition=Ready pod/tolerated-pod -n practice-scheduling --timeout=120s
kubectl delete pod blocked-pod -n practice-scheduling
Der tolerierte Pod besitzt zusätzlich einen nodeSelector. Eine Regel wählt also den Node aus, während die andere den Zugriff erlaubt. Durch das Löschen des absichtlich blockierten Pods bleibt der Namespace in einem sauberen und fehlerfreien Zustand.
pod/tolerated-pod condition met bestätigt, dass die passende Toleration das Ergebnis verändert hat. Die zuvor erstellten Pods laufen weiter, da NoSchedule nur die Platzierung neuer Pods betrifft und bereits laufende Pods nicht entfernt.
Zusammenfassung
Sie haben Labels, nodeSelector, erforderliche und bevorzugte Affinitäten, Scheduler-Ereignisse, Taints und Tolerations verwendet, um Platzierungsabsichten und die Zulassung durch Nodes unabhängig voneinander zu steuern.


