Модуль 10 / 19
Scheduling: affinity, taints і topology
Зміст
1. Цілі модуля
Ви навчитеся пояснювати рішення scheduler, застосовувати nodeSelector, affinity, taints/tolerations і topology spread, діагностувати Pending Pod та безпечно готувати Node до обслуговування.
2. Теорія: scheduling cycle
Scheduler розглядає непризначені Pods: filter виключає невідповідні Nodes, score ранжує решту, binding записує spec.nodeName. Контейнер запускає kubelet, а не scheduler.
Основні обмеження: requests і allocatable, nodeSelector/affinity, taints, topology, volume topology та host ports.
3. Теорія: selectors і affinity
nodeSelector — простий обов’язковий збіг labels. requiredDuringSchedulingIgnoredDuringExecution — обов’язкове правило під час scheduling; preferred — зважений пріоритет без гарантії. IgnoredDuringExecution означає, що зміна label не виселяє вже запущений Pod.
Pod affinity розміщує поруч з іншими Pods, anti-affinity розносить їх. TopologySpreadConstraints керує skew за hostname/zone; DoNotSchedule є жорстким обмеженням, ScheduleAnyway — перевагою.
4. Теорія: taints і tolerations
Taint відштовхує Pods, toleration лише дозволяє розглядати Node й не притягує Pod. NoSchedule блокує нове розміщення, PreferNoSchedule є м’яким, NoExecute також може виселяти вже запущені Pods.
Для виділеного node pool зазвичай поєднуйте taint з node affinity, інакше tolerating workload усе ще може потрапити на інший Node.
5. Методичні вказівки
- Не використовуйте spec.nodeName замість scheduler constraints
- Захищайте довірені node labels
- Починайте Pending-діагностику з Pod Events
- Перевіряйте всі constraints одночасно
- Оцінюйте topology під час scale і rollout
- Перед drain перевірте PDB, local storage, unmanaged Pods та capacity
6. Лабораторна робота: placement
Збережіть перші об’єкти як scheduling-lab.yaml, а tolerating Pod — як toleration-pod.yaml.
apiVersion: v1
kind: Namespace
metadata: {name: lab-scheduling}
---
apiVersion: v1
kind: Pod
metadata: {name: selector-demo, namespace: lab-scheduling}
spec:
nodeSelector: {workload.course/tier: general}
containers:
- {name: app, image: "busybox:1.37.0", command: ["sh", "-c", "sleep 3600"]}
---
apiVersion: v1
kind: Pod
metadata: {name: affinity-demo, namespace: lab-scheduling}
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- {key: workload.course/tier, operator: In, values: [general]}
containers:
- {name: app, image: "busybox:1.37.0", command: ["sh", "-c", "sleep 3600"]}apiVersion: v1
kind: Pod
metadata: {name: toleration-demo, namespace: lab-scheduling}
spec:
nodeSelector: {workload.course/tier: general}
tolerations:
- {key: dedicated, operator: Equal, value: course, effect: NoSchedule}
containers:
- {name: app, image: "busybox:1.37.0", command: ["sh", "-c", "sleep 3600"]}kubectl label node course-worker workload.course/tier=general
kubectl apply -f scheduling-lab.yaml
kubectl wait -n lab-scheduling --for=condition=Ready pod/selector-demo pod/affinity-demo --timeout=120s
kubectl get pods -n lab-scheduling -o wide
kubectl taint node course-worker dedicated=course:NoSchedule
kubectl apply -f toleration-pod.yaml
kubectl wait -n lab-scheduling --for=condition=Ready pod/toleration-demo --timeout=120s
kubectl get pods -n lab-scheduling -o wide
kubectl get node course-worker --show-labelsКритерій: усі Pods Ready на course-worker; toleration-demo запускається попри taint.
7. Діагностика: Unschedulable Pod
Створіть Pod з обов’язковим label, якого немає на жодному Node. Він залишиться Pending без container logs.
kubectl run impossible -n lab-scheduling --image=busybox:1.37.0 --overrides='{"spec":{"nodeSelector":{"hardware.course/gpu":"true"},"containers":[{"name":"impossible","image":"busybox:1.37.0","command":["sh","-c","sleep 3600"]}]}}'
kubectl get pod impossible -n lab-scheduling
kubectl describe pod impossible -n lab-scheduling
kubectl events -n lab-scheduling --for pod/impossible --types=Warning
kubectl label node course-worker hardware.course/gpu=true
kubectl wait -n lab-scheduling --for=condition=Ready pod/impossible --timeout=120s
kubectl get pod impossible -n lab-scheduling -o wideЛанцюжок: Pod Events → requests/allocatable → labels і required affinity → taints/tolerations → volume topology → ports. Виправляйте причину, зазначену у FailedScheduling.
8. Обслуговування Node: cordon і drain
cordon забороняє нове scheduling, але не виселяє Pods. drain використовує eviction і PDB; --delete-emptydir-data дозволяє втрату emptyDir. Спочатку виконайте server dry-run.
kubectl drain course-worker --ignore-daemonsets --delete-emptydir-data --dry-run=server
kubectl cordon course-worker
kubectl get nodes
kubectl uncordon course-worker
kubectl taint node course-worker dedicated=course:NoSchedule-
kubectl label node course-worker workload.course/tier- hardware.course/gpu-
kubectl delete namespace lab-schedulingНе запускайте реальний drain без перевірки capacity. --force і --disable-eviction обходять захист і потребують обґрунтування.
9. Контроль і шпаргалка
- Чим filter відрізняється від score?
- Чому toleration не гарантує Node?
- Що означає IgnoredDuringExecution?
- Коли DoNotSchedule небезпечніший за ScheduleAnyway?
- Які дані може видалити drain?
Модуль засвоєно, якщо ви пояснюєте FailedScheduling, розміщуєте Pod декларативно й складаєте безпечний план обслуговування Node.
PDF для роботи офлайн
Завантажте оформлену версію модуля для читання без підключення до мережі.