kubernetes 노드 제거(master/worker)

김건호·2022년 10월 20일
3

목적

애플리케이션이 파드로 실행인 클러스터에서 master node / woker node를 제거 하기 위함

환경

해당 문서에서 사용된 컨테이너 런타임은 cri-o입니다.

패키지버전
cri-o1.17.4
kubernetesv1.17.6

작업

Step 1. 제거할 node를 스케줄 불가로 표시

  1. node 목록을 조회하여 제거할 node를 확인합니다.
$ kubectl get nodes
  1. cordon을 실행하여 node를 스케줄 불가로 표시합니다.
$ kubectl cordon [Node]

노드를 스케줄 불가로 표시하면 스케줄러가 해당 노드에 새 파드를 배치할 수 없지만, 노드에 있는 기존 파드에는 영향을 미치지 않습니다.

  1. node 목록을 조회하여 제거할 node가 SchedulingDisabled 상태인지 확인합니다.
$ kubectl get nodes
NAME      STATUS                     ROLES    AGE    VERSION
node1    Ready                       master   159m   v1.17.6
node2    Ready,SchedulingDisabled    master   159m   v1.17.6
node3    Ready                       master   125m   v1.17.6
node4    Ready,SchedulingDisabled    <none>   96m    v1.17.6
node5    Ready                       <none>   125m   v1.17.6

Step 2. drain 하여 pod를 유지할 node로 이동

  1. Node에 PDB가 있는지 확인합니다.
kubectl get pdb -A
  1. PDB가 있다면, PDB 데이터를 백업 후, 다른 Node로 스케줄링 합니다.
kubectl get pdb [pdb-name] -o yaml > pdb-backup.yaml
kubectl delete pod [pdb=pod=name]
  1. drain을 실행하여 제거할 node의 파드들을 다른 노드로 gratefully terminating 하여 이동시킵니다. (kubernets에서 pod 실행을 유지하며 다른 노드 옮기는 명령은 존재하지 않습니다.)
$ kubectl drain node-name --ignore-daemonsets 🌞
node/node-name already cordoned ⭐
evicting pod "pod-name"
...
node/node-name evicted
  • ⭐drain은 pod 종료 전, drain을 실행한 node에 cordon을 실행합니다.
  • 🌞daemonset으로 떠있는 pod는 각 node에만 배치 되기 때문에 drain이 될 수 없습니다. --ignore-daemonsets 옵션을 추가합니다.
  • pod가 controller(replica set, job, daemon set or stateful set)에 의해 생성되지 않고 pod만 생성되어 있는 경우 drain이 불가능 할 수 있습니다. force 옵션으로 강제로 진행시킬 수 있습니다. (pod 중요성 확인)
  1. drain이 완료되면 pod들이 모두 다른 node로 이동되었는지 (daemonset pod 제외) 확인합니다.
$ kubectl get pods -A -o wide

Step3. kubectl delete node로 클러스터에서 node 제거

제거할 node가 master인 경우

multi master에선 etcd에 정보가 동기화 되어 있기 때문에 node제거 후, etcd member에서 제거해야 합니다. 제거된 node의 etcd가 메인이 되면 apiserver가 존재하지 않아 통신이 불가능하고 데이터 일관성이 깨질 수 있게 됩니다. 자세한 내용은 RAFT 알고리즘을 참조해주세요.
0. 제거할 노드들의 keepalived service를 중지합니다.

$ systemctl stop keepalived
  1. 제거할 노드를 확인합니다.
$ kubectl get nodes
  1. 노드를 클러스터에서 제거합니다.
$ kubectl delete node [node-name you want to remove from cluster]
  1. 노드가 제거 되었는지 확인합니다.
$ kubectl get nodes
  1. keepalived를 가지고 있는 main master 노드에 접속합니다.

  2. main master의 etcd pod를 조회합니다.

$ kubectl get pods -n kube-system | grep etcd
  1. etcd pod에 접속합니다.
$ kubctl exec -it -n kube-system etcd-pod -- bash # bash 안되면 sh

❗7번부터 9번까지 명령어는 접속한 pod에서 진행됩니다.❗

  1. etcd member을 조회합니다.
$ etcdctl -w table member list --cacert /etc/kubernetes/pki/etcd/ca.crt \ 
--cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key
  1. etcd member list에서 제거한 master node의 etcd ID를 선택하여 제거합니다.
$ etcdctl member remove [etcd ID] --cacert /etc/kubernetes/pki/etcd/ca.crt \ 
--cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key
  1. 다시 etcd member를 조회하여 삭제가 되었는지 확인합니다.
$ etcdctl -w table member list --cacert /etc/kubernetes/pki/etcd/ca.crt \ 
--cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key

9-1. exit로 pod에서 나옵니다.

  1. 노드에 저장된 클러스터 정보를 초기화 하기 위해 클러스터에 제거한 노드로 접속합니다.
    ❗지금부터 실행되는 명령어는 접속한 노드에서 진행 되는 내용입니다.❗

  2. 클러스터 정보를 초기화 합니다.

$ kubeadm reset --cri-socket=/var/run/crio/crio.sock⭐
...
The reset process does not clean CNI configuration. To do so, you must remove /etc/cni/net.d

The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually by using the "iptables" command.

If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.

The reset process does not clean your kubeconfig files and you must remove them manually.
Please, check the contents of the $HOME/.kube/config file.
  • ⭐ dockershim과 cri-o가 동시에 있으면 에러가 발생할 수 있습니다.
    --cri-socket=/var/run/crio/crio.sock 옵션으로 컨테이너 런타임으로 지정하여 정상적으로 초기화 되도록 합니다.
  • kubeadm reset 만 입력해도 진행되는 경우가 있지만, 완전히 리셋이 되지 않을 수 있습니다.
    컨테이너 런타임이 cri-o라면 --cri-socket=/var/run/crio/crio.sock 를 사용해줍니다.
  1. CNI 구성파일과 kubernetes, kubelet 구성 디렉토리를 삭제합니다.
$ rm -rf /var/lib/kubelet
$ rm -rf /etc/kubernetes
$ rm -rf /etc/cni/net.d
  1. kubeadm, kubelet, kubectl 패키지를 삭제합니다.
$ yum(dnf) autoremove kubeadm kubelet kubectl

autoremove 란? 삭제하는 패키지와 의존성이 있는 패키지도 같이 삭제합니다. 추후 재설치 시, 버전이 변경되는 경우 의존성 패키지가 남아 있으면 충돌이 발생할 수 있기 때문에 autoremove를 통해 의존성 패키지도 모두 삭제합니다.

  1. 이제 이 node는 kubernets cluster node에서 은퇴입니다❗

제거할 node가 worker인 경우

  1. 제거할 노드를 확인합니다.
$ kubectl get nodes
  1. 노드를 클러스터에서 제거합니다.
$ kubectl delete node [node-name you want to remove from cluster]
  1. 노드가 제거 되었는지 확인합니다.
$ kubectl get nodes
  1. 노드에 저장된 클러스터 정보를 초기화 하기 위해 클러스터에 제거한 노드로 접속합니다.
    ❗지금부터 실행되는 명령어는 접속한 노드에서 진행 되는 내용입니다.❗

  2. 클러스터 정보를 초기화 합니다.

$ kubeadm reset --cri-socket=/var/run/crio/crio.sock⭐
...
The reset process does not clean CNI configuration. To do so, you must remove /etc/cni/net.d

The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually by using the "iptables" command.

If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.

The reset process does not clean your kubeconfig files and you must remove them manually.
Please, check the contents of the $HOME/.kube/config file.
  • ⭐ dockershim과 cri-o가 동시에 있으면 에러가 발생할 수 있습니다.
    --cri-socket=/var/run/crio/crio.sock 옵션으로 컨테이너 런타임으로 지정하여 정상적으로 초기화 되도록 합니다.
  • kubeadm reset 만 입력해도 진행되는 경우가 있지만, 완전히 리셋이 되지 않을 수 있습니다.
    컨테이너 런타임이 cri-o라면 --cri-socket=/var/run/crio/crio.sock 를 사용해줍니다.
  1. CNI 구성파일과 kubernetes, kubelet 구성 디렉토리를 삭제합니다.
$ rm -rf /var/lib/kubelet
$ rm -rf /etc/kubernetes
$ rm -rf /etc/cni/net.d
  1. kubeadm, kubelet, kubectl 패키지를 삭제합니다.
$ yum(dnf) autoremove kubeadm kubelet kubectl

autoremove 란? 삭제하는 패키지와 의존성이 있는 패키지도 같이 삭제합니다. 추후 재설치 시, 버전이 변경되는 경우 의존성 패키지가 남아 있으면 충돌이 발생할 수 있기 때문에 autoremove를 통해 의존성 패키지도 모두 삭제합니다.

  1. 이제 이 node는 kubernets cluster node에서 은퇴입니다❗
profile
Ken, 🔽🔽 거노밥 유튜브(house icon) 🔽🔽

0개의 댓글