🚀 Taint & Toleration

🚀 Taint
테인트(Taints)와 톨러레이션(Tolerations) | Kubernetes
- Taint : 특정 노드에 역할을 부여
- Toleration : Taint 노드에 스케줄링 허용
vagrant@k8s-node1 ~/schedule/affinity kubectl describe node node1
Taints: <none>
node-role.kubernetes.io/master:NoSchedule
현재 시스템에서는 node1이 컨트롤 플레인이자 워커 노드로 작동하고 있다.
컨트롤 플레인 시스템에는 다음과 같이 Taint key에 Effect가 세팅되어 있다.
워커 노드에는 파드를 배치할 수 있으므로 node1에도 파드가 배치될 수 있다.
만약 node1이 컨트롤 플레인 역할만을 한다면 Taint가 설정되어 있을 것이다.
Taint가 과연 무엇이길래 스케줄링이 되지 않는가 ?
vagrant@k8s-node1 ~ kubectl explain pod.spec.tolerations
FIELDS:
effect <string>
key <string>
operator <string>
tolerationSeconds <integer>
value <string>
- operator
- Exists : 키만 존재
- Equal(default) : 값까지 같아야 한다.
- effect
- NoSchedule
- PreferNoSchedule : 스케줄링 될 때 가능하면 배치하지 않는다. 이미 실행되고 있는 것들에 대해서는 상관없다.
- NoExecute : 현재 실행되고 있는 것들까지 포함한다.
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
kubectl taint nodes node1 key1=value1:NoSchedule
다음 YAML 파일과 명령형 커맨드는 똑같이 동작한다.
이때 해당 tolerations값을 사용하는 파드는 node1에 배치될 수 있다.
파드를 만들 때 tolerations을 설정할 수 있는 tolerations과 taint조건이 맞으면 파드는 해당 노드에 배치될 수 있다.
Taint는 특정 노드에 역할, 기능을 부여한다.
컨트롤 플레인 전용 노드에서는 node-role.kubernetes.io/master:NoSchedule이 설정되어 있었다.
지금까지 파드를 만들 때 tolerations을 설정한 적이 없었다. 그래서 파드가 컨트롤 플레인에 배치될 수 없었다.
node-role.kubernetes.io/master:NoSchedule의 의미는 마스터이므로 스케줄링 하지말라는 뜻이다.
그렇다면 Taint는 단순히 스케줄링을 막는 것인가 ?
1차원적으로는 그렇게 생각할 수 있지만 근본적으로 특정한 역할을 부여하는 것이다.
즉, 마스터에 배치하고 싶으면 node-role.kubernetes.io/master:NoSchedule tolerations을 세팅해야 한다.
kubectl taint nodes node1 key1=value1:NoSchedule-
다음 명령으로 taint를 제거할 수 있다.
🚀 실습
vagrant@k8s-node1 ~/schedule/affinity kubectl taint node node1 node-role.kubernetes.io/master:NoSchedule
node/node1 tainted
vagrant@k8s-node1 ~/schedule/affinity kubectl describe node node1 | grep -i taint
Taints: node-role.kubernetes.io/master:NoSchedule
다음과 같이 taint 설정이 되어있는 것을 확인할 수 있다.
vagrant@k8s-node1 ~/schedule/affinity kubectl create -f myweb-a.yaml
replicaset.apps/myweb-a created
vagrant@k8s-node1 ~/schedule/affinity kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myweb-a-464bw 0/1 Pending 0 4s <none> <none> <none> <none>
myweb-a-hn65z 1/1 Running 0 4s 10.233.96.145 node2 <none> <none>
myweb-a-szhkz 1/1 Running 0 4s 10.233.92.165 node3 <none> <none>
nfs-client-provisioner-758f8cd4d6-wpjbt 1/1 Running 0 3d 10.233.92.110 node3 <none> <none>
Pending이 걸리고 배치가 되지 않는다.
노드 3개가 있고 anti-affinity에 의해 myweb-a는 모두 다른 노드에 배치되어야 한다.
따라서 node1에 배치되어야 하나 배치할 수 없다.
vagrant@k8s-node1 ~/schedule/affinity kubectl describe po myweb-a-464bw
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 52s default-scheduler 0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match pod anti-affinity rules.
1개의 node는 taint때문에 2개의 노드는 anti-affinity 때문에 안되며 tolerate가 없다고 출력한다.
myweb-a.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myweb-a
spec:
replicas: 3
selector:
matchLabels:
app: a
template:
metadata:
labels:
app: a
spec:
tolerations: node-role.kubernetes.io/master:NoSchedule
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 10
preference:
matchExpressions:
- key: gpu
operator: Exists
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: a
topologyKey: "kubernetes.io/hostname"
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb
vagrant@k8s-node1 ~/schedule/taint kubectl create -f myweb-a.yaml
replicaset.apps/myweb-a created
vagrant@k8s-node1 ~/schedule/taint kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myweb-a-bt8cv 1/1 Running 0 2s 10.233.92.166 node3 <none> <none>
myweb-a-jnk8w 1/1 Running 0 2s 10.233.96.146 node2 <none> <none>
myweb-a-wt829 1/1 Running 0 2s 10.233.90.105 node1 <none> <none>
nfs-client-provisioner-758f8cd4d6-wpjbt 1/1 Running 0 3d 10.233.92.110 node3 <none> <none>
node1에도 정상적으로 배치된다.
🚀 Toleration
vagrant@k8s-node1 ~/schedule/taint kubectl describe node node1
Non-terminated Pods: (12 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age
--------- ---- ------------ ---------- --------------- ------------- ---
default myweb-a-wt829 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3m26s
ingress-nginx ingress-nginx-controller-cmzt4 0 (0%) 0 (0%) 0 (0%) 0 (0%) 5d12h
kube-system calico-node-r257f 150m (8%) 300m (16%) 64M (1%) 500M (14%) 10d
kube-system coredns-8474476ff8-q7svm 100m (5%) 0 (0%) 70Mi (2%) 170Mi (5%) 10d
kube-system dns-autoscaler-5ffdc7f89d-r45qt 20m (1%) 0 (0%) 10Mi (0%) 0 (0%) 10d
kube-system kube-apiserver-node1 250m (13%) 0 (0%) 0 (0%) 0 (0%) 10d
kube-system kube-controller-manager-node1 200m (11%) 0 (0%) 0 (0%) 0 (0%) 10d
kube-system kube-proxy-m2xmr 0 (0%) 0 (0%) 0 (0%) 0 (0%) 5d12h
kube-system kube-scheduler-node1 100m (5%) 0 (0%) 0 (0%) 0 (0%) 10d
kube-system metrics-server-c57c76cf4-x9nwj 100m (5%) 100m (5%) 200Mi (6%) 200Mi (6%) 5d12h
kube-system nodelocaldns-qc6vf 100m (5%) 0 (0%) 70Mi (2%) 170Mi (5%) 10d
metallb-system speaker-zstnm 0 (0%) 0 (0%) 0 (0%) 0 (0%) 5d22h
컨트롤 플레인 역할을 하는 node1 파드들을 살펴보자
vagrant@k8s-node1 ~/schedule/taint kubectl describe po -n ingress-nginx ingress-nginx-controller-cmzt4
Tolerations: node.kubernetes.io/disk-pressure:NoSchedule op=Exists
node.kubernetes.io/memory-pressure:NoSchedule op=Exists
node.kubernetes.io/not-ready:NoExecute op=Exists
node.kubernetes.io/pid-pressure:NoSchedule op=Exists
node.kubernetes.io/unreachable:NoExecute op=Exists
node.kubernetes.io/unschedulable:NoSchedule op=Exists
vagrant@k8s-node1 ~/schedule/taint kubectl describe po -n kube-system kube-apiserver-node1
Tolerations: :NoExecute op=Exists
Tolerations설정이 되어있다.
- PreferNoSchedule
- NoSchedule
- NoExecute
- NoSchedule
다음과 같은 포함 관계를 갖는다 NoExecute는 NoSchedule을 포함하고 NoSchedule은 PreferNoSchedule을 포함한다.
PreferNoSchedule가 가장 낮은 효과를 가지며 NoExecute가 가장 높은 효과를 가진다.
Tolerations: :NoExecute op=Exists
따라서 해당 내용의 의미는 아무 키나 상관없이 NoExecute는 실행할 수 있다는 것이다.
쉽게 말하면 Taint가 걸려있어도 아무 상관이 없다는 뜻이다.
kube-apiserver는 static pod이기 때문에 반드시 node1에 배치되어야 한다.
node1에만 배치하려고 보니 컨트롤 플레인에는 Taint 설정이 되어있을 수 있는데 그 설정을 무력화 시킨다.
그래서 kube-apiserver가 배치될 수 있다.
vagrant@k8s-node1 ~/schedule/taint kubectl describe po -n metallb-system speaker-zstnm
Tolerations: node-role.kubernetes.io/control-plane:NoSchedule op=Exists
node-role.kubernetes.io/master:NoSchedule op=Exists
node.kubernetes.io/disk-pressure:NoSchedule op=Exists
node.kubernetes.io/memory-pressure:NoSchedule op=Exists
node.kubernetes.io/network-unavailable:NoSchedule op=Exists
node.kubernetes.io/not-ready:NoExecute op=Exists
node.kubernetes.io/pid-pressure:NoSchedule op=Exists
node.kubernetes.io/unreachable:NoExecute op=Exists
node.kubernetes.io/unschedulable:NoSchedule op=Exists
metallb-system에도 Tolerations가 설정되어 있다.
node-role.kubernetes.io/master:NoSchedule op=Exists에 의해 컨트폴 플레인 전용 노드에도 배치될 수 있는 것이다.
정리해보자면
특정 노드에 Taint를 건다고 하는 것은 특정 역할을 부여하는 것과 같다.
파드를 생성할 때 tolerations를 설정해서 해당되는 역할이 있는 노드에 배치되도록 스케줄링을 조정할 수 있다.
만약 tolerations가 없는 파드들은 Taint가 걸려있지 않은 나머지 파드들에만 배치될 수 있다.
그렇기 때문에 Taint의 목적은 노드에 역할을 부여하는 것이다.
vagrant@k8s-node1 ~/schedule/taint kubectl describe po -n kube-system coredns-8474476ff8-q7svm
Node-Selectors: kubernetes.io/os=linux
Tolerations: node-role.kubernetes.io/control-plane:NoSchedule
node-role.kubernetes.io/master:NoSchedule
node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
kubeadm으로 설치할 때 network 플러그인으로 Calico를 사용했는데 Calico 설치 전에는 Not Ready라고 되어있었다.
Not Ready가 되어있으면 쿠버네티스가 노드에 자동으로 Taint를 설정한다.
즉, Ready가 되지 않은 노드는 Taint가 설정되어 있다.
그러면 파드를 생성한다해도 tolerations를 설정하지 않으면 배치되지 않는다.
실제로 쿠버네티스가 설치된 이후에 Calico가 설치된다.
쿠버네티스가 설치된 직후에는 노드의 상태가 Not Ready 상태이다.
그때 Calico를 배치해야 Ready 상태가 되는데 Taint가 걸려있으면 Calico 파드를 배치할 수 없다.
그래서 Calico의 경우 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s로 not-ready를 허용시켜준다. 그래야 배치될 수 있고 그래야 Ready가 될 수 있기 때문이다.
Calico는 DaemonSet이다.
1개의 노드에서 스케일링을 거쳐 1개의 노드를 추가한다면 DS에 의해서 Calico를 배치하려고 할 것이다.
그런데 Calico를 배치시키기 전에는 Not Ready이다.
Calico를 배치해야 Ready가 되는데 Taint가 걸려있어 파드를 배치할 수 없는 상태이다.
따라서 Calico에 Tolerations가 세팅되어 있는 이유는 컨트롤 플레인에 Taint가 걸려 있어도 파드를 강제로 배치시키기 위함이다.
'DevOps > Kubernetes' 카테고리의 다른 글
| [Kubernetes] Authenticate (인증) (0) | 2022.06.07 |
|---|---|
| [Kubernetes] Kubeconfig 파일 (0) | 2022.06.06 |
| [Kubernetes] Cordon & Drain (0) | 2022.06.06 |
| [Kubernetes] Affinity (affinity, anti-affinity) (0) | 2022.06.05 |
| [Kubernetes] Pod Scheduling ( + kube-scheduler, nodeName, nodeSelector) (0) | 2022.06.05 |
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!