はじめに
Kubespray v2.30.0で構築したK8sクラスターにKubespray v2.31.0を適用します。
環境
- サーバー: TX120 S3p (CPU: Xeon e3-1230 v2, Memory: 32GB) x4台
適用対象の現行バージョン
- Kubespray v2.30.0 (Kubernetes v1.34.3)
- OS: Ubuntu 24.0.4 LTS amd64版
参考資料
事前確認
作業前に次の点を確認します。
RELEASE_NOTESの確認
必ずRelease Notesの各バージョンに記載されている変更内容を確認してください。
v2.31.0のリリースノードでは、cgroup.v1やingress-nginxの提供終了に伴う対応が掲載されていますが、特に対応はしていません。
ingress-nginxについてはEnvoy Gatewayへ移行しています。
Rook/Cephの状態確認
対象のクラスターではPVCを利用するためにRook/Cephを利用しています。
Rook/Cephを利用している場合には、あらかじめクラスターの状態が、HEALTH_OK であることを確認します。
$ podname=$(kubectl -n rook-ceph get pod -l app=rook-ceph-tools -o jsonpath='{.items[*].metadata.name}')
$ kubectl -n rook-ceph exec -it "${podname}" -- ceph status
各ノードが参照するAPI Serverのホスト名を確認
過去にaddons.ymlファイルでkube_vip_services_enabled:を有効にしていたが、現在は無効(false)である場合などは作業中に障害となる可能性があります。
各ノードのAPI ServerへのURLを確認します。
## kubesprayのansible-playbookを実行しているディレクトリで実行
$ . venv/k8s/bin/activate
(k8s) $ ansible all -i inventory/mycluster/inventory.ini -b -m shell -a 'grep server: /etc/kubernetes/*.conf'
もしlb-apiserver.kubernetes.localが指定されていた場合には、kube-vipを有効にしていること、各ノードの/etc/hostsに、lb-apiserver.kubernetes.localに対応したエントリがあることを確認し、このIPアドレスをloopback(127.0.0.1)に設定します。
(k8s) $ ansible all -i inventory/mycluster/inventory.ini -b -m shell -a 'grep lb-apiserver /etc/hosts'
## "192.168.56.128"は実際のVIPアドレスに変更すること
(k8s) $ ansible all -i inventory/mycluster/inventory.ini -b -m lineinfile -a 'path=/etc/hosts regexp="^192.168.56.128" line="127.0.0.1 lb-apiserver.kubernetes.local"'
## 全てのkubeletを再起動します
(k8s) $ ansible all -i inventory/mycluster/inventory.ini -b -m systemd -a 'name=kubelet.service state=restarted'
これによって
もしkube-vipを無効化しているのであれば、全ノードの/etc/kubernetes/以下の設定ファイルから、lb-apiserver.kubernetes.localを参照している部分について、localhostなどのloopbackアドレスに変更します。
kubeletがAPI serverと通信できなくなった場合は/etc/kubernetes/*.confファイルの中からVIP(lb-apiserver.kubernetes.local)を参照している箇所を修正して、systemctlからkubeletを再起動します。
詳細は参考資料にある「Kubespray v2.28.1でクラスターをアップグレードした時のメモ」の後半にある「適用後に発生した問題」のセクションを確認してください。
システム全体のPod Disruption Budgets(pdb)設定の確認
例えば2つのPodでクラスターを組んでいる時に、「最大1つまで停止して良い」といった設定を行っておくことが可能で、2つ目のPodも停止しようとするとシステム側でノードを停止しないようにDrain処理を中断させます。
これはpdbの設定を確認することで可能になっています。
$ kubectl get --all-namespaces pdb
NAMESPACE NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
dex postgres-pgcluster-pdb 1 N/A 0 173d
...
この時にMAX UNAVAILABLEが0などになっていないか、MIN AVAILABLEが1で正しいようにみえても、そのPodが1つのノードで全て稼動しているといったことがないように設定されているか確認が必要です。
自前のアプリケーションの場合は、Pod Anti Affinityの設定を見直してください。
設定されている例としてApache Zookeeperの設定を下記に掲載していますが、Nodeオブジェクトに設定しているlabels:にある"kubernetes.io/hostname"をみて、さらにPodのlabels:にあるapp=zkを含むPodをノードに重複しないように配置してくれます。
template:
metadata:
labels:
app: zk
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- zk
topologyKey: "kubernetes.io/hostname"
ただnginxなど、「できるだけ分散したい」といった用途であれば、requiredDuring...ではなく、preferredDuring...を指定するなど必要に応じて使い分けます。
作業手順
基本的な遵守事項は次のとおり。
- masterブランチに変更は加えないこと
- masterブランチから作業用ブランチは作成しないこと
- 作業の度にtagsから作業用ブランチを作成すること
- 変更内容は作業用ブランチにcommitすること
始めて実施する場合にはあらかじめGithubからkubesprayディレクトリをpullすること。
$ git pull https://github.com/kubernetes-sigs/kubespray.git
通常はkubesprayディレクトリが存在するものとして次のステップから開始する。
$ cd kubespray
$ git status
## コミットしていないファイルがあるとブランチの作成ができないため、untrackedやchangedなファイルがあればcommitしておく
## masterブランチにcommitしないため日付のブランチを作成してcommitする
$ git checkout -b $(date +%Y%m%d.%H%M%S)_tmp
$ git commit -a -m 'prepare to upgrade v2.31.0'
## 【git statusで差分が表示されなければ、ここからスタート】まずkubesprayの最新のリポジトリに更新
$ git checkout master
$ git pull
## 次のバージョンタグを確認する
$ git tag
## v2.28.xの次のv2.31.0からブランチを作成する
$ git checkout refs/tags/v2.31.0 -b t_v2.31.0
## 先頭の tag: v2.31.0 を確認する
$ git log
## 新しいvenv環境を作成し、環境変数を読み込む
$ rm -rf venv
$ /usr/bin/python3 -m venv venv/k8s
$ . venv/k8s/bin/activate
(k8s) $ pip install -r requirements.txt
## inventory/mycluster を作成する。(もし inventory/mycluster があれば削除する)
(k8s) $ rm -rf inventory/mycluster
(k8s) $ cp -rfp inventory/sample inventory/mycluster
## v2.28.0以降ではinventory/mycluster/inventory.iniファイルを利用する
(k8s) $ git checkout t_v2.30.0 inventory/mycluster/inventory.ini
## .gitignore に !inventory/mycluster を追加する
(k8s) $ vi .gitignore
(k8s) $ git add .gitignore inventory/mycluster
(k8s) $ git commit -m 'Added the inventory/mycluster config directory.'
## 一つ前のバージョン(v2.30.0)との差分を確認する
(k8s) $ git diff t_v2.30.0 inventory/mycluster
## 変更が必要なファイルは group_vars/k8s-cluster/{addons.yml,k8s-cluster.yml,k8s-net-calico.yml} のみです
## container_manager: が変更になるなどの大規模な変更がないか、念のため全体を概観してください
## 変更する際には各ファイルの差分を確認しながら作業を進めていきます
(k8s) $ cd inventory/mycluster/group_vars/k8s_cluster
(k8s) $ git diff t_v2.30.0 addons.yml
(k8s) $ vi addons.yml
(k8s) $ git diff t_v2.30.0 k8s-cluster.yml
(k8s) $ vi k8s-cluster.yml
(k8s) $ git diff t_v2.30.0 k8s-net-calico.yml
(k8s) $ vi k8s-net-calico.yml
## 変更が終ったら差分をコミットし、トップディレクトリに移動します
(k8s) $ git add .
(k8s) $ git commit -m 'Modified addons.yml, k8s-cluster.yml, and k8s-net-calico.yml files.'
(k8s) $ cd ../../../../
## 変更方法をupgrades.mdから確認する。そのままでは古いコマンドなので適宜変更すること
(k8s) $ less docs/operations/upgrades.md
## ansible.cfgを見直し、remote_userなどを環境に合わせて、適宜変更する
(k8s) $ git diff t_v2.30.0 ansible.cfg
## 変更したinventory.iniが前の版から変化していないことを確認する (v2.28.0以降は一つ前と比較する)
(k8s) $ git diff t_v2.30.0 inventory/mycluster/inventory.ini
## 変更したansible.cfgが正常に動くか動作を確認し、同時に"kube_node"などに対応するノードの名前と数が正しいか確認する
(k8s) $ ansible kube_control_plane -i inventory/mycluster/inventory.ini -m command -a 'uname -n'
(k8s) $ ansible etcd -i inventory/mycluster/inventory.ini -m command -a 'uname -n'
(k8s) $ ansible kube_node -i inventory/mycluster/inventory.ini -m command -a 'uname -n'
## 正常に動作したら残りのファイルをコミットする (変更点があればinventory.iniも)
(k8s) $ git add ansible.cfg inventory/mycluster/inventory.ini
(k8s) $ git commit -m 'Updated the configuration for Ansible.'
## kube_version を確認するが、v2.30.0から設定ファイルにデフォルト値が記載されなくなったので、RELEASE_NOTESか、checksums.ymlファイルからサポートされているバージョンを確認する
(k8s) $ grep -C 40 kubelet_checksums roles/kubespray_defaults/vars/main/checksums.yml
## 確認したkube_versionを指定して、upgrade-cluster.ymlを実行する
(k8s) $ ansible-playbook upgrade-cluster.yml -b -i inventory/mycluster/inventory.ini -e kube_version=1.35.4
さいごに
最初にアップグレードしたクラスターでは問題なく作業が完了しています。
v2.31.0ではingress-nginxの削除など、それなりに大きな変更が行われています。
必ずReleaseNoteは確認してください。
これから他のクラスターのアップグレードが続きますが、問題があればここにまとめていきます。