はじめに
僕はVultrという海外VPSのマシンを2台借りて、すごくチープなKubernetesクラスタを構築しています。下記が少し古いですが、セットアップ方法です。
で、記事にはしていなかったのですが、このクラスタ、アップグレードを重ねてv1.13.2の状態になっていました。
今回この記事では、v1.13.2から最新のv1.14.1にバージョンアップした方法を紹介しようと思います。
アップグレードの苦労
今までのバージョンでのアップグレードは、実は何度も失敗してきました。失敗というのはKubernetesクラスタを構成するコンポーネントが立ち上がらなくなってしまい、kubeadmによるupgradeができなくなってしまうことです。
そうなるとクラスタを1から作り直していたのですが、そうすると当然クラスタ内にデプロイしていたアプリケーションを再度デプロイしなおす必要があります。クラスタ内で動作しているアプリケーションのmanifestは手元にあるので、それほど苦労することもないのですが、、結構悔しいです。
注意:これは我が家のクラスタがmaster 1台という推奨とは違う構成になっているのが主な原因です。masterを3台などでHA構成することで、ローリングアップデートができるようになり、そうすればアップグレードももっと簡単にできます。(激安クラスタの運命ですね。。)
ということで、今回は慎重に作業しようと誓いながら作業を始めました。
宣伝コーナー!!
僕がKubernetesクラスタを動かしているVultrという海外のVPSサービスです。下記リンクから申し込むと$50のクーポンがつくはずです。
前述の記事の方法でセットアップすれば実質無料でおよそ5か月Kubernetesクラスタを運用できます。
よく似たサービスにDigitalOceanがありますが、VultrはTokyoリージョンがあるという点が大きな違いとなっています。
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
参考
本家にかなり詳しいアップグレードマニュアルがあります。なので詳しい人はこれを見ればアップグレードできるはず・・です。
素直に指示に従ってみる
まずはmasterのアップグレードです
# apt-get update
# apt-mark unhold kubeadm && apt-get update && apt-get install -y kubeadm=1.14.1-00 && apt-mark hold kubeadm
...
The following packages have unmet dependencies:
kubelet : Depends: kubernetes-cni (= 0.6.0) but 0.7.5-00 is to be installed
あれ?
kubernetes-cniというものをバージョンアップしようとしたが、kubeletが期待しているものと違う。ということらしい。
以前のインストールでkubeletのバージョンはapt-markによって固定しているので、それが原因でしょう。
しかし、ここでkubeletの固定を解除して、一気にkubeadmとkubeletをアップグレードしてはいけません。毎回ここで間違えます。そうするとkubeadmがkubeletの新しい設定を作る前に新しいkubeletが起動してしまい、コンポーネントが正しく起動しなくなってしまうことが過去にありました。
(今回もダメなのかどうかは確かめていないのでわかりませんが・・)
ひとまずmasterをv1.13.5にアップグレードする
とりあえず、今はv1.13.2ですが、これをいきなりv1.14.1にするのではなくv1.13.5というv1.13系の最新のパッチバージョンに上げたのちに、v1.14.1にする。という作戦でいくことにしました。
# apt-mark unhold kubeadm && apt-get update && apt-get install -y kubeadm=1.13.5-00 && apt-mark hold kubeadm
The following packages have unmet dependencies:
kubelet : Depends: kubernetes-cni (= 0.6.0) but 0.7.5-00 is to be installed
E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.
え、これもできないのか・・
パッチバージョン間のバージョンアップ方法はドキュメントに明記していないが、このタイミングならkubeadmとkubeletを一気に上げても大丈夫では? と考え
# apt-mark unhold kubeadm kubelet && apt-get update && apt-get install -y kubeadm=1.13.5-00 kubelet=1.13.5-00 && apt-mark hold kubeadm kubelet
を実行。無事 v1.13.5にアップグレードできた。
v1.13.5のkubeadmでクラスタを
# kubeadm upgrade plan
[preflight] Running pre-flight checks.
[upgrade] Making sure the cluster is healthy:
[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'
[upgrade] Fetching available versions to upgrade to
[upgrade/versions] Cluster version: v1.13.2
[upgrade/versions] kubeadm version: v1.13.5
I0418 02:03:25.771423 15661 version.go:237] remote version is much newer: v1.14.1; falling back to: stable-1.13
[upgrade/versions] Latest stable version: v1.13.5
[upgrade/versions] Latest version in the v1.13 series: v1.13.5
Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
COMPONENT CURRENT AVAILABLE
Kubelet 1 x v1.13.2 v1.13.5
1 x v1.13.5 v1.13.5
Upgrade to the latest version in the v1.13 series:
COMPONENT CURRENT AVAILABLE
API Server v1.13.2 v1.13.5
Controller Manager v1.13.2 v1.13.5
Scheduler v1.13.2 v1.13.5
Kube Proxy v1.13.2 v1.13.5
CoreDNS 1.2.6 1.2.6
Etcd 3.2.24 3.2.24
You can now apply the upgrade by executing the following command:
kubeadm upgrade apply v1.13.5
_____________________________________________________________________
できそう!
ということでアップグレード
# kubeadm upgrade apply v1.13.5
[upgrade/staticpods] Moved new manifest to "/etc/kubernetes/manifests/kube-apiserver.yaml" and backed up old manifest to "/etc/kubernetes/tmp/kubeadm-backup-manifests-2019-04-18-02-04-52/kube-apiserver.yaml"
[upgrade/staticpods] Waiting for the kubelet to restart the component
[upgrade/staticpods] This might take a minute or longer depending on the component/version gap (timeout 5m0s)
Static pod: kube-apiserver-kubernetes hash: 1b4484ac0b54c491dc5cfe4d158f31c0
Static pod: kube-apiserver-kubernetes hash: 1b4484ac0b54c491dc5cfe4d158f31c0
Static pod: kube-apiserver-kubernetes hash: 1b4484ac0b54c491dc5cfe4d158f31c0
Static pod: kube-apiserver-kubernetes hash: 1b4484ac0b54c491dc5cfe4d158f31c0
Static pod: kube-apiserver-kubernetes hash: 1b4484ac0b54c491dc5cfe4d158f31c0
[upgrade/apply] FATAL: couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced
死んだ!!!
kubeletのログを見ると、このログを最後にkube-apiserverが起動していない、nodeのconditionが異常だったのかな?
Apr 18 02:09:59 kubernetes kubelet[15375]: W0418 02:09:59.079140 15375 eviction_manager.go:160] Failed to admit pod kube-apiserver-kubernetes_kube-system(1b4484ac0b54c491dc5cfe4d158f31c0) - node has conditions: [DiskPressure]
あきらめずにkubeletをrestartしてみる
# systemctl restart kubelet
無事kube-apiserverが復活 何だったんだ・・
# docker ps |grep apiserver
1044739d1d01 177db4b8e93a "kube-apiserver --au…" About a minute ago Up About a minute k8s_kube-apiserver_kube-apiserver-kubernetes_kube-system_1b4484ac0b54c491dc5cfe4d158f31c0_0
d0b403dc4ec2 k8s.gcr.io/pause:3.1 "/pause" About a minute ago Up About a minute k8s_POD_kube-apiserver-kubernetes_kube-system_1b4484ac0b54c491dc5cfe4d158f31c0_0
もう一度アップグレードを実行してみる。
# kubeadm upgrade apply v1.13.5
...
[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.13.5". Enjoy!
[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.
今度はうまくいった!
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kubernetes Ready master 129d v1.13.5
worker01 Ready <none> 129d v1.13.2
kubectlでも上がっていることが確認できた。
workerをv1.13.5にアップグレードする
workerも上げておく
# apt-mark unhold kubeadm kubelet && apt-get update && apt-get install -y kubeadm=1.13.5-00 kubelet=1.13.5-00 && apt-mark hold kubeadm kubelet
(kubeadmは上げておく必要があったかな?)
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kubernetes Ready master 129d v1.13.5
worker01 Ready <none> 129d v1.13.5
masterをv1.14.1にアップグレードする
ここからはあっさりとアップグレードできました。
# apt-mark unhold kubeadm && apt-get update && apt-get install -y kubeadm=1.14.1-00 && apt-mark hold kubeadm
...
The following packages will be upgraded:
kubeadm
1 upgraded, 0 newly installed, 0 to remove and 6 not upgraded.
Need to get 8,150 kB of archives.
After this operation, 3,171 kB of additional disk space will be used.
Get:1 https://packages.cloud.google.com/apt kubernetes-xenial/main amd64 kubeadm amd64 1.14.1-00 [8,150 kB]
Fetched 8,150 kB in 0s (9,463 kB/s)
(Reading database ... 99264 files and directories currently installed.)
Preparing to unpack .../kubeadm_1.14.1-00_amd64.deb ...
Unpacking kubeadm (1.14.1-00) over (1.13.5-00) ...
Setting up kubeadm (1.14.1-00) ...
kubeadm set on hold.
# kubeadm upgrade plan
...
Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
COMPONENT CURRENT AVAILABLE
Kubelet 2 x v1.13.5 v1.14.1
Upgrade to the latest stable version:
COMPONENT CURRENT AVAILABLE
API Server v1.13.5 v1.14.1
Controller Manager v1.13.5 v1.14.1
Scheduler v1.13.5 v1.14.1
Kube Proxy v1.13.5 v1.14.1
CoreDNS 1.2.6 1.3.1
Etcd 3.2.24 3.3.10
You can now apply the upgrade by executing the following command:
kubeadm upgrade apply v1.14.1
_____________________________________________________________________
$ kubeadm upgrade apply v1.14.1
...
[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.14.1". Enjoy!
[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.
$ apt-mark unhold kubelet &&apt-get update && apt-get install -y kubelet=1.14.1-00 kubectl=1.14.1-00 && apt-mark hold kubelet
...
# systemctl restart kubelet
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kubernetes Ready master 129d v1.14.1
worker01 Ready <none> 129d v1.13.5
workerをv1.14.1にアップグレードする
こちらも簡単。少しマニュアルとは違う指定にしましたが、この辺はお好みで。
# apt-mark unhold kubeadm && apt-get update && apt-get install -y kubeadm=1.14.1-00 && apt-mark hold kubeadm
// どうせworkerが1つしかないからdrainは意図的に行わない
# kubeadm upgrade node config --kubelet-version v1.14.1
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.14" 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.
//まちがえてkubeletが上がらないようにholdしておく
# apt-mark unhold kubelet && apt-get install -y kubelet=1.14.1-00 kubectl=1.14.1-00 && apt-mark hold kubelet
# systemctl restart kubelet
すべてがv1.14.1になりました
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kubernetes Ready master 129d v1.14.1
worker01 Ready <none> 129d v1.14.1
おまけ:metrics-serverの設定
metrics-serverを入れないとkubectl top node, kubectl top podが動作しません。
ということでこの機会にmetrics-serverも入れることにします。
といっても、下記のmanifestを使うだけです。
我が家の環境の場合は
command:
- /metrics-server
- --kubelet-preferred-address-types=InternalIP
- --kubelet-insecure-tls
と2つ引数を変更する必要がありました。
kubelet-preferred-address-typesはnodeの名前でDNS解決できない環境で設定する必要があります。
kubelet-insecure-tlsは手抜きでやっています。本当はちゃんとした証明書を使うようにすべきです。
そして無事にkubectl top nodesが実行できました。
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
kubernetes 154m 15% 646Mi 82%
worker01 338m 33% 611Mi 77%