kubeadm環境のKubernetesのアップグレード

kubeadmにて作成したKubernetes Clusterをアップグレードしてみます。下記は参考の公式ドキュメント。

Upgrading kubeadm clusters

環境

  • 構成
    • マスターノード
      • 1台
    • ワーカーノード
      • 1台
  • バージョン
    • OS
    • kubernetes
      • 現行
        • 1.19.0
      • アップグレード先
        • 1.20.2-00
    • CNI
      • calico/cni:v3.17.1
    • コンテナランタイム
      • Docker version 19.03.11

etcdはKubernetes内に作っています。

アップグレード中の影響

ざっと確認ですが、マスターノードをアップグレード中は、KubernetesのControl Planeで提供される機能を利用できなくなります。現在起動中のPodには影響を与えませんが、kube-apiへのアクセス、SchedulerやControlerでの管理動作、etcdへのアクセスは不可能となります。そのため、新規でのオブジェクト作成やDaemonSetにたいする管理動作等には影響が発生します。

事前確認

アップグレード先のKubernetesバージョンに対して、現在利用しているCNIやコンテナランタイムが動作可能であるか、事前に確認する必要があります。それら以外にも、管理用のPodやControllerを起動させている場合、それらを動作対応も確認しておく必要があります。

CNI(Calico)

Calicoをバージョンしたところ、Kubernetes 1.20がサポートに入っていなかったのですが、動くことを知っているので、無視してアップグレードしてしまいます。

Kubernetes requirements
Supported versions
We test Calico v3.17 against the following Kubernetes versions.
1.17
1.18
1.19

Kubernetes requirements

コンテナラインタイム(Docker CE)

公式ドキュメントには下記とあるのですが、リリースノート見に行っても、Dockerがdeprecatedされた情報のみで、サポートバージョンについては記載ありませんでした。

The Kubernetes release notes list which versions of Docker are compatible with that version of Kubernetes.

Container runtimes Docker

Stack overflowに、以下の投稿ありましたが、結局確かなことは分かりませんでした。

I have confirmed the information on the changelog for version 1.16. On the changelog for version 1.17, 1.18 and 1.19, there is no change about the Dependecies section about docker version. It seems that k8s 1.17, 1.18 and 1.19 support the same version. (1.13.1, 17.03, 17.06, 17.09, 18.06, 18.09)

Which docker versions are supported on kubernetes 1.18 and 1.19?

まあ、動くこと知っているので、無視してアップグレードしてしまいます。

マスターノードのアップグレード

マスターノード側から作業します。マスターノードにssh接続します。

kubeadmのアップグレード

アップグレード可能なkubeadmバージョンを確認します。1.20バージョンの最新である、 1.20.2-00 へアップグレードする方針とします。

$ sudo apt update
$ sudo apt-cache madison kubeadm

実際にアップグレードする前に、ノードをdrainして、evict可能なPodを退避させてあげます。

$ kubectl get node -o wide
NAME                     STATUS   ROLES    AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION   CONTAINER-RUNTIME
kubeadm-upgrade-master   Ready    master   30h   v1.19.0   10.146.0.5    <none>        Ubuntu 20.04.1 LTS   5.4.0-1034-gcp   docker://19.3.11
kubeadm-upgrade-worker   Ready    <none>   29h   v1.19.0   10.146.0.6    <none>        Ubuntu 20.04.1 LTS   5.4.0-1034-gcp   docker://19.3.11
$
$ kubectl drain kubeadm-upgrade-master --ignore-daemonsets
node/kubeadm-upgrade-master already cordoned
WARNING: ignoring DaemonSet-managed Pods: kube-system/calico-node-rdsjh, kube-system/kube-proxy-xfg67
evicting pod kube-system/calico-kube-controllers-744cfdf676-qnfl4
evicting pod kube-system/coredns-f9fd979d6-fg92v
evicting pod kube-system/coredns-f9fd979d6-hsr4v
pod/calico-kube-controllers-744cfdf676-qnfl4 evicted
pod/coredns-f9fd979d6-hsr4v evicted
pod/coredns-f9fd979d6-fg92v evicted
node/kubeadm-upgrade-master evicted
$
$ kubectl get node -o wide
NAME                     STATUS                     ROLES    AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION   CONTAINER-RUNTIME
kubeadm-upgrade-master   Ready,SchedulingDisabled   master   30h   v1.19.0   10.146.0.5    <none>        Ubuntu 20.04.1 LTS   5.4.0-1034-gcp   docker://19.3.11
kubeadm-upgrade-worker   Ready                      <none>   29h   v1.19.0   10.146.0.6    <none>        Ubuntu 20.04.1 LTS   5.4.0-1034-gcp   docker://19.3.11

モジュールをアップグレードします。

# replace x in 1.20.x-00 with the latest patch version
$ sudo apt-mark unhold kubeadm
$ sudo apt-get install -y kubeadm=1.20.2-00
$ sudo apt-mark hold kubeadm

バージョンの確認。

$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-13T13:25:59Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}

Kubernetes Clusterのアップグレード

アップグレード可否を確認できるコマンドが用意されているため、事前に確認を行います。

$ sudo kubeadm upgrade plan v1.20.2
[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 -o yaml'
[preflight] Running pre-flight checks.
[upgrade] Running cluster health checks
[upgrade] Fetching available versions to upgrade to
[upgrade/versions] Cluster version: v1.19.7
[upgrade/versions] kubeadm version: v1.20.2
[upgrade/versions] Latest stable version: v1.20.2
[upgrade/versions] Latest version in the v1.19 series: v1.20.2

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

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

COMPONENT                 CURRENT   AVAILABLE
kube-apiserver            v1.19.7   v1.20.2
kube-controller-manager   v1.19.7   v1.20.2
kube-scheduler            v1.19.7   v1.20.2
kube-proxy                v1.19.7   v1.20.2
CoreDNS                   1.7.0     1.7.0
etcd                      3.4.9-1   3.4.13-0

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

        kubeadm upgrade apply v1.20.2

_____________________________________________________________________


The table below shows the current state of component configs as understood by this version of kubeadm.
Configs that have a "yes" mark in the "MANUAL UPGRADE REQUIRED" column require manual config upgrade or
resetting to kubeadm defaults before a successful upgrade can be performed. The version to manually
upgrade to is denoted in the "PREFERRED VERSION" column.

API GROUP                 CURRENT VERSION   PREFERRED VERSION   MANUAL UPGRADE REQUIRED
kubeproxy.config.k8s.io   v1alpha1          v1alpha1            no
kubelet.config.k8s.io     v1beta1           v1beta1             no
_____________________________________________________________________

実行。

$ sudo kubeadm upgrade apply v1.20.2
[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 -o yaml'
[preflight] Running pre-flight checks.
[upgrade] Running cluster health checks
[upgrade/version] You have chosen to change the cluster version to "v1.20.2"
[upgrade/versions] Cluster version: v1.19.7
[upgrade/versions] kubeadm version: v1.20.2
[upgrade/confirm] Are you sure you want to proceed with the upgrade? [y/N]: y
[upgrade/prepull] Pulling images required for setting up a Kubernetes cluster
...
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.20.2". Enjoy!

[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.

アップグレードされました。尚、本アップグレード処理では、Cluster内で利用されている証明書の更新もされるそうです。そのため、独自に証明書を作成している場合、考慮が必要となります。

Note: kubeadm upgrade also automatically renews the certificates that it manages on this node. To opt-out of certificate renewal the flag --certificate-renewal=false can be used.

CNIのアップグレード

CNIのアップグレードが必要な場合、このタイミングでアップグレード(実行されているPod)の更新を行います。本構成のCalicoでは、アップグレード不要のため、スキップします。

その他マスターノードのアップグレード

今回はシングル構成のため実施しないですが、マスターノードが冗長構成の場合、以下のコマンドにて同様にアップグレード処理を行います。

$ sudo kubeadm upgrade node

kubeletとkubectlをアップグレード

kubeletとkubectlのモジュールを、kubeadmのバージョンに合わせてアップグレードします。

$ sudo apt-mark unhold kubelet kubectl
$ sudo apt-get install -y kubelet=1.20.2-00 kubectl=1.20.2-00
$ sudo apt-mark hold kubelet kubectl

kubeletプロセスの再起動。

$ sudo systemctl daemon-reload
$ sudo systemctl restart kubelet
$ sudo systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: active (running) since Tue 2021-01-19 08:50:23 UTC; 9s ago
       Docs: https://kubernetes.io/docs/home/
   Main PID: 23941 (kubelet)
      Tasks: 13 (limit: 9544)
     Memory: 34.7M
     CGroup: /system.slice/kubelet.service
             └─23941 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml >

Jan 19 08:50:24 kubeadm-upgrade-master kubelet[23941]: I0119 08:50:24.910708   23941 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "lib-mod>
Jan 19 08:50:24 kubeadm-upgrade-master kubelet[23941]: I0119 08:50:24.910737   23941 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "xtables>
Jan 19 08:50:24 kubeadm-upgrade-master kubelet[23941]: I0119 08:50:24.910769   23941 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "usr-loc>
Jan 19 08:50:24 kubeadm-upgrade-master kubelet[23941]: I0119 08:50:24.910800   23941 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "usr-sha>
Jan 19 08:50:24 kubeadm-upgrade-master kubelet[23941]: I0119 08:50:24.910829   23941 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "cni-bin>
Jan 19 08:50:24 kubeadm-upgrade-master kubelet[23941]: I0119 08:50:24.910857   23941 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "etc-pki>
Jan 19 08:50:24 kubeadm-upgrade-master kubelet[23941]: I0119 08:50:24.910884   23941 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "lib-mod>
Jan 19 08:50:24 kubeadm-upgrade-master kubelet[23941]: I0119 08:50:24.910913   23941 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "kube-pr>
Jan 19 08:50:24 kubeadm-upgrade-master kubelet[23941]: I0119 08:50:24.910948   23941 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "ca-cert>
Jan 19 08:50:24 kubeadm-upgrade-master kubelet[23941]: I0119 08:50:24.910962   23941 reconciler.go:157] Reconciler: start to sync state

マスター側での処理完了のため、nodeをuncordonしておきます。

$ kubectl uncordon kubeadm-upgrade-master
node/kubeadm-upgrade-master uncordoned
$
$ kubectl get node -o wide
NAME                     STATUS   ROLES                  AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION   CONTAINER-RUNTIME
kubeadm-upgrade-master   Ready    control-plane,master   30h   v1.20.2   10.146.0.5    <none>        Ubuntu 20.04.1 LTS   5.4.0-1034-gcp   docker://19.3.11
kubeadm-upgrade-worker   Ready    <none>                 30h   v1.19.0   10.146.0.6    <none>        Ubuntu 20.04.1 LTS   5.4.0-1034-gcp   docker://19.3.11

ワーカーノードのアップグレード

ワーカーノードにssh接続します。

kubeadmのアップグレード

マスターノードと同様に、kubeadmのモジュールをアップグレードします。

その前に、対象ノードをdrainしておきます。

$ kubectl drain kubeadm-upgrade-worker --ignore-daemonsets
node/kubeadm-upgrade-worker already cordoned
WARNING: ignoring DaemonSet-managed Pods: kube-system/calico-node-tj78s, kube-system/kube-proxy-s9b6j
evicting pod kube-system/coredns-74ff55c5b-xcjfq
evicting pod kube-system/calico-kube-controllers-744cfdf676-556b4
evicting pod default/sample-54dd9cdb5d-xkgnw
evicting pod kube-system/coredns-74ff55c5b-gz4kj
pod/sample-54dd9cdb5d-xkgnw evicted
pod/calico-kube-controllers-744cfdf676-556b4 evicted
pod/coredns-74ff55c5b-gz4kj evicted
pod/coredns-74ff55c5b-xcjfq evicted
node/kubeadm-upgrade-worker evicted
$
$ kubectl get node -o wide
NAME                     STATUS                     ROLES                  AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION   CONTAINER-RUNTIME
kubeadm-upgrade-master   Ready                      control-plane,master   30h   v1.20.2   10.146.0.5    <none>        Ubuntu 20.04.1 LTS   5.4.0-1034-gcp   docker://19.3.11
kubeadm-upgrade-worker   Ready,SchedulingDisabled   <none>                 30h   v1.19.0   10.146.0.6    <none>        Ubuntu 20.04.1 LTS   5.4.0-1034-gcp   docker://19.3.11

アップグレードします。

$ sudo apt-mark unhold kubeadm
$ sudo apt-get update
$ sudo apt-get install -y kubeadm=1.20.2-00
$ sudo apt-mark hold kubeadm

確認。

$ sudo kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-13T13:25:59Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}

Kubernetes Clusterのアップグレード

Clusterのアップグレード処理を実施します。

$ sudo 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 -o yaml'
[preflight] Running pre-flight checks
[preflight] Skipping prepull. Not a control plane node.
[upgrade] Skipping phase. Not a control plane node.
[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.

kubeletとkubectlのアップグレード

kubeletとkubectlのモジュールをアップグレードします。

$ sudo apt-mark unhold kubelet kubectl
$ sudo apt-get install -y kubelet=1.20.2-00 kubectl=1.20.2-00
$ sudo apt-mark hold kubelet kubectl

kubeletプロセスの再起動。

$ sudo systemctl daemon-reload
$ sudo systemctl restart kubelet
$ sudo systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: active (running) since Tue 2021-01-19 09:14:03 UTC; 4s ago
       Docs: https://kubernetes.io/docs/home/
   Main PID: 43766 (kubelet)
      Tasks: 13 (limit: 9544)
     Memory: 30.3M
     CGroup: /system.slice/kubelet.service
             └─43766 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml >

Jan 19 09:14:05 kubeadm-upgrade-worker kubelet[43766]: I0119 09:14:05.038554   43766 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "policys>
Jan 19 09:14:05 kubeadm-upgrade-worker kubelet[43766]: I0119 09:14:05.038614   43766 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "kube-pr>
Jan 19 09:14:05 kubeadm-upgrade-worker kubelet[43766]: I0119 09:14:05.038694   43766 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "xtables>
Jan 19 09:14:05 kubeadm-upgrade-worker kubelet[43766]: I0119 09:14:05.038789   43766 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "lib-mod>
Jan 19 09:14:05 kubeadm-upgrade-worker kubelet[43766]: I0119 09:14:05.038826   43766 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "kube-pr>
Jan 19 09:14:05 kubeadm-upgrade-worker kubelet[43766]: I0119 09:14:05.038976   43766 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "var-lib>
Jan 19 09:14:05 kubeadm-upgrade-worker kubelet[43766]: I0119 09:14:05.039004   43766 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "xtables>
Jan 19 09:14:05 kubeadm-upgrade-worker kubelet[43766]: I0119 09:14:05.039033   43766 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "cni-net>
Jan 19 09:14:05 kubeadm-upgrade-worker kubelet[43766]: I0119 09:14:05.039057   43766 reconciler.go:224] operationExecutor.VerifyControllerAttachedVolume started for volume "calico->
Jan 19 09:14:05 kubeadm-upgrade-worker kubelet[43766]: I0119 09:14:05.039071   43766 reconciler.go:157] Reconciler: start to sync state

ワーカーノード側での処理完了のため、nodeをuncordonしておきます。

$ kubectl uncordon kubeadm-upgrade-worker
node/kubeadm-upgrade-worker uncordoned
$
$ kubectl get node -o wide
NAME                     STATUS   ROLES                  AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION   CONTAINER-RUNTIME
kubeadm-upgrade-master   Ready    control-plane,master   30h   v1.20.2   10.146.0.5    <none>        Ubuntu 20.04.1 LTS   5.4.0-1034-gcp   docker://19.3.11
kubeadm-upgrade-worker   Ready    <none>                 30h   v1.20.2   10.146.0.6    <none>        Ubuntu 20.04.1 LTS   5.4.0-1034-gcp   docker://19.3.11

Clusterのアップグレードが完了しました。

その他メモ

kubeadm upgrade applykubeadm upgrade node 時に、何をしているかの説明。

How it works

kubectl cordonkubectl uncordon を実行するわけで、Cluster上でPodが偏ってしまうじゃないかと思ったのですが、 descheduler というものがあるみたいです。

kubernetes-sigs/descheduler

Descheduler, based on its policy, finds pods that can be moved and evicts them.

Cluster上でCronJobとして動くものらしいです。