TT Lab
はじめる
学ぶ 学習パス コース

Kubespray と Terraform でクラスターを構築する

1.35.8 から 1.36.4 へ — 同じノード、新しいバージョン

TT Labで続きを見る

目標

kubespray v2.32.0でKubernetes 1.35.8クラスターを構築してワークロードを起動しておき、インベントリのバージョンを1.36.4に変更して、upgrade-cluster.ymlで1つ上げます。上げる前後を「写真」として残し、何が変わって何がそのままかを証拠で語ります。

なぜ重要なのか

Kubernetesは、おおむね4か月ごとにマイナーバージョンが出て、サポート期間が過ぎるとセキュリティパッチが途切れます。そのため、アップグレードは1回やって終わりの作業ではなく、定期的な作業です。 kubesprayは、アップグレードをインストールと同じ宣言として扱います。インベントリのバージョンを変更して、プレイブックを実行します。その代わり、順序があります。マイナーバージョンを飛ばさず、kubesprayのタグを飛ばさず、ノードごとにcordon → drain → 更新 → uncordonを行います。ノードが1台だと、drainの間ワークロードが止まることも、このラボで自分で見ます。 インストールとアップグレードを合わせて、約13分待ちます。余裕が足りなければ、セッションを延長してください。

ステップ

  1. /opt/ks/kubesprayでansible-playbook -i /root/ks/inventory/lab/inventory.ini cluster.ymlを実行して、出力の全体を残してください(約7分、保存先: /root/ks/logs/cluster-1.log)。インベントリのkube_versionは1.35.8です。終わったら、APIサーバーのバージョンがv1.35.8である必要があります。
  2. defaultネームスペースにDeploymentweb(イメージはregistry.k8s.io/e2e-test-images/agnhost:2.59、引数はnetexec --http-port=8080、レプリカ2)を作成して、2つのPodがReadyになるようにしてください。そのあと次のフィールドを書いてください(書き込み先: /root/ks/upgrade/before.json)。server_version、kubelet_version、etcd_version(etcd --versionのバージョン)、coredns_image(coredns Deploymentのイメージ)、node_uid、web_pod_uids(webのPodのUIDをソートした配列)です。
  3. kube_versionを1.36.4に変更してください(対象: /root/ks/inventory/lab/group_vars/k8s_cluster/k8s-cluster.yml)。-eで渡さずに、ファイルを直します。ansible-inventory --host node1が1.36.4を返す必要があります。
  4. /opt/ks/kubesprayでansible-playbook -i /root/ks/inventory/lab/inventory.ini upgrade-cluster.ymlを実行して、出力の全体を残してください(約6分、保存先: /root/ks/logs/upgrade.log)。PLAY RECAPがfailed=0で、APIサーバーとkubeletがどちらもv1.36.4で、/etc/kubernetes/kubeadm-config.yamlのkubernetesVersionもv1.36.4である必要があります。
  5. ステップ2と同じフィールドで、ファイルを書いてください(書き込み先: /root/ks/upgrade/after.json)。そして、same_node(ノードのUIDがそのままか)、web_pods_recreated(webのPodのUIDがすべて変わったか)、etcd_changed(etcdのバージョンが変わったか)、coredns_changed(corednsのイメージが変わったか)を、ブール値で書いてください(書き込み先: /root/ks/upgrade/diff.json)。
  6. /root/ks/logs/upgrade.logから、upgrade/pre-upgradeとpost-upgradeロールのタスクを探して、次のフィールドを書いてください(書き込み先: /root/ks/upgrade/drain.json)。cordon_changed、drain_changed、uncordon_changed(それぞれ「Cordon node」「Drain node」「Uncordon node」のタスクがchangedを出したか、ブール値)、drain_sec(「Drain node」のタスクにかかった秒、TASKS RECAPの値を四捨五入した整数、一覧になければ0)、node_schedulable_now(現在のノードのspec.unschedulableが真ではないか、ブール値)です。
  7. 次のフィールドを書いてください(書き込み先: /root/ks/upgrade/next.json)。running(現在のAPIサーバーのバージョン)、max_supported(このkubesprayのバージョンがインストールできる最も高いKubernetesのバージョン、チェックサム一覧の最初のキー)、needs_new_kubespray(次のマイナーバージョンに上げるには、kubesprayを次のタグに先に上げる必要があるか、ブール値)です。

参考

1つ下(1.35.8)で構築する

/opt/ks/kubesprayでansible-playbook -i /root/ks/inventory/lab/inventory.ini cluster.ymlを実行して、出力の全体を残してください(約7分、保存先: /root/ks/logs/cluster-1.log)。インベントリのkube_versionは1.35.8です。終わったら、APIサーバーのバージョンがv1.35.8である必要があります。

アップグレードを練習するには、1つ下のバージョンが先にある必要があります。このkubesprayのバージョンのデフォルト値は1.36.4なので、インベントリに1.35.8を書いておかないと、最初から1.36.4がインストールされます。

上げる前の写真

defaultネームスペースにDeploymentweb(イメージはregistry.k8s.io/e2e-test-images/agnhost:2.59、引数はnetexec --http-port=8080、レプリカ2)を作成して、2つのPodがReadyになるようにしてください。そのあと次のフィールドを書いてください(書き込み先: /root/ks/upgrade/before.json)。server_version、kubelet_version、etcd_version(etcd --versionのバージョン)、coredns_image(coredns Deploymentのイメージ)、node_uid、web_pod_uids(webのPodのUIDをソートした配列)です。

アップグレードの後に何が変わって何がそのままかを語るには、上げる前の値を先に残す必要があります。etcdはPodではなくホストのサービスなので、kubectlではなくバイナリでバージョンを尋ねます。採点ツールは、この記録がアップグレードより先に書かれたかどうかを、バージョン番号で照合します。

バージョンはインベントリで上げる

kube_versionを1.36.4に変更してください(対象: /root/ks/inventory/lab/group_vars/k8s_cluster/k8s-cluster.yml)。-eで渡さずに、ファイルを直します。ansible-inventory --host node1が1.36.4を返す必要があります。

kubesprayのアップグレードのドキュメントは、インベントリにバージョンを書いてあるなら、upgrade-cluster.ymlを実行する前にその値を直すよう求めています。-eだけで上げると、インベントリには古いバージョンが残り、次に誰かがそのインベントリでcluster.ymlを実行すると、クラスターとインベントリが食い違った状態から始まります。

upgrade-cluster.yml

/opt/ks/kubesprayでansible-playbook -i /root/ks/inventory/lab/inventory.ini upgrade-cluster.ymlを実行して、出力の全体を残してください(約6分、保存先: /root/ks/logs/upgrade.log)。PLAY RECAPがfailed=0で、APIサーバーとkubeletがどちらもv1.36.4で、/etc/kubernetes/kubeadm-config.yamlのkubernetesVersionもv1.36.4である必要があります。

upgrade-cluster.ymlは、すでにあるクラスターにだけ使うプレイブックで、ノードごとにcordon → drain → 更新 → uncordonを行います。ノードが1台だと、drainする間にPodの行き先がなく、しばらくPendingになります。1台構成のクラスターのアップグレードは、そのまま中断時間だという意味です。待っている間に、ログのPLAYの見出しを追ってみてください。

上げた後の写真

ステップ2と同じフィールドで、ファイルを書いてください(書き込み先: /root/ks/upgrade/after.json)。そして、same_node(ノードのUIDがそのままか)、web_pods_recreated(webのPodのUIDがすべて変わったか)、etcd_changed(etcdのバージョンが変わったか)、coredns_changed(corednsのイメージが変わったか)を、ブール値で書いてください(書き込み先: /root/ks/upgrade/diff.json)。

Kubernetesを1つ上げても、すべてのコンポーネントが一緒に上がるわけではありません。kubesprayは、etcdとCoreDNSのバージョンを、Kubernetesのマイナーバージョンごとの表(etcd_supported_versions、coredns_supported_versions)で選びます。2つのバージョンが表で同じ値を指していれば、そのまま残ります。

ログで読み取るdrain

/root/ks/logs/upgrade.logから、upgrade/pre-upgradeとpost-upgradeロールのタスクを探して、次のフィールドを書いてください(書き込み先: /root/ks/upgrade/drain.json)。cordon_changed、drain_changed、uncordon_changed(それぞれ「Cordon node」「Drain node」「Uncordon node」のタスクがchangedを出したか、ブール値)、drain_sec(「Drain node」のタスクにかかった秒、TASKS RECAPの値を四捨五入した整数、一覧になければ0)、node_schedulable_now(現在のノードのspec.unschedulableが真ではないか、ブール値)です。

profile_tasksのTASKS RECAPの一覧には、時間のかかったタスクだけが出ます。drainが一覧にないなら、すぐに終わったという意味です。アップグレードが途中で失敗すると、ノードがcordonされたまま残ることがあるので、終わった後にunschedulableを確認する習慣が必要です。

次の1つはどこから来るのか

次のフィールドを書いてください(書き込み先: /root/ks/upgrade/next.json)。running(現在のAPIサーバーのバージョン)、max_supported(このkubesprayのバージョンがインストールできる最も高いKubernetesのバージョン、チェックサム一覧の最初のキー)、needs_new_kubespray(次のマイナーバージョンに上げるには、kubesprayを次のタグに先に上げる必要があるか、ブール値)です。

kubesprayは、タグごとに受け入れるバージョンをチェックサムで固定します。現在のバージョンが一覧の一番上なら、このkubesprayではこれ以上は上げられず、ドキュメントの「複数回のアップグレード」の節のとおり、kubesprayのタグを1つずつ上げてから、upgrade-cluster.ymlを実行する必要があります。タグを飛ばすことは、サポートされていません。