Taint/Tolerations
Taint - это внутренний механизм, распределения подов по нодам кластера. Позволяет ограничить для подов запуск и шедуллинг на определённых нодах. Устанавливается на ноду кластера. Tolerations - позволяет сделать исключение для отдельных подов и позволяющий им запускаться на нодах с установленным taints.
Taint – это NodeAffinity наоборот. Если nodeAffinity говорит scheduler-у, где он должен размещать pod-ы, то taint говорит, где pod-ы размещать нельзя. Любой taint запрещает размещение на машине любых подов (есть одно исключение, про него дальше). Однако можно создать под, который будет игнорировать tolerations этот запрет – и данный pod запустится на данной машине.
1. На master nodes тоже есть taint. Это taint node-role.kubernetes.io/master, запрещающий аллоцировать на них любой под.
2. Taint никак не связан с безопасностью в кластере. Это просто механизм ограничивающий запуск и шедулинг подов. Защитить кластер он никак не может.
3. Taint and tolerations не предписывают поду размещаться на конкретном узле. На котором установлен taint и для которого у пода установлен tolerations. Такой под может разместиться и на других узлах кластера.
Посмотрим список нод в кластере.
kubectl get nodes NAME STATUS ROLES AGE VERSION cl10sucmg9fveg2v9mka-ijym Ready <none> 15d v1.22.6 cl16hmah0j04fn6h944k-ilis Ready <none> 66m v1.22.6 cl18jmsftl4879u5tuu0-izym Ready <none> 4h9m v1.22.6
Установим на одну из них политику taint.
kubectl taint nodes cl18jmsftl4879u5tuu0-izym cam=taint:NoSchedule kubectl taint nodes cl18jmsftl4879u5tuu0-izym cam=taint:PreferNoSchedule kubectl taint nodes cl18jmsftl4879u5tuu0-izym cam=taint:NoExecute
Здесь cam=taint - это просто метка, которая в общем-то может быть совершенно произвольная.
Создадим Deployment и посмотрим будут ли на ноду с taint аллоцироваться поды.
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: cam-nginx
spec:
replicas: 16
selector:
matchLabels:
cam: nginx
template:
metadata:
labels:
cam: nginx
spec:
containers:
- name: cam-nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
restartPolicy: Always
EOFkubectl describe no cl18jmsftl4879u5tuu0-izym
Name: cl18jmsftl4879u5tuu0-izym
Roles: <none>
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/instance-type=standard-v3
beta.kubernetes.io/os=linux
cam=taint
failure-domain.beta.kubernetes.io/zone=ru-central1-c
kubernetes.io/arch=amd64
kubernetes.io/hostname=cl18jmsftl4879u5tuu0-izym
kubernetes.io/os=linux
node.kubernetes.io/instance-type=standard-v3
node.kubernetes.io/kube-proxy-ds-ready=true
node.kubernetes.io/masq-agent-ds-ready=true
node.kubernetes.io/node-problem-detector-ds-ready=true
topology.kubernetes.io/zone=ru-central1-c
yandex.cloud/node-group-id=catlsf230utg39omk0nc
yandex.cloud/pci-topology=k8s
yandex.cloud/preemptible=true
Annotations: csi.volume.kubernetes.io/nodeid:
{"disk-csi-driver.mks.ycloud.io":"ef36k7398e4u22vp3oji","io.ycloud.mks.disk-csi-driver":"ef36k7398e4u22vp3oji"}
node.alpha.kubernetes.io/ttl: 0
projectcalico.org/IPv4Address: 10.130.0.33/24
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Fri, 23 Sep 2022 17:35:42 +0300
Taints: cam=taint:NoExecute
cam=taint:NoSchedule
Unschedulable: false
Lease:
HolderIdentity: cl18jmsftl4879u5tuu0-izym
AcquireTime: <unset>
RenewTime: Sat, 24 Sep 2022 13:05:23 +0300
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
KernelDeadlock False Sat, 24 Sep 2022 13:03:08 +0300 Fri, 23 Sep 2022 17:35:58 +0300 KernelHasNoDeadlock kernel has no deadlock
ReadonlyFilesystem False Sat, 24 Sep 2022 13:03:08 +0300 Fri, 23 Sep 2022 17:35:58 +0300 FilesystemIsNotReadOnly Filesystem is not read-only
FrequentUnregisterNetDevice Unknown Sat, 24 Sep 2022 13:03:08 +0300 Fri, 23 Sep 2022 17:35:59 +0300 NoFrequentUnregisterNetDevice node is functioning properly
FrequentKubeletRestart Unknown Sat, 24 Sep 2022 13:03:08 +0300 Fri, 23 Sep 2022 17:35:59 +0300 NoFrequentKubeletRestart kubelet is functioning properly
FrequentDockerRestart Unknown Sat, 24 Sep 2022 13:03:08 +0300 Fri, 23 Sep 2022 17:35:59 +0300 NoFrequentDockerRestart docker is functioning properly
FrequentContainerdRestart Unknown Sat, 24 Sep 2022 13:03:08 +0300 Fri, 23 Sep 2022 17:35:59 +0300 NoFrequentContainerdRestart containerd is functioning properly
CorruptDockerOverlay2 Unknown Sat, 24 Sep 2022 13:03:08 +0300 Fri, 23 Sep 2022 17:35:59 +0300 NoCorruptDockerOverlay2 docker overlay2 is functioning properly
NetworkUnavailable False Fri, 23 Sep 2022 17:35:50 +0300 Fri, 23 Sep 2022 17:35:50 +0300 RouteCreated RouteController created a route
MemoryPressure False Sat, 24 Sep 2022 13:02:55 +0300 Fri, 23 Sep 2022 17:35:41 +0300 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Sat, 24 Sep 2022 13:02:55 +0300 Fri, 23 Sep 2022 17:35:41 +0300 KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False Sat, 24 Sep 2022 13:02:55 +0300 Fri, 23 Sep 2022 17:35:41 +0300 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Sat, 24 Sep 2022 13:02:55 +0300 Fri, 23 Sep 2022 17:36:01 +0300 KubeletReady kubelet is posting ready status. AppArmor enabled
Addresses:
InternalIP: 10.130.0.33
ExternalIP: 51.250.46.162
Hostname: cl18jmsftl4879u5tuu0-izym
Capacity:
cpu: 2
ephemeral-storage: 99034708Ki
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 4026060Ki
pods: 32
Allocatable:
cpu: 1930m
ephemeral-storage: 49394455606
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 2772684Ki
pods: 32
System Info:
Machine ID: 230000073c6888b69deb8cf2a12dc048
System UUID: 23000007-3c66-a1c6-9438-9e10bf91e272
Boot ID: a6d70f56-d00b-4ddb-b4e8-43fbf4b06a88
Kernel Version: 5.4.0-124-generic
OS Image: Ubuntu 20.04.4 LTS
Operating System: linux
Architecture: amd64
Container Runtime Version: containerd://1.6.7
Kubelet Version: v1.22.6
Kube-Proxy Version: v1.22.6
PodCIDR: 192.168.2.64/26
PodCIDRs: 192.168.2.64/26
ProviderID: yandex://ef36k7398e4u22vp3oji
Non-terminated Pods: (5 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age
--------- ---- ------------ ---------- --------------- ------------- ---
kube-system calico-node-bddbg 250m (12%) 0 (0%) 0 (0%) 0 (0%) 19h
kube-system ip-masq-agent-klbsq 10m (0%) 0 (0%) 16Mi (0%) 0 (0%) 19h
kube-system kube-proxy-92pkl 100m (5%) 0 (0%) 0 (0%) 0 (0%) 19h
kube-system npd-v0.8.0-x79nm 20m (1%) 200m (10%) 20Mi (0%) 100Mi (3%) 19h
kube-system yc-disk-csi-node-v2-76phn 30m (1%) 600m (31%) 96Mi (3%) 600Mi (22%) 19h
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 410m (21%) 800m (41%)
memory 132Mi (4%) 700Mi (25%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-1Gi 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
Events: <none>Ни одного пода с наименованием cam-nginx!
kubectl delete deploy cam-nginx
Tolerations
Если taint - это замок, то toleration - это ключ от этого замка. Он позволяет отдельным подам аллоцироваться на ноду с установленным taint.
Модернизируем наш Deployment и взглянем на дескрайб ноды.
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: cam-nginx
spec:
replicas: 2
selector:
matchLabels:
cam: nginx
template:
metadata:
labels:
cam: nginx
spec:
containers:
- name: cam-nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
restartPolicy: Always
tolerations:
- key: "cam"
operator: "Exists"
effect: "NoSchedule"
- key: "cam"
operator: "Exists"
effect: "NoExecute"
EOFБлок toleration здесь разрешает установить поды из этого deployment на ноду с двумя установленными taint-политиками.
tolerations:
- key: "cam"
operator: "Exists"
effect: "NoSchedule"
- key: "cam"
operator: "Exists"
effect: "NoExecute"Посмотрим на кусок вывода дескрайба:
Non-terminated Pods: (6 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age --------- ---- ------------ ---------- --------------- ------------- --- default cam-nginx-c77857886-78sb5 0 (0%) 0 (0%) 0 (0%) 0 (0%) 69s kube-system calico-node-bddbg 250m (12%) 0 (0%) 0 (0%) 0 (0%) 19h kube-system ip-masq-agent-klbsq 10m (0%) 0 (0%) 16Mi (0%) 0 (0%) 19h kube-system kube-proxy-92pkl 100m (5%) 0 (0%) 0 (0%) 0 (0%) 19h kube-system npd-v0.8.0-x79nm 20m (1%) 200m (10%) 20Mi (0%) 100Mi (3%) 19h kube-system yc-disk-csi-node-v2-76phn 30m (1%) 600m (31%) 96Mi (3%) 600Mi (22%) 19h
Вот теперь под успешно аллоцировался!
Когда нужно использовать taints/tolerations?
Это полезный инструмент, когда необходимо скрыть ноду со специфическими ресурсами от большинства подов. Например, когда есть нода с GPU шедулить на неё поды, которым эта GPU необходима для работы. Например, для каких-то расчётов. Также это может быть какое-то специфическое шифрование на аппаратном уровне.
Особенности взаимодействия taint и pod:
1. Если навесить политику NoSchedule на ноду где уже зашедулены поды, то они никуда не денуться.
2. Если добавить политику NoExecute, то поды на этой ноде перейдут в состояние Pending.
3. У taint наивысший приоритет среди инструкций. Это означает, что даже если у пода установлены nodeName/nodeSelector или podAffinity/podAntiAffinity, то он всё равно не сможет быть зашедулен на ноду с установленным taints. Если нет соответствующего блока tolerations в спецификации пода, разрешающего шедулинг на эту ноду.
4. Есть ещё нюанс работы taint и standalone pod. Об этом позже.
kubectl taint nodes cl18jmsftl4879u5tuu0-izym cam=taint:NoSchedule- kubectl taint nodes cl18jmsftl4879u5tuu0-izym cam=taint:NoExecute-
# operator Equal - точное сопоставление значений key=value tolerations: - key: cam value: app operator: Equal effect: NoSchedule - key: cam value: app operator: Equal effect: NoExecute
Полезные ссылки.
Подробно про taints/tolerations:
https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
Про поды писал здесь: https://teletype.in/@cameda2/Yme-IYqYWB0
Про ноды кластера здесь: https://teletype.in/@cameda2/PVXtu-qHWcv