Plánování: taints, tolerations, affinity
Plánování: taints, tolerations, affinity
Scheduler standardně umístí pod tam, kde se vejde. Tři mechanismy to umí změnit a fungují proti sobě.
| Mechanismus | Sedí na | Říká |
|---|---|---|
| Taint | uzlu | „drž pody dál, pokud tohle netolerují“ |
| Toleration | podu | „tenhle taint mi nevadí“ |
| nodeSelector / node affinity | podu | „chci běžet na uzlu tohohle typu“ |
Ta dvojice je záměrně nesymetrická. Tolerance povoluje, ale nepřitahuje: pod, který taint toleruje, může stejně přistát kdekoli jinde. Chcete-li ho na těch uzlech, potřebujete k tomu ještě affinity.
Taints
kubectl taint node worker03 disk=ssd:NoSchedule # přidat
kubectl taint node worker03 disk=ssd:NoSchedule- # odebrat (pomlčka na konci)
kubectl describe node control01 | grep -i taint
Tři efekty:
| Efekt | Význam |
|---|---|
NoSchedule | žádný nový pod bez tolerance; běžící zůstávají |
PreferNoSchedule | scheduler se uzlu vyhýbá, pokud může – měkká nápověda |
NoExecute | totéž co výše, a navíc vystěhuje běžící pody bez tolerance |
S taintem jste se už potkali: kubectl cordon přidá
node.kubernetes.io/unschedulable:NoSchedule a uzly control plane nesou
node-role.kubernetes.io/control-plane:NoSchedule. Tainty nejsou exotika – je to
mašinerie pod příkazy, které používáte celou dobu.
Tolerations
tolerations:
- key: disk
operator: Equal
value: ssd
effect: NoSchedule
operator: Exists bez hodnoty toleruje jakoukoli hodnotu daného klíče. Vynechte
i klíč a pod toleruje všechno – takhle běží některé monitorovací DaemonSety na
každém uzlu bez ohledu na cokoli.
U NoExecute můžete přidat tolerationSeconds ve smyslu „vystěhuj mě, ale dej
mi pět minut“.
nodeSelector
Jednoduchá varianta: přesná shoda labelů, všech.
kubectl label node worker01 disktype=ssd
spec:
nodeSelector:
disktype: ssd
Node affinity
Bohatší varianta – operátory (In, NotIn, Exists, Gt, Lt) a hlavně
měkká varianta.
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # tvrdé: musí
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values: ["ssd", "nvme"]
preferredDuringSchedulingIgnoredDuringExecution: # měkké: zkus
- weight: 100
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values: ["zone-a"]
Ty dlouhé názvy čtěte doslova:
requiredDuringScheduling– když nic neodpovídá, pod zůstanePending.preferredDuringScheduling– scheduler uzly boduje a shody preferuje, ale pod umístí tak jako tak.IgnoredDuringExecution– jakmile pod běží, změna labelů uzlu s ním nepohne. Běžící pod vystěhuje jen taint sNoExecute.
Pod affinity a anti-affinity
Umístění vůči jiným podům, ne vůči uzlům. Běžnější je anti-affinity: drž moje repliky mimo stejný uzel.
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels: { app: web }
topologyKey: kubernetes.io/hostname
topologyKey definuje, co znamená „stejné místo“ – stejný uzel, stejná zóna,
stejný rack.
Pro prostý případ „rozprostři repliky rovnoměrně“ použijte raději
topologySpreadConstraints – je jednodušší a skutečně vyvažuje, kdežto
anti-affinity jen odpuzuje.
Co si vybrat?
| Cíl | Použijte |
|---|---|
| Vyhradit uzly pro určitou zátěž | taint na uzly + tolerance + affinity na podu |
| Nepustit tam nikoho dalšího | jen taint |
| Poslat pod na konkrétní hardware | nodeSelector nebo node affinity |
| Odstavit uzel na údržbu | kubectl drain (pod kapotou taint) |
| Rozprostřít repliky po uzlech | topologySpreadConstraints |