CKA를 준비해보자 18일차 - OS Upgrade

0

CKA

목록 보기
18/43

OS Upgrade

만약 특정 node의 os를 upgrade하는 등의 일을 위해서, 해당 node를 reboot해야하는 상황이 발생한다고 하자.

이때에는 해당 node의 pod들이 다운될 수 밖에 없는데, 만약 5분이 지나도 node가 복구되지 않으면, 이후에 node가 복구되어도 해당 node의 pod들은 복구되지 않는다.

다만, DeploymentReplicaSet을 이용하여 pod를 배포했다면 해당 node에 배포되었던 pod들은 다른 node에 배포될 것이다. 단지 pod 그 자체로 배포했다면 해당 node에 있던 pod는 5분 후에도 복구되지 않는다.

node에 있는 pod들을 다른 node로 보내는 동작은 kubectl drain을 통해 실행할 수 있다.

kubectl drain node-1 --ignore-daemonsets

다음의 명령어를 사용하면 node-1에 있던 pod들이 다른 node로 이동하게 된다.

----node-1----
| pod1, pod2 |
|            |
--------------

----node-2----
|            |
|            |
--------------

위와 같이 node-1pod1, pod2가 있다고 하자. kubectl drain 명령어 호출 시에 다음과 같이 된다.

----node-1----
|            |
|            |
--------------

----node-2----
| pod1, pod2 |
|            |
--------------

pod들이 node-2로 이동하는 것을 볼 수 있다.

사실 kubectl drain은 진짜 pod를 그대로 옮기는 것이 아니라, 이전 node에서 pod를 다운시키고 다른 node에서 재시작시키는 것이다. 또한, 이전 node는 이제 pod를 배포하지 말라고, unschedulable 표시를 받게된다. 이 표시를 받게되면 해당 node에 pod를 배포할 수 없게 된다.

한 가지 조심해야할 것은 kubectl drain을 동작할 때의 내부 pod들은 deploymentreplicasets에 의해 관리받는 pod들이어야 한다는 것이다. 이유는 위에서 말했듯이 node가 다운된 후에 5분간의 evicted후에는 pod들이 재시작되지 않고, 사라지기 때문이다. 때문에 일반 Pod가 있다면 해당 node에 대해서 일반적으로 kubectl drain이 동작되지 않는다.

이후 해당 node에 대한 os upgrade와 같은 reboot작업 이후, node에 pod를 배포할 수 있도록 마크를 해주어야 한다. 즉, unscheduled 표시를 풀어주어 새로운 pod가 배포될 수 있도록 scheduled 상태로 만들어주는 것이다. 이 방법은 kubectl uncordon 을 사용하면 된다.

kubectl uncordon node-1

명심할 것은 이전에 해당 node에 배포되었던 pod들이 다시 해당 node로 돌아오진 않는다.

그런데 만약, 특정 node에 더이상 pod를 추가로 스케줄링하지 못하게 하고만 싶다면 어떻게해야할까? 즉, node에 있던 pod들을 다른 node로 옮기지않고 해당 node에 대해서 unshcedulable 표시만 하고싶다면 말이다.

이 방법은 kubectl cordon을 사용하면 된다.

kubectl cordon node-2

이제 node-2에는 새로운 pod들이 스케줄링되지 않지만, 기존의 pod들이 다른 곳으로 가진 않는다.

Cluster Upgrade Process

kubernetes cluster를 이루는 component들은 동일한 version을 가지고 동작할 필요가 없다.

가령 kube-apiservercontroller-manager는 서로 버전이 달라도 된다. 그러나, 몇가가 version호환성 법칙이있는데, 다음과 같다.

  1. 중심이 되는 version은 kube-apiserver이다. x라고 하자.
  2. controller-manager, kube-schedulerkube-apiserver보다 버전이 하나 낮은 것까지 허용한다. x-1 <= v <= x
  3. kubeletkube-proxykube-apiserver가 버전이 두 개 낮은 것까지 허용한다. x-2 <= v <= x
  4. kubectl의 경우 kube-apiserver보다 버전이 하나 낮거나 높은 것까지 허용한다. x-1 <= v <= x+1

가령 다음과 같다. kube-apiserverv1.10라면 허용되는 version은 다음과 같다.

controller-manager: v1.9, v1.10
kube-scheduler: v1.9, v1.10
kubelet: v1.8, v1.9, v1.10
kube-proxy: v1.8, v1.9, v1.10
kubelet: v1.9, v1.10, v1.11

이러한 version 호환성 rule은 모든 component에 대해서 live upgrade를 가능하도록 해준다.

그럼 어떻게 kubernetes cluster component version들을 업그레이드 할 수 있을까?? 우리가 생각하기에 v1.9에서 바로 v1.13으로 업그레이드 할 수 있을 것이라 생각하지만, 사실 그렇지 않다. kubernetes cluster component는 하나씩 version을 upgrade해주는 것이 좋다.

가령, v1.9에서 v.1.13으로 업그레이드하고 싶다면 v1.10로 업그레이드하고, v1.11, v1.12로 순차적으로 업그레이드한다. 이렇게 minor 버전에 대해서 하나씩 업그레이드가 진행되는 이유는, 위에서 보는 것과 같이 kubernetes clustert component들의 버전 호환성이 하나, 둘 밖에 차이가 나지 않아서 그렇다.

이 version 업그레이드는 cloud platform을 이용하고 있는 지, 아니면 vanila kubernetes cluster로 동작하고 있는 지에 따라 다르다. 만약 vanila kubernetes라면 kubeadm을 통해서 upgrade하는 것이 좋다.

kubeadm upgrade plan
kubeadm upgrade apply

version upgrade는 두 단계로 이루어진다.

  1. master node를 다운키고 version upgrade가 진행된다.
  2. worker node에 대한 version upgrade가 진행된다.

첫번째 단계는 master node에 대한 version upgrade이므르 kubeadm을 통해서 가능하다. 단, 두번째 단계는 worker node에 관련된 단계로 직접들어가서 하나씩 하는 방법 밖에 없다.

master node에 대한 version upgrade가 진행되면 kube-apiserver, controller-mananger, kube-scheduler 등 master node component들이 다운되고 새로운 version으로 설치된다.

이때, worker node에 대한 service impact가 없다는 것에 집중하도록 하자. master node가 다운되면 새로운 pod나 kubernetes resource를 배포하지 못한다는 것이지, 절대 worker node가 다운되고 service가 정상적으로 동작하지 않는다는 것을 말하지 않는다.

master node에서 version upgrade가 마무리되면, worker node에 대한 upgrade가 이루어진다. 이때 두 가지 전략이 있다.

  1. 한번에 모든 worker node upgrade: worker node를 모두 내리고 version upgrade 진행한다.
  2. 한번에 하나씩 worker node upgrade: worker node를 하나씩 version upgrade한다.

첫번째 방법은 user가 service에 접근하지 못한다는 단점이 있는 반면에, 두번째 방법은 service에 접근할 수 있고, version upgrade되는 pod들이 다른 pod들에 다시 deploy되어 정상적으로 service를 제공할 수 있다는 장점이 있다.

다시 말하지만, worker node에 대한 전략은 메뉴얼하게 직접 설치해주는 방법 밖에 없다.

다음의 명령어를 입력하면 현재 cluster version과 kubeadm version, stable version, component version등을 자세히 보여준다.

kubeadm upgrade plan

결과를 잘보면 kubeadm의 버전을 타겟 version에 맞추라는 말이 있다. 즉, v1.12로 cluster를 업그레이드시키고 싶다면 먼저 kubeadm 버전을 v1.12로 업그레이드해야한다는 것이다.

apt-get upgrade -y kubeadm=1.12.0-00

다음으로 kubeadm upgrade apply를 통해서 업데이트를 진행시켜주면 된다.

kubeadm upgrade apply v1.12.0

이후 master node의 kube-apiserver가 업그레이드되는 것을 볼 수 있을 것이다. 단, kubectl get nodesversion을 확인하면 아직도 이전 버전이 적혀져 있을 것이다. 이는 kubelet의 version이기 때문에 따로 해당 worker node에 들어가, 업그레이드 시켜주는 방법 밖에 없다.

apt-get upgrade -y kubelet=1.12.0-00
systemctl restart kubelet

이 후에 kubectl get nodes로 확인해보면 바뀐 것을 볼 수 있을 것이다.

문제는 kubeletrestart시켜버리면, 해당 worker node에서 동작하고 있던 pod들이 동작하지 않게된다는 문제가 발생한다. 이를 해결하기 위해서, 위에서 배웠던 kubectl drain을 사용하면 된다.

kubectl drain을 사용하여 해당 worker node에 pod가 스케줄링되지 못하게 막고, 기존의 pod들은 다른 곳으로 옮기도도록 하는 것이다.

kubectl drain node-1 --ignore-daemonsets

이후에 해당 worker node에 들어가 kubelet을 버전을 업그레이드 시켜주는 것이다. 참고로 worker node에서는 kubeadm까지 작업하지 않아도 된다.

apt-get upgrade -y kubelet=1.12.0-00
systemctl restart kubelet

kubeadm을 통해서 kubelet버전을 지정하고 kubelet을 재시작해주기만 하면 된다.

이후 drain된 node에 대한 unscheduled 표시를 지우기위해 kubectl uncordon을 사용하도록 하자.

이렇게 각 node에 대해서 같은 step을 진행하면 된다.

0개의 댓글