← К программе курса

Модуль 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 через NodeRestriction-compatible prefixes
  • Начинайте Pending-диагностику с Pod Events
  • Проверяйте все constraints одновременно: они объединяются логическим AND
  • Оценивайте topology при scale и rolling update
  • Перед drain проверьте PDB, local storage, unmanaged Pods и capacity других Nodes
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

Критерий: selector, affinity и toleration 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 и владельцев workload. --force и --disable-eviction обходят защитные механизмы и требуют отдельного обоснования.

09

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

  • Чем filter отличается от score?
  • Почему toleration не гарантирует Node?
  • Что означает IgnoredDuringExecution?
  • Когда DoNotSchedule опаснее ScheduleAnyway?
  • Какие данные может удалить drain?

Модуль освоен, если вы объясняете FailedScheduling, размещаете Pod декларативно и составляете безопасный план обслуживания Node.

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

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

Скачать PDFPDF