본문 바로가기
Kubernetes

K8s from scratch - 4. 노드 유지관리 및 보수

by Hyeon Cloud 2023. 10. 25.

노드 자원 보호하기

최근에 문제가 생긴 노드에 파드를 할당하면 문제가 생길 가능성이 높습니다. 하지만 모든 개발/프로덕션 환경이 그렇듯 사용할 수 있는 자원을 활용하지 않는것또한 자원의 낭비입니다. 때문에 해당 노드를 어쩔수 없이 사용해야하는 경우가 생기는데 어떻게 조치해야할까요? 어떻게 문제가 생길 가능성이 있는 노드임을 쿠버네티스에 알려줄까요? 쿠버네티스에서는 이런경우에 문제가 cordon기능을 사용합니다.

현재 배포된 파드가 없기때문에 파드를 생성해보도록 하겠습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-hname
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: echo-hname
        image: sysnet4admin/echo-hname
ubuntu@master001:~$ k apply -f echo-hname.yaml
deployment.apps/echo-hname created
ubuntu@master001:~$ k get po
NAME                          READY   STATUS    RESTARTS      AGE
echo-hname-5746bc5cb9-46vvs   1/1     Running   0             4s
echo-hname-5746bc5cb9-72bbt   1/1     Running   0             4s
echo-hname-5746bc5cb9-jtxf5   1/1     Running   0             4s
nginx-pod                     1/1     Running   1 (50m ago)   5h11m
ubuntu@master001:~$

scale 명령으로 파드를 9개로 늘려보겠습니다.

ubuntu@master001:~$ k scale deploy echo-hname --replicas=9
deployment.apps/echo-hname scaled
ubuntu@master001:~$ k get po
NAME                          READY   STATUS              RESTARTS      AGE
echo-hname-5746bc5cb9-46vvs   1/1     Running             0             48s
echo-hname-5746bc5cb9-72bbt   1/1     Running             0             48s
echo-hname-5746bc5cb9-7g7rb   0/1     ContainerCreating   0             3s
echo-hname-5746bc5cb9-85lm4   1/1     Running             0             3s
echo-hname-5746bc5cb9-85vln   1/1     Running             0             3s
echo-hname-5746bc5cb9-9wdlj   0/1     ContainerCreating   0             3s
echo-hname-5746bc5cb9-dqcm5   1/1     Running             0             3s
echo-hname-5746bc5cb9-jtxf5   1/1     Running             0             48s
echo-hname-5746bc5cb9-qj4z8   0/1     ContainerCreating   0             3s
nginx-pod                     1/1     Running             1 (51m ago)   5h11m
ubuntu@master001:~$ k get po
NAME                          READY   STATUS    RESTARTS      AGE
echo-hname-5746bc5cb9-46vvs   1/1     Running   0             56s
echo-hname-5746bc5cb9-72bbt   1/1     Running   0             56s
echo-hname-5746bc5cb9-7g7rb   1/1     Running   0             11s
echo-hname-5746bc5cb9-85lm4   1/1     Running   0             11s
echo-hname-5746bc5cb9-85vln   1/1     Running   0             11s
echo-hname-5746bc5cb9-9wdlj   1/1     Running   0             11s
echo-hname-5746bc5cb9-dqcm5   1/1     Running   0             11s
echo-hname-5746bc5cb9-jtxf5   1/1     Running   0             56s
echo-hname-5746bc5cb9-qj4z8   1/1     Running   0             11s
nginx-pod                     1/1     Running   1 (51m ago)   5h12m

배포된 9개의 파드의 세부사항을 columns를 사용하여 출력해보겠습니다.

ubuntu@master001:~$ k get po \\
> -o=custom-columns=NAME:.metadata.name,IP:.status.podIP,STATUS:status.phase,NODE:.spec.nodeName
NAME                          IP          STATUS    NODE
echo-hname-5746bc5cb9-46vvs   10.36.0.2   Running   slave002
echo-hname-5746bc5cb9-72bbt   10.36.0.1   Running   slave002
echo-hname-5746bc5cb9-7g7rb   10.36.0.4   Running   slave002
echo-hname-5746bc5cb9-85lm4   10.44.0.3   Running   slave001
echo-hname-5746bc5cb9-85vln   10.36.0.3   Running   slave002
echo-hname-5746bc5cb9-9wdlj   10.44.0.4   Running   slave001
echo-hname-5746bc5cb9-dqcm5   10.36.0.5   Running   slave002
echo-hname-5746bc5cb9-jtxf5   10.44.0.2   Running   slave001
echo-hname-5746bc5cb9-qj4z8   10.44.0.5   Running   slave001
nginx-pod                     10.44.0.1   Running   slave001
ubuntu@master001:~$

scale로 파드의 수를 2개로 줄입니다. 각 노드에 파드가 1개씩 남았는지 확인합니다.

ubuntu@master001:~$ k delete pod nginx-pod
pod "nginx-pod" deleted
ubuntu@master001:~$ k scale deploy echo-hname --replicas=2
deployment.apps/echo-hname scaled
ubuntu@master001:~$ k get po -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP          NODE       NOMINATED NODE   READINESS GATES
echo-hname-5746bc5cb9-4rshr   1/1     Running   0          11s   10.36.0.2   slave002   <none>           <none>
echo-hname-5746bc5cb9-zrdfc   1/1     Running   0          11s   10.44.0.1   slave001   <none>           <none>
ubuntu@master001:~$

워커노드2에 문제가 발생해 현재 상태를 보존해야 한다고 가정하겠습니다. cordon을 적용합니다.

ubuntu@master001:~$ k cordon slave002
node/slave002 cordoned
ubuntu@master001:~$ k get nodes
NAME        STATUS                     ROLES           AGE   VERSION
master001   Ready                      control-plane   13d   v1.27.4
slave001    Ready                      <none>          13d   v1.27.4
slave002    Ready,SchedulingDisabled   <none>          13d   v1.27.4
ubuntu@master001:~$

node2는 이제 파드가 할당되지 않는 상태를 가집니다. 이 상태에서 파드 수를 늘려보겠습니다.

ubuntu@master001:~$ k scale deployment echo-hname --replicas=9
deployment.apps/echo-hname scaled
ubuntu@master001:~$ k get pods -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP          NODE       NOMINATED NODE   READINESS GATES
echo-hname-5746bc5cb9-4fbvt   1/1     Running   0          12s     10.44.0.5   slave001   <none>           <none>
echo-hname-5746bc5cb9-4r4zx   1/1     Running   0          12s     10.44.0.6   slave001   <none>           <none>
echo-hname-5746bc5cb9-4rshr   1/1     Running   0          2m34s   10.36.0.2   slave002   <none>           <none>
echo-hname-5746bc5cb9-9g54x   1/1     Running   0          12s     10.44.0.2   slave001   <none>           <none>
echo-hname-5746bc5cb9-9zwt2   1/1     Running   0          12s     10.44.0.3   slave001   <none>           <none>
echo-hname-5746bc5cb9-bdmgk   1/1     Running   0          12s     10.44.0.7   slave001   <none>           <none>
echo-hname-5746bc5cb9-dkr4f   1/1     Running   0          12s     10.44.0.8   slave001   <none>           <none>
echo-hname-5746bc5cb9-stm7p   1/1     Running   0          12s     10.44.0.4   slave001   <none>           <none>
echo-hname-5746bc5cb9-zrdfc   1/1     Running   0          2m34s   10.44.0.1   slave001   <none>           <none>
ubuntu@master001:~$

노드2에 파드가 더이상 할당되지 않는것을 확인 할 수 있습니다.

uncordon을 적용합니다.

ubuntu@master001:~$ k uncordon slave002
node/slave002 uncordoned

노드 유지보수하기

쿠버네티스 사용시에 정기 또는 비정기적인 유지보수를 위해 노드를 꺼야하는 상황이 발생하기도 합니다. 이때 쿠버네티스는 drain기능을 제공합니다. drain은 지정된 파드를 전부 다른 곳으로 이동시켜 해당 노드를 유지보수 할 수 있도록 합니다.

drain명령을 사용하여 유지보수할 노드를 파드가 없는 상태로 만들어보도록 하겠습니다.

ubuntu@master001:~$ k drain slave002
node/slave002 cordoned
error: unable to drain node "slave002" due to error:cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): kube-system/kube-proxy-dhgrf, kube-system/weave-net-zqllr, continuing command...
There are pending nodes to be drained:
 slave002
cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): kube-system/kube-proxy-dhgrf, kube-system/weave-net-zqllr
ubuntu@master001:~$

데몬셋을 지울수 없기때문에 명령을 수행 할 수 없다고합니다.

drain은 실제 파드를 옮기는것이 아니라 파드를 삭제하고 다른곳에 생성합니다. 데몬셋은 각 노드에 1개씩만 존재하는 파드이기때문에 drain으로는 삭제할 수 없습니다.

이번에는 ignore-daemonsets옵션을 함께 사용하여 데몬셋을 무시하고 진행해보도록 하겠습니다.

ubuntu@master001:~$ k drain slave002 --ignore-daemonsets
node/slave002 already cordoned
Warning: ignoring DaemonSet-managed Pods: kube-system/kube-proxy-dhgrf, kube-system/weave-net-zqllr
evicting pod default/echo-hname-5746bc5cb9-4rshr
pod/echo-hname-5746bc5cb9-4rshr evicted
node/slave002 drained
ubuntu@master001:~$ k get no
NAME        STATUS                     ROLES           AGE   VERSION
master001   Ready                      control-plane   13d   v1.27.4
slave001    Ready                      <none>          13d   v1.27.4
slave002    Ready,SchedulingDisabled   <none>          13d   v1.27.4
ubuntu@master001:~$ k get pods -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP          NODE       NOMINATED NODE   READINESS GATES
echo-hname-5746bc5cb9-4fbvt   1/1     Running   0          12m   10.44.0.5   slave001   <none>           <none>
echo-hname-5746bc5cb9-4r4zx   1/1     Running   0          12m   10.44.0.6   slave001   <none>           <none>
echo-hname-5746bc5cb9-9g54x   1/1     Running   0          12m   10.44.0.2   slave001   <none>           <none>
echo-hname-5746bc5cb9-9zwt2   1/1     Running   0          12m   10.44.0.3   slave001   <none>           <none>
echo-hname-5746bc5cb9-bdmgk   1/1     Running   0          12m   10.44.0.7   slave001   <none>           <none>
echo-hname-5746bc5cb9-dkr4f   1/1     Running   0          12m   10.44.0.8   slave001   <none>           <none>
echo-hname-5746bc5cb9-j22sd   1/1     Running   0          24s   10.44.0.9   slave001   <none>           <none>
echo-hname-5746bc5cb9-stm7p   1/1     Running   0          12m   10.44.0.4   slave001   <none>           <none>
echo-hname-5746bc5cb9-zrdfc   1/1     Running   0          14m   10.44.0.1   slave001   <none>           <none>
ubuntu@master001:~$

모든 파드가 워커노드 1에서 실행됨을 확인할 수 있습니다.

파드를 업데이트하고 복구하기

파드운영시에 새로운 기능을 추가하거나 버그를 픽스해야할 때가 있습니다. 업데이트중 문제가 발생하여 기존버전으로 롤백해야하는 상황도 발생합니다. 이때 쿠버네티스에서 어떻게 처리해야하는지에 알아보도록 하겠습니다.

파드업데이트

간단한 파드를 배포하도록 하겠습니다. —record 옵션을 사용하여 배포 정보의 히스토리를 기록합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rollout-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.12

 

ubuntu@master001:~$ k apply -f rollout-nginx.yaml --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/rollout-nginx created
ubuntu@master001:~$

record옵션으로 기록된 히스토리는 rollout history 명령으로 확인해볼수 있습니다.

ubuntu@master001:~$ k rollout history deployment rollout-nginx
deployment.apps/rollout-nginx
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=rollout-nginx.yaml --record=true

ubuntu@master001:~$

배포한 파드의 정보를 확인하고 ip를 기억해둡니다. nginx 버전을 확인해보겠습니다.

ubuntu@master001:~$ k get pods -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP          NODE       NOMINATED NODE   READINESS GATES
rollout-nginx-6b6c46d58f-55pml   1/1     Running   0          44h   10.36.0.1   slave002   <none>           <none>
rollout-nginx-6b6c46d58f-cz5l7   1/1     Running   0          44h   10.44.0.1   slave001   <none>           <none>
rollout-nginx-6b6c46d58f-dgsk5   1/1     Running   0          44h   10.36.0.2   slave002   <none>           <none>
ubuntu@master001:~$ curl -I --silent 10.36.0.1 | grep Server
Server: nginx/1.15.12
ubuntu@master001:~$

컨테이너의 nginx 버전을 업데이트 하도록 하겠습니다. —record 옵션으로 명령을 기록합니다.

ubuntu@master001:~$ k set image deployment rollout-nginx nginx=nginx:1.16.0 --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/rollout-nginx image updated
ubuntu@master001:~$ k get pods
NAME                             READY   STATUS              RESTARTS   AGE
rollout-nginx-6b6c46d58f-55pml   1/1     Running             0          45h
rollout-nginx-6b6c46d58f-cz5l7   1/1     Running             0          45h
rollout-nginx-6b6c46d58f-dgsk5   1/1     Running             0          45h
rollout-nginx-9bcd84889-w6hpj    0/1     ContainerCreating   0          4s
ubuntu@master001:~$ k get pods
NAME                             READY   STATUS              RESTARTS   AGE
rollout-nginx-6b6c46d58f-cz5l7   1/1     Running             0          45h
rollout-nginx-6b6c46d58f-dgsk5   1/1     Running             0          45h
rollout-nginx-9bcd84889-sqm85    0/1     ContainerCreating   0          5s
rollout-nginx-9bcd84889-w6hpj    1/1     Running             0          13s
ubuntu@master001:~$ k get pods
NAME                             READY   STATUS        RESTARTS   AGE
rollout-nginx-6b6c46d58f-dgsk5   0/1     Terminating   0          45h
rollout-nginx-9bcd84889-cbsx5    1/1     Running       0          1s
rollout-nginx-9bcd84889-sqm85    1/1     Running       0          9s
rollout-nginx-9bcd84889-w6hpj    1/1     Running       0          17s
ubuntu@master001:~$ k get pods
NAME                            READY   STATUS    RESTARTS   AGE
rollout-nginx-9bcd84889-cbsx5   1/1     Running   0          6s
rollout-nginx-9bcd84889-sqm85   1/1     Running   0          14s
rollout-nginx-9bcd84889-w6hpj   1/1     Running   0          22s
ubuntu@master001:~$ k get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP          NODE       NOMINATED NODE   READINESS GATES
rollout-nginx-9bcd84889-cbsx5   1/1     Running   0          49s   10.44.0.3   slave001   <none>           <none>
rollout-nginx-9bcd84889-sqm85   1/1     Running   0          57s   10.44.0.2   slave001   <none>           <none>
rollout-nginx-9bcd84889-w6hpj   1/1     Running   0          65s   10.36.0.3   slave002   <none>           <none>

파드의 이름과 ip가 변경되었습니다. 컨테이너 업데이트 시에 replicas의 수를 줄이고 늘려서 파드를 새로생성합니다. replicas의 모든 파드를 한번에 지우는 것이 아닌 하나씩을 순차적으로 지우고 생성하게 됩니다. 업데이트 기본값은 전체의 1/4 이며 최솟값은 1개입니다.

업데이트 실패 시 파드 복구하기

set image 명령으로 nginx 컨테이너 버전을 잘못 입력해보도록 하겠습니다.

ubuntu@master001:~$ k get pods
NAME                             READY   STATUS         RESTARTS   AGE
rollout-nginx-6f58d68f85-h5bw6   0/1     ErrImagePull   0          6s
rollout-nginx-9bcd84889-cbsx5    1/1     Running        0          19m
rollout-nginx-9bcd84889-sqm85    1/1     Running        0          19m
rollout-nginx-9bcd84889-w6hpj    1/1     Running        0          19m
ubuntu@master001:~$ k get pods
NAME                             READY   STATUS             RESTARTS   AGE
rollout-nginx-6f58d68f85-h5bw6   0/1     ImagePullBackOff   0          18s
rollout-nginx-9bcd84889-cbsx5    1/1     Running            0          19m
rollout-nginx-9bcd84889-sqm85    1/1     Running            0          19m
rollout-nginx-9bcd84889-w6hpj    1/1     Running            0          19m

업데이트가 더이상 진행되지 않고, 파드가 동작하지 않음을 확인 할 수 있습니다.

rollout undo 명령을 통해 마지막 개정에서 전 개정으로 되돌리도록 하겠습니다.

ubuntu@master001:~$ k rollout undo deployment rollout-nginx
deployment.apps/rollout-nginx rolled back
ubuntu@master001:~$ k get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP          NODE       NOMINATED NODE   READINESS GATES
rollout-nginx-9bcd84889-cbsx5   1/1     Running   0          21m   10.44.0.3   slave001   <none>           <none>
rollout-nginx-9bcd84889-sqm85   1/1     Running   0          21m   10.44.0.2   slave001   <none>           <none>
rollout-nginx-9bcd84889-w6hpj   1/1     Running   0          21m   10.36.0.3   slave002   <none>           <none>
ubuntu@master001:~$

히스토리를 확인해보면 개정5가 추가되었고 1.16 버전으로 롤백함을 알 수 있습니다.

ubuntu@master001:~$ k rollout history deployment rollout-nginx
deployment.apps/rollout-nginx
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=rollout-nginx.yaml --record=true
2         kubectl set image deployment rollout-nginx nginx=1.16.0 --record=true
4         kubectl set image deployment rollout-nginx nginx=nginx:2.0.0 --record=true
5         kubectl set image deployment rollout-nginx nginx=nginx:1.16.0 --record=true

ubuntu@master001:~$

특정 시점으로 파드 복구하기

바로 전 시점이아니라 특정 개정 시점으로 복구하고싶다면 —to-revision옵션을 사용합니다.

처음상태인 revision 1로 돌아가보겠습니다.

ubuntu@master001:~$ k rollout undo deployment rollout-nginx --to-revision=1
deployment.apps/rollout-nginx rolled back
ubuntu@master001:~$

nginx 버전을 확인해보도록 하겠습니다.

ubuntu@master001:~$ k get po -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP          NODE       NOMINATED NODE   READINESS GATES
rollout-nginx-6b6c46d58f-pwtts   1/1     Running   0          35s   10.44.0.1   slave001   <none>           <none>
rollout-nginx-6b6c46d58f-zngxx   1/1     Running   0          36s   10.36.0.1   slave002   <none>           <none>
rollout-nginx-6b6c46d58f-zw9dl   1/1     Running   0          34s   10.44.0.3   slave001   <none>           <none>
ubuntu@master001:~$ curl -I --silent 10.44.0.1 | grep Server
Server: nginx/1.15.12
ubuntu@master001:~$

1.15.12버전이므로 처음 상태로 복구된 것을 확인 할 수 있습니다.