🚀 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 |
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!