TT Lab
开始
学习 学习路径 课程

用 Kubespray 与 Terraform 搭建集群

从 1.35.8 到 1.36.4 — 同一节点,新版本

在 TT Lab 中继续学习

目标

用 kubespray v2.32.0 搭建 Kubernetes 1.35.8 集群并部署工作负载,然后把 inventory 中的版本改为 1.36.4, 用 upgrade-cluster.yml 向上升一格。把升级前后拍成对照照片,用证据说明哪些变了、哪些保持不变。

为什么重要

Kubernetes 大约每四个月发布一个次版本,过了支持期就不再提供安全补丁。所以升级不是做一次就完的事,而是定期工作。 kubespray 把升级与安装一样,当作声明来处理——修改 inventory 中的版本,然后运行 playbook。不过有顺序:不跳过次版本, 不跳过 kubespray 标签,对每个节点执行 cordon → drain → 升级 → uncordon。如果只有一个节点,drain 期间工作负载会停止,你也会在本实验中亲眼看到。 安装和升级加起来要等待约 13 分钟。如果时间不够,请延长会话。

步骤

  1. 在 /opt/ks/kubespray 中运行 ansible-playbook -i /root/ks/inventory/lab/inventory.ini cluster.yml,把完整输出保存到 /root/ks/logs/cluster-1.log(约 7 分钟)。inventory 的 kube_version 是 1.35.8。结束后,API 服务器的版本必须是 v1.35.8。
  2. 在 default 命名空间中创建 Deployment web(镜像 registry.k8s.io/e2e-test-images/agnhost:2.59,参数 netexec --http-port=8080,副本数 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. 把 /root/ks/inventory/lab/group_vars/k8s_cluster/k8s-cluster.yml 中的 kube_version 改为 1.36.4。不要用 -e 传入,而是修改文件。ansible-inventory --host node1 必须返回 1.36.4。
  4. 在 /opt/ks/kubespray 中运行 ansible-playbook -i /root/ks/inventory/lab/inventory.ini upgrade-cluster.yml,把完整输出保存到 /root/ks/logs/upgrade.log(约 6 分钟)。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。然后在 /root/ks/upgrade/diff.json 中以布尔值写入 same_node(节点 UID 是否保持不变)、web_pods_recreated(web Pod 的 UID 是否全部改变了)、etcd_changed(etcd 版本是否改变了)、coredns_changed(coredns 镜像是否改变了)。
  6. 在 /root/ks/logs/upgrade.log 中找出 upgrade/pre-upgrade 和 post-upgrade role 的任务,在 /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.35.8)

在 /opt/ks/kubespray 中运行 ansible-playbook -i /root/ks/inventory/lab/inventory.ini cluster.yml,把完整输出保存到 /root/ks/logs/cluster-1.log(约 7 分钟)。inventory 的 kube_version 是 1.35.8。结束后,API 服务器的版本必须是 v1.35.8。

要练习升级,必须先有低一格的版本。这个 kubespray 版本的默认值是 1.36.4,所以如果不在 inventory 中写下 1.35.8,一开始就会安装 1.36.4。

升级之前的对照照片

在 default 命名空间中创建 Deployment web(镜像 registry.k8s.io/e2e-test-images/agnhost:2.59,参数 netexec --http-port=8080,副本数 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,而是用二进制文件来询问版本。评分器会通过版本号来核对这份记录是否写在升级之前。

版本要在 inventory 中升级

把 /root/ks/inventory/lab/group_vars/k8s_cluster/k8s-cluster.yml 中的 kube_version 改为 1.36.4。不要用 -e 传入,而是修改文件。ansible-inventory --host node1 必须返回 1.36.4。

kubespray 升级文档要求,如果在 inventory 中写了版本,就在运行 upgrade-cluster.yml 之前修改这个值。如果只用 -e 升级,inventory 中仍然保留旧版本,下次有人用这个 inventory 运行 cluster.yml 时,就会从集群与 inventory 不一致的状态开始。

upgrade-cluster.yml

在 /opt/ks/kubespray 中运行 ansible-playbook -i /root/ks/inventory/lab/inventory.ini upgrade-cluster.yml,把完整输出保存到 /root/ks/logs/upgrade.log(约 6 分钟)。PLAY RECAP 必须是 failed=0,API 服务器和 kubelet 都必须是 v1.36.4,/etc/kubernetes/kubeadm-config.yaml 中的 kubernetesVersion 也必须是 v1.36.4。

upgrade-cluster.yml 是只用于已经存在的集群的 playbook,对每个节点执行 cordon → drain → 升级 → uncordon。如果只有一个节点,在 drain 期间 Pod 无处可去,会暂时处于 Pending——这意味着单节点集群的升级就是停机时间。等待期间,请跟着日志中的 PLAY 标题看一看。

升级之后的对照照片

用与第 2 步相同的字段写入 /root/ks/upgrade/after.json。然后在 /root/ks/upgrade/diff.json 中以布尔值写入 same_node(节点 UID 是否保持不变)、web_pods_recreated(web Pod 的 UID 是否全部改变了)、etcd_changed(etcd 版本是否改变了)、coredns_changed(coredns 镜像是否改变了)。

把 Kubernetes 向上升一格,并不意味着所有组件都会跟着升级。kubespray 按 Kubernetes 次版本对应的表(etcd_supported_versions、coredns_supported_versions)来选择 etcd 和 CoreDNS 的版本。如果两个版本在表中指向同一个值,就保持不变。

通过日志读取 drain

在 /root/ks/logs/upgrade.log 中找出 upgrade/pre-upgrade 和 post-upgrade role 的任务,在 /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 的习惯。

下一格从哪里来

在 /root/ks/upgrade/next.json 中写入 running(当前 API 服务器的版本)、max_supported(这个 kubespray 版本能够安装的最高 Kubernetes 版本,校验和列表的第一个键)、needs_new_kubespray(要升级到下一个次版本,是否必须先把 kubespray 升级到下一个标签,布尔值)。

kubespray 在每个标签中用校验和固定其所接受的版本。如果当前版本已经位于列表的最顶端,就无法再用这个 kubespray 继续升级,必须按照文档“多次升级”一节,把 kubespray 标签一格一格地升级,然后运行 upgrade-cluster.yml。不支持跳过标签。