Kubernetes

Pod Scheduling에 대해서 알아보자 -2 (taint&toleration, cordon&drain)

chaenii 2022. 3. 3. 17:32

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

https://www.google.com/url?sa=i&url=https%3A%2F%2Fleoh0.github.io%2Fpost%2F2018-08-07-kubernetes-dedicated-node-pattern%2F&psig=AOvVaw0bucxJQA1JXMyEkH_vSKwb&ust=1646377148973000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCPjWmPuuqfYCFQAAAAAdAAAAABAd 

 

리디렉션 알림

 

www.google.com

 

반응형