Kubesprayでv1.11.3からv1.12.5にアップグレードしてみた。

# はじめに

気がつけばv1.12.5用のKubesprayがリリースされているので、これをインストールしてみました。
ただ、メモリ、CPUに余裕のある node3, node4 でアップグレードに失敗し、最終的には動いていますが、実験環境としてはもう少しメモリが必要だったかなと思っています。

# 環境

## Kubespray(ansibleホスト)側

* Hardware: VM on VMWare Workstation 15
* OS: Ubuntu 18.04 LTS
* Ansible: v2.7.2
* Kubespray: v2.8.2

## K8sクラスター側

* Hardware: APU2 (PC Engines社製 apu2c4) AMD GX-412TC (4コア 1.2GHz), Memory 4GB, mSATA 128GB
* OS: Ubuntu 16.04.5 LTS (xenial) 64bit版

これとは別にiBOX 501N10というCPUがJ1900、NICx4構成でUbuntu 18.04 LTSのマシンを3台使った、v1.12.3のk8s環境もkubesprayで新規に構築しています。

# Kubernetes v1.12.5にアップグレードして困った事

kubectlがapiserverへlocalhost:8080を経由して接続しようとしたところ、実際にはinsecure-portが閉じられていたため、kubectlが実行できないという事態に遭遇しました。

    $ kubectl get node
    The connection to the server localhost:8080 was refused - did you specify the right host or port?

sudoと--kubeconfigを使って無事に結果が得られれば、問題なく動いている事が確認できます。

    $ sudo kubectl --kubeconfig=/etc/kubernetes/admin.conf get node
    NAME    STATUS                     ROLES                 AGE    VERSION
    node1   Ready                      ingress,master,node   262d   v1.12.5
    ...

理由は最初に書いたinsecure-portではなく6443ポートでapiserverが動いている事の他に、kubectlがデフォルトでは/etc/kubernetes/admin.confを読みに行かないため、--kubeconfigオプションが必要になっていた点、その上でパーミッションが (root:root, 0600) になっていため、一般ユーザーで実行することができなくなっていた事が原因でした。

解決のため ~/.kube/config にコピーをして読み取れるようパーミッションを変更して、sudoも--kubeconfigも必要なくなりましたが、一般ユーザー毎にRBACを設定するべきだったのか、IDの共有は安直な方法だったのかなと思っています。

# v1.12.5にするための主な手順

## git pull による kubesprayディレクトリの更新

既に別のブランチで作業をしているので、一旦内容を保存して、最新のtagをcheckoutしています。

    $ cd kubespray
    $ git add inventory/mycluster
    $ git commit -a -m 'commit all'
    $ git pull
    $ git checkout tags/v2.8.2 -b t_v2.8.2
    $ git branch
      master
      t_v2.7.0
    * t_v2.8.2


この時点で、inventory/mycluster には .gitignoreで指定されている、artifactsディレクトリだけが入っています。

## 新しいinventory/myclusterの準備

inventory の内容はかなり変更されているので、古いものは捨てて、新たに README.md の手順どおりに作成します。

    $ rsync -av inventory/mycluster inventory/mycluster.v1.11.3
    $ cp -rfp inventory/sample inventory/mycluster
    $ declare -a IPS=(192.168.1.11 192.168.1.12 192.168.1.13 192.168.1.194)
    $ CONFIG_FILE=inventory/mycluster/hosts.ini python3 contrib/inventory_builder/inventory.py ${IPS[@]}

## 設定の移行

新しく inventory/mycluster を準備したので、設定ファイルを編集しています。

* inventory/apucluster/group_vars/all/all.yml
* inventory/apucluster/group_vars/k8s-cluster/k8s-cluster.yml
* inventory/apucluster/group_vars/k8s-cluster/addons.yml

設定ファイルの場所はv1.11.3とほぼ変更ありませんが、v1.9.xなどと比較すると、かなり分割・整理が進んでいます。

## ansible-playbookコマンドの実行

最終的に docs/upgrade.md の方を確認して、kube_version を指定しつつ、upgrade-cluster.yml を実行します。

    $ ansible-playbook -i inventory/mycluster/hosts.ini --b upgrade-cluster.yml -e kube_version=v1.12.5

いまのところ node1, node2 については問題なくアップグレードが完了していますが、node3, node4 についてはアップグレードに失敗し、その後、ネットワークアクセスができなくなっています。

今後、原因については調査していきますが、手順自体に問題はなさそうです。

# 【事後】

node3,node4を強制的に再起動してから調査しました。

現状では次のようになっています。

    $ kubectl get nodes
    NAME    STATUS                     ROLES                 AGE    VERSION    
    node1   Ready                      ingress,master,node   265d   v1.12.5
    node2   Ready                      ingress,master        81d    v1.12.5
    node3   Ready,SchedulingDisabled   node                  265d   v1.11.3
    node4   Ready                      node                  265d   v1.11.3

この状態で、kubespray の upgrade-cluster.yml を再び実行しています。

    $ ansible-playbook -i inventory/apucluster/hosts.ini -b upgrade-cluster.yml -e kube_version=v1.12.5
    ....
    PLAY RECAP ************************************************************************************************
    localhost                  : ok=1    changed=0    unreachable=0    failed=0
    node1                      : ok=353  changed=33   unreachable=0    failed=0
    node2                      : ok=321  changed=22   unreachable=0    failed=0
    node3                      : ok=308  changed=38   unreachable=0    failed=0
    node4                      : ok=277  changed=38   unreachable=0    failed=0
    ....

upgrade-cluster.ymlの実行が問題なく終わった事を確認してから、uncordoned しました。

    $ kubectl uncordon node3
    node/node3 uncordoned

その後、自動的にv1.12.5に更新されていました。

    $ kubectl get nodes
    NAME    STATUS   ROLES                 AGE    VERSION
    node1   Ready    ingress,master,node   265d   v1.12.5
    node2   Ready    ingress,master        81d    v1.12.5
    node3   Ready    node                  265d   v1.12.5
    node4   Ready    node                  265d   v1.12.5

原因についてはログを確認していますが、rsyslogdが終了したところで記録がないので、少ないメモリが原因だったのかなと推測しています。

以上