본 포스팅은 Udemy Certificated Kubernetes Administrator 강좌를 공부한 내용입니다.

 

Certified Kubernetes Administrator (CKA) Practice Exam Tests

Prepare for the Certified Kubernetes Administrators Certification with live practice tests right in your browser - CKA

www.udemy.com

Kubernetes Upgrade

Kubernetes 역시 소프트웨어이기 때문에 버전이 존재하고 하위 버전을 호환하기 위한 backward compatibility를 갖추고 있어야 한다.

Kubernetes는 Master Node에서 동작하는 ControlPlane의 구성요소와

Worker Node에서 동작하는 kubelet, kube-proxy,

사용자가 사용하는 kubectl 등 다양한 프로세스로 구성되어 있다.

 

그리고 다양한 프로세스는 같은 버전을 유지하는 것을 권장한다.

하지만 모든 프로세스의 버전을 맞출 수 없다면, Kubernetes는 프로세스의 모든 버전에 대해 backward compatibility를 갖추고 있어야 할까?

현실적으로 그것은 불가능하기 때문에 Kubernetes는 버전과 프로세스의 하위 버전 지원의 범위를 정해놓고 있다.

Kubernetes의 버전은 api-server의 버전을 기준으로 한다.

 

프로세스 지원 버전 범위 예시
kube-apiserver X v1.10
controller-manager X-1 v1.9 or v1.10
kube-scheduler X-1 v1.9 or v1.10
kubelet X-2 v1.8 or v1.9 or v1.10
kube-proxy X-2 v1.8 or v1.9 or v1.10
kubectl X+1 > X-1 v1.9 or v1.10 or v1.11

 

또한 kubernetes를 업그레이드 할 때에는 minor 버전을 하나씩 올리는 것을 권장한다. (eg,. v1.9 -> v1.10 -> v1.11)

(버전 명 : v{major}.{minor}.{patch})

 

Kubernetes를 설치할 때와 마찬가지로 업그레이드 시에도 Manual하게 하는 방법과 kubeadm을 사용하는 방법이 있다.

이번에도 역시 kubeadm으로 업그레이드를 진행한다.

 

 

Upgrade Strategy

Kubernetes는 여러 노드로 구성되어 있기 때문에 모든 노드를 전부 업그레이드 해주어야 한다.

이 과정에서 노드의 downtime에 따른 3가지 전략이 있다.

 

1. Master 노드를 업그레이드한 후, 모든 Worker 노드를 한 번에 업그레이드 한다.

당연하겠지만 모든 Worker 노드의 kubelet, kube-proxy 등이 한번에 재시작 되기 때문에 클러스터에서 동작하는 Pod의 downtime이 존재한다.

 

2. Master 노드를 업그레이드한 후, 한 Worker 노드씩 업그레이드 한다.

Worker 노드를 하나씩 재시작하며 업그레이드를 진행한다. 업그레이드 하기 전 node drain을 통해 노드에 있는 Pod를 퇴출시킨 뒤 업그레이드 한다.

 

3. 업그레이드가 이미 된 새로운 Worker 노드를 추가하고 기존 노드 하나를 업그레이드 한다.

언뜻 2번과 비슷한 전략 같지만 이렇게 진행하기 위해선 전체 Worker 노드 수 + 1개의 노드가 필요하다. 업그레이드 중에도 노드의 갯수를 동일하게 유지할 수 있기 때문에 클러스터의 리소스 양을 유지할 수 있다.

 

Kubeadm Upgrade

이제 kubeadm을 사용해 노드 업그레이드를 진행해보자.

$ kubectl get node
NAME     STATUS   ROLES    AGE    VERSION
master   Ready    master   112s   v1.16.0
node01   Ready    <none>   82s    v1.16.0

2개의 노드가 있고 각 노드의 버전은 v1.16.0이다.

노드 하나씩 업그레이드 하는 Strategy 2를 사용해서 업그레이드 해보자.

kubeadm을 사용하면 현재 업그레이드 할 수 있는 버전을 알 수 있다.

$ kubeadm upgrade plan
[upgrade/config] Making sure the configuration is correct:
[upgrade/config] Reading configuration from the cluster...
...
...
Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
COMPONENT   CURRENT       AVAILABLE
Kubelet     2 x v1.16.0   v1.17.7

Upgrade to the latest stable version:

COMPONENT            CURRENT   AVAILABLE
API Server           v1.16.0   v1.17.7
Controller Manager   v1.16.0   v1.17.7
Scheduler            v1.16.0   v1.17.7
Kube Proxy           v1.16.0   v1.17.7
CoreDNS              1.6.2     1.6.5
Etcd                 3.3.15    3.4.3-0

You can now apply the upgrade by executing the following command:

        kubeadm upgrade apply v1.17.7

Note: Before you can perform this upgrade, you have to update kubeadm to v1.17.7.

v1.17.7 버전으로 업그레이드 할 수 있다고 나온다.

 

v1.17.7으로 업그레이드 하기 위해서는 kubeadm의 버전이 일치해야한다.

일치하지 않을 경우 kubeadm 버전을 업그레이드 하고

kubeadm upgrade plan v1.17.7을 통해 해당 버전으로 업그레이드가 가능한지 확인한다.

$ apt-get upgrade kubeadm=1.17.7-00

$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.7", GitCommit:"b4455102ef392bf7d594ef96b97a4caa79d729d9", GitTreeState:"clean", BuildDate:"2020-06-17T11:37:34Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}

$ kubeadm upgrade plan v1.17.7
[upgrade/config] Making sure the configuration is correct:
[upgrade/config] Reading configuration from the cluster...
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[preflight] Running pre-flight checks.
[upgrade] Making sure the cluster is healthy:
[upgrade] Fetching available versions to upgrade to
[upgrade/versions] Cluster version: v1.16.0
[upgrade/versions] kubeadm version: v1.17.7

Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
COMPONENT   CURRENT       AVAILABLE
Kubelet     2 x v1.16.0   v1.17.7

Upgrade to the latest version in the v1.16 series:

COMPONENT            CURRENT   AVAILABLE
API Server           v1.16.0   v1.17.7
Controller Manager   v1.16.0   v1.17.7
Scheduler            v1.16.0   v1.17.7
Kube Proxy           v1.16.0   v1.17.7
CoreDNS              1.6.2     1.6.5
Etcd                 3.3.15    3.4.3-0

You can now apply the upgrade by executing the following command:

        kubeadm upgrade apply v1.17.7

_____________________________________________________________________

 

 

업그레이드를 하기 전 노드에서 Pod를 퇴출시키는 명령어에 대해 알아보자.

# <NODE>의 Pod 퇴출 및 unscheduling
$ kubectl drain <NODE>

# <NODE> unscheduling
$ kubectl cordon <NODE>

# <NODE> scheduling
$ kubectl uncordon <NODE>

drain은 현재 Pod를 모두 퇴출시키고 앞으로도 kube-scheduler에 의해 Pod가 해당 노드로 스케쥴링 되지 않는다.

$ kubectl describe node master
Name:               master
...
...
Taints:             node.kubernetes.io/unschedulable:NoSchedule

$ kubectl get node
NAME     STATUS                     ROLES    AGE   VERSION
master   Ready,SchedulingDisabled   master   11m   v1.16.0
node01   Ready                      <none>   10m   v1.16.0

위와 같이 스케쥴링이 되지 않도록 Taint가 설정되고 STATUS에 SchedulingDisabled가 나온다.

cordon은 drain처럼 스케쥴링이 되지 않지만 현재 실행중인 Pod는 퇴출시키지 않는다.

uncordon은 drain/cordon된 node를 다시 스케쥴링 할 수 있도록 변경한다.

 

 

master 노드에 있는 Pod를 퇴출시킨 두 업그레이드 한다.

$ kubectl drain master --ignore-daemonsets
node/master already cordoned
WARNING: ignoring DaemonSet-managed Pods: kube-system/kube-proxy-7qcdn, kube-system/weave-net-k2z8q
node/master drained

$ kubeadm upgrade apply v1.17.7
...
...
[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.17.7". Enjoy!
...

$ kubectl get node
NAME     STATUS                     ROLES    AGE   VERSION
master   Ready,SchedulingDisabled   master   31m   v1.16.0
node01   Ready                      <none>   30m   v1.16.0

$ apt-get install kubelet=1.17.7-00

$ kubectl get node
NAME     STATUS                     ROLES    AGE   VERSION
master   Ready,SchedulingDisabled   master   33m   v1.17.7
node01   Ready                      <none>   32m   v1.16.0

kubeadm으로 업그레이드를 한 뒤 kubelet까지 업그레이드를 해야 노드의 업그레이드가 완료된다.

 

kubeadm과 kubelet은 자동적으로 업그레이드가 되면 안되기 때문에 자동 업그레이드를 막아준다.

$ apt-mark hold kubeadm
kubeadm set on hold.

$ apt-mark hold kubelet
kubelet set on hold.

 

이제 master노드를 다시 스케쥴링 될 수 있도록 만든다.

$ kubectl uncordon master
node/master uncordoned

$ kubectl get node
NAME     STATUS   ROLES    AGE   VERSION
master   Ready    master   34m   v1.17.7
node01   Ready    <none>   33m   v1.16.0

 

이제 node01을 업그레이드 해보자.

$ kubectl drain node01
WARNING: ignoring DaemonSet-managed Pods: kube-system/kube-proxy-hggqf, kube-system/weave-net-rw9th
evicting pod kube-system/coredns-6955765f44-pwtbn
evicting pod kube-system/coredns-6955765f44-tnbjn
pod/coredns-6955765f44-pwtbn evicted
pod/coredns-6955765f44-tnbjn evicted
node/node01 evicted

$ ssh node01

node01 $ kubeadm upgrade node
[upgrade] Reading configuration from the cluster...
[upgrade] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[upgrade] Skipping phase. Not a control plane node[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.17" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[upgrade] The configuration for this node was successfully updated!
[upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.

node01 $ apt-get install kubelet=1.17.7-00

node01 $ apt-mark hold kubeadm
kubeadm set on hold.

node01 $ apt-mark hold kubelet
kubelet set on hold.

node01 $ logout

$ kubectl uncordon node01
node/node01 uncordoned

$ kubectl get node
NAME     STATUS   ROLES    AGE   VERSION
master   Ready    master   42m   v1.17.7
node01   Ready    <none>   42m   v1.17.7

 

이미 master 노드에서 업그레이드한 kubernetes의 정보가 있기 때문에 kubeadm upgrade node 를 통해서 업그레이드 할 수 있다.

 

정리하자면, 업그레이드 순서는 아래와 같다.

 

1. master node drain (kubectl drain <MASTER_NODE>)

2. upgrade master node (apt-get install kubeadm=<VERSION> kubeadm upgrade apply <VERSION>

3. upgrade kubelet (apt-get install kubelet=<VERSION>)

4. master node uncordon (kubectl uncordon <MASTER_NODE>)

 

5. worker node drain (kubectl drain <WORKER_NODE>)

6. upgrade worker node (kubeadm upgrade node)

7. upgrade kubelet (apt-get install kubelet=<VERSION>)

8. worker node uncordon (kubectl uncordon <WORKER_NODE>)

+ Recent posts