← До програми курсу

Модуль 10 / 19

Scheduling: affinity, taints і topology

KUBERNETES

Зміст
01

1. Цілі модуля

Ви навчитеся пояснювати рішення scheduler, застосовувати nodeSelector, affinity, taints/tolerations і topology spread, діагностувати Pending Pod та безпечно готувати Node до обслуговування.

02

2. Теорія: scheduling cycle

Scheduler розглядає непризначені Pods: filter виключає невідповідні Nodes, score ранжує решту, binding записує spec.nodeName. Контейнер запускає kubelet, а не scheduler.

Основні обмеження: requests і allocatable, nodeSelector/affinity, taints, topology, volume topology та host ports.

03

3. Теорія: selectors і affinity

nodeSelector — простий обов’язковий збіг labels. requiredDuringSchedulingIgnoredDuringExecution — обов’язкове правило під час scheduling; preferred — зважений пріоритет без гарантії. IgnoredDuringExecution означає, що зміна label не виселяє вже запущений Pod.

Pod affinity розміщує поруч з іншими Pods, anti-affinity розносить їх. TopologySpreadConstraints керує skew за hostname/zone; DoNotSchedule є жорстким обмеженням, ScheduleAnyway — перевагою.

04

4. Теорія: taints і tolerations

Taint відштовхує Pods, toleration лише дозволяє розглядати Node й не притягує Pod. NoSchedule блокує нове розміщення, PreferNoSchedule є м’яким, NoExecute також може виселяти вже запущені Pods.

Для виділеного node pool зазвичай поєднуйте taint з node affinity, інакше tolerating workload усе ще може потрапити на інший Node.

05

5. Методичні вказівки

  • Не використовуйте spec.nodeName замість scheduler constraints
  • Захищайте довірені node labels
  • Починайте Pending-діагностику з Pod Events
  • Перевіряйте всі constraints одночасно
  • Оцінюйте topology під час scale і rollout
  • Перед drain перевірте PDB, local storage, unmanaged Pods та capacity
06

6. Лабораторна робота: placement

Збережіть перші об’єкти як scheduling-lab.yaml, а tolerating Pod — як toleration-pod.yaml.

terminal
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"]}
terminal
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"]}
terminal
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.

07

7. Діагностика: Unschedulable Pod

Створіть Pod з обов’язковим label, якого немає на жодному Node. Він залишиться Pending без container logs.

terminal
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.

08

8. Обслуговування Node: cordon і drain

cordon забороняє нове scheduling, але не виселяє Pods. drain використовує eviction і PDB; --delete-emptydir-data дозволяє втрату emptyDir. Спочатку виконайте server dry-run.

terminal
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 обходять захист і потребують обґрунтування.

09

9. Контроль і шпаргалка

  • Чим filter відрізняється від score?
  • Чому toleration не гарантує Node?
  • Що означає IgnoredDuringExecution?
  • Коли DoNotSchedule небезпечніший за ScheduleAnyway?
  • Які дані може видалити drain?

Модуль засвоєно, якщо ви пояснюєте FailedScheduling, розміщуєте Pod декларативно й складаєте безпечний план обслуговування Node.

PDF для роботи офлайн

Завантажте оформлену версію модуля для читання без підключення до мережі.

Завантажити PDFPDF