Taints & Tolerations
쿠버네티스는 클러스터의 특정 노드에 테인트를 설정할 수 있다.
테인트를 설정한 노드에는 파드들을 스케줄링하지 않는다. 테인드를 설정한 노드에 파드들을 스케줄링하려면 톨러레이션을 설정해야한다. 그럼 테인트는 톨러레아션에서 설정한 특정 파드들만 실행하고 다른 파드는 실행하지 못하게 한다.
즉, toleration이 있는 Pod는 동일한 taint가 있는 노드를 포함에 모든 노드에 배치되며, worker node는 taint가 설정된 경우 동일 값의 toleration이 있는 pod만 배치한다.
$ kubectl get nodes -A
NAME STATUS ROLES AGE VERSION
kube-master Ready control-plane,master 24d v1.22.0
kube-worker Ready <none> 24d v1.23.3
kube-worker2 Ready <none> 4h16m v1.23.4
$ kubectl describe nodes kube-master | grep -i taint
Taints: node-role.kubernetes.io/master:NoSchedule
노드에 taint 지정하기
kube-worker에 NoSchedule taint를 지정했다.
결과적으로는 kube-worker2를 제외하고 나머지 노드에 NoSchedule이 설정됐다.
$ kubectl taint nodes kube-worker role=web:NoSchedule
node/kube-worker tainted
$ kubectl describe nodes -A | grep -i taint
Taints: node-role.kubernetes.io/master:NoSchedule
Taints: role=web:NoSchedule
Taints: <none>
pod 배포하기
toleration이 지정되지 않은 pod를 먼저 배포해보자.
apiVersion: apps/v1
kind: Deployment
metadata:
name: webui
labels:
app: webui
spec:
replicas: 4
selector:
matchLabels:
app: webui
template:
metadata:
name: webui
labels:
app: webui
spec:
containers:
- name: nginx-container
image: nginx:1.14
NoSchedule taint가 정의되지 않은 유일한 노드인 kube-worker2에 배포된 것을 확인할 수 있다.
$ kubectl get po -L app -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES APP
webui-5467f6f754-27754 1/1 Running 0 103s 10.244.3.11 kube-worker2 <none> <none> webui
webui-5467f6f754-mxtk8 1/1 Running 0 103s 10.244.3.10 kube-worker2 <none> <none> webui
webui-5467f6f754-nz7jd 1/1 Running 0 103s 10.244.3.9 kube-worker2 <none> <none> webui
webui-5467f6f754-ppjx4 1/1 Running 0 103s 10.244.3.8 kube-worker2 <none> <none> webui
pod 배포하기
toleration이 지정된 pod를 배포해보자.
해당 파드들은 NoSchedule taint여부와 무관하게 모든 노드에 스케줄링될 것이다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: webui
labels:
app: webui
spec:
replicas: 4
selector:
matchLabels:
app: webui
template:
metadata:
name: webui
labels:
app: webui
spec:
containers:
- name: nginx-container
image: nginx:1.14
tolerations:
- key: "role"
operator: "Equal"
value: "web"
effect: "NoSchedule"
Taint 삭제하기
$ kubectl taint node kube-worker role-
node/kube-worker untainted
cordon & drain
쿠버네티스 클러스터를 사용하다 보면 특정 노드에 있는 파드들을 모두 다른 노드로 옮기거나 특정 노드에 파드들을 스케줄링하지 않도록 제한할 필요가 있다. kubectl에는 이러한 기능을 제공하는 cordon과 drain이라는 명령어가 있다.
cordon
노드 스케줄링 중단(cordon) 및 허용(uncordon)
- 특정 노드에 Pod 스케줄을 금지하거나 해제
$ kubectl [cordon/uncordon] node [options]
$ kubectl get nodes -A
NAME STATUS ROLES AGE VERSION
kube-master Ready control-plane,master 24d v1.22.0
kube-worker Ready <none> 24d v1.23.3
kube-worker2 Ready <none> 5h23m v1.23.4
STATUS 항목에 파드 스케줄링을 준비 중인 Ready와 함께 이 노드에 더 이상 파드를 스케줄링하지 않는다는 SchedulingDisabled이 추가된 것을 확인할 수 있다.
$ kubectl cordon kube-worker
$ kubectl get nodes -A
NAME STATUS ROLES AGE VERSION
kube-master Ready control-plane,master 24d v1.22.0
kube-worker Ready,SchedulingDisabled <none> 24d v1.23.3
kube-worker2 Ready <none> 5h23m v1.23.4
모든 노드를 cordon한 후, 파드를 스케일링 해보자.
$ kubectl cordon kube-worker2
$ kubectl get nodes -A
kube-master Ready control-plane,master 24d v1.22.0
kube-worker Ready,SchedulingDisabled <none> 24d v1.23.3
kube-worker2 Ready,SchedulingDisabled <none> 5h27m v1.23.4
replicas 개수가 2개인 nginx-deploy의 replicas 개수를 3개로 늘려보았다.
$ kubectl scale deployment nginx-deploy --replicas=3
deployment.apps/nginx-deploy scaled
파드가 정상적으로 실행되지 않고 Pending 상태이다.
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-deploy-79f85fd859-hhmm2 2/2 Running 0 23d
nginx-deploy-79f85fd859-mspjc 0/1 Pending 0 9s
nginx-deploy-79f85fd859-v47km 2/2 Running 0 23d
2개의 노드가 모두 cordon 상태라 스케줄링이 불가능하기 때문이다.
$ kubectl describe po nginx-deploy-79f85fd859-mspjc
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 101s default-scheduler 0/4 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 1 node(s) had taint {node.kubernetes.io/not-ready: }, that the pod didn't tolerate, 2 node(s) were unschedulable.
Warning FailedScheduling 34s default-scheduler 0/4 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 1 node(s) had taint {node.kubernetes.io/not-ready: }, that the pod didn't tolerate, 2 node(s) were unschedulable.
노드 uncordon 하기
$ kubectl uncordon kube-worker
kube-worker를 uncordon하자 해당 파드는 스케줄링되고, 바로 Running 상태가 되었다.
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-deploy-79f85fd859-hhmm2 2/2 Running 0 23d
nginx-deploy-79f85fd859-mspjc 1/1 Running 0 3m23s
nginx-deploy-79f85fd859-v47km 2/2 Running 0 23d
drain
kubectl drain은 노드 관리 등의 이유로 지정된 노드에 있는 파드들을 다른 노드로 이동시키는 명령이다.
현재 backend라는 pod는 kube-worker2에서 실행되고 있다.
kube-worker2를 drain하면 backend 파드가 어떻게 되는지 확인해보자.
$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
backend 1/1 Running 0 121m 10.244.3.2 kube-worker2 <none> <none>
아래와 같은 에러 메시지가 뜨는데 이는 데몬세트, 레플리카세트, 리플리케이션 컨트롤러, 스테이트풀세트로 실행한 파드가 있기때문이다.
--ignore-daemonsets=true, --force 옵션을 설정해 다시 실행하면 정상적으로 드레인 설정이 실행된다.
$ kubectl drain kube-worker2
node/kube-worker2 cordoned
DEPRECATED WARNING: Aborting the drain command in a list of nodes will be deprecated in v1.23.
The new behavior will make the drain command go through all nodes even if one or more nodes failed during the drain.
For now, users can try such experience via: --ignore-errors
error: unable to drain node "kube-worker2", aborting command...
There are pending nodes to be drained:
kube-worker2
cannot delete Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet (use --force to override): default/backend, default/db
cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): kube-system/kube-flannel-ds-cw9g7, kube-system/kube-proxy-22vv7
kube-worker2에 backend 파드는 삭제되고, 노드는 SchedulingDisabled 상태가 된다.
$ kubectl drain kube-worker2 --ignore-daemonsets=true --force
WARNING: deleting Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet: default/backend, default/db; ignoring DaemonSet-managed Pods: kube-system/kube-flannel-ds-cw9g7, kube-system/kube-proxy-22vv7
evicting pod default/db
evicting pod default/backend
pod/backend evicted
node/kube-worker2 evicted
$ kubectl get nodes -A
NAME STATUS ROLES AGE VERSION
kube-master Ready control-plane,master 24d v1.22.0
kube-worker Ready <none> 24d v1.23.3
kube-worker2 Ready,SchedulingDisabled <none> 5h47m v1.23.4
drain 해제하기
$ kubectl uncordon kube-worker2
node/kube-worker2 uncordoned
$ kubectl get nodes -A
NAME STATUS ROLES AGE VERSION
kube-master Ready control-plane,master 24d v1.22.0
kube-worker Ready <none> 24d v1.23.3
kube-worker2 Ready <none> 5h48m v1.23.4
리디렉션 알림
www.google.com
'Kubernetes' 카테고리의 다른 글
K8S Worker Node - Not Ready (0) | 2022.11.21 |
---|---|
Failed to create pod sandbox: open /run/systemd/resolve/resolv.conf: no such file or directory (0) | 2022.05.24 |
Pod Scheduling에 대해서 알아보자 - 1 [NodeSelector, affinity&antiaffinity] (0) | 2022.03.03 |
mount.nfs: access denied by server while mounting (0) | 2022.03.02 |
5-3. Init container (0) | 2022.02.07 |