裸金属上的集群升级
本指南说明如何完成裸金属集群升级流程的第 2 阶段。在升级 Kubernetes 之前,请先完成 Upgrading Clusters 中描述的 Distribution Version 升级。
本页面在完整 ACP 升级流程中的位置
本页面仅涵盖升级中的 Kubernetes 步骤。完整的 ACP 升级流程——包括升级制品同步、通过 CVO 升级 ACP Core、Aligned plugin 升级,以及从 Marketplace 升级 Agnostic plugin——已在 ACP 产品文档中说明。在开始本页的 Kubernetes 步骤之前,请先完成这些步骤:
当同一个集群运行在物理主机不可变操作系统上时,请使用本页面,因为裸金属上的 Kubernetes 步骤会用新的 elemental upgrade 镜像替换每个节点,而不是就地升级二进制文件。
目录
关键注意事项升级顺序Provider 升级期间的存储兼容性前提条件更新镜像目录在 control plane 之前升级 Kube-OVN升级 control plane升级 worker跨版本升级从失败的 Phase 2 升级中恢复验证故障排查其他资源关键注意事项
裸金属升级会替换每个节点——不会在现有操作系统上执行 kubeadm upgrade。其机制如下:
- CAPI 会根据滚动升级策略删除一个
Machine。 - provider 将
clean计划写入 inventory 的 plan secret。 - 主机停止 kubelet,停用所有受管数据挂载,清理 CRI workload,停止 containerd,然后在同一 pool 中回到
Available。 - CAPI 创建一个替代的
Machine。 - provider 从同一 pool 中选择一个
Available的 inventory,基于elemental-image-catalog解析新的 Kubernetes 版本,并写入reprovision计划。 - 主机会暂存受管卷激活,运行
cloud-init clean→elemental upgrade --system <new-image>→ 重启。initramfs会清除 Kubernetes 持久状态;受管挂载单元会在 kubelet 之前启动,而 cloud-init 会重新执行并针对新的 control plane 运行kubeadm init/kubeadm join。
运维人员在开始前必须理解两个结构性后果:
- Kubernetes 管理的系统状态不会保留。
/var/lib/kubelet、/var/lib/containerd、/var/lib/etcd和/etc/kubernetes会在每次 reprovision 的 initramfs 清理步骤中被清除。Storage v2 不允许这些受保护路径作为受管数据挂载。 - 声明的数据卷可以保留在 inventory 上。 clean 计划会停用这些卷,但不会擦除其文件系统,reprovision 会在 kubelet 之前激活所选 inventory 的已准备卷。这是主机本地保留,不是备份或数据迁移机制。
- 同一个
MachineInventory可能不会被再次选中。 provider 不保证通过clean计划释放的 inventory 会被重新分配给替代的Machine;数据不会自动随替代对象迁移。当maxSurge=0时,替换以先删后加的方式执行(旧节点与新节点不会重叠),因此 pool 容量只需满足期望的副本数即可——滚动过程中旧节点和新节点不会同时存在。
升级顺序
按照以下顺序升级裸金属集群:
- (前提条件) 升级
global集群上的 ACP 平台。这会将裸金属 provider、elemental-operator以及相关的 CAPI 组件升级到能够理解新 schema 的版本。只有在管理侧控制器完成滚动并进入 Ready 之后,才触发业务集群升级。 - 在业务集群上升级 Distribution Version(Aligned Extensions)。参见 Upgrading Distribution Version。
- 确认目标 Kubernetes 版本已存在于
elemental-image-catalog中(并且对于未来任何主机重新注册,匹配的-iso仓库可用)。 - 将 Kube-OVN 升级到目标 ACP 版本所需的 chart 版本,并等待
AppRelease达到Success。 - 升级 control plane 的 Kubernetes 版本(一次替换一个 control-plane 节点)。
- 将 worker 节点升级到目标 Kubernetes 版本(在
maxUnavailable预算内替换所有 worker 节点)。
Cluster API 会编排滚动替换。
跳过步骤 1 存在两种失败模式:旧 provider 会静默忽略新的 schema 字段;或者在滚动过程中切换 controller 镜像会中断 plan secret 状态机。在触碰业务工作负载滚动之前,务必先完成管理侧升级。
Provider 升级期间的存储兼容性
如果某个现有集群是在受管存储引入之前创建的,只要 MachineInventory.spec.storage 仍然缺失或其值为 volumes: [],它仍然兼容。在这种未受管模式下,storage controller 不会执行任何磁盘操作,也不会仅因为 management-side provider 已升级就重写正在运行的 Machine 的 plan。
这种兼容性不意味着可以在所有旧主机上就地启用受管存储:
- 仅在
global集群上升级 provider 和elemental-operator,不会在较旧的主机 OS 上安装elemental-storage-observer.service或早期引导存储集成。 - 在此类主机上保持
spec.storage为空。若要稍后启用受管存储,请重新安装、重置或用经批准且具备 observer 能力的镜像替换该主机,然后在 inventory 未分配时验证 observer 服务以及新的status.observedStorage报告。 - 只有在满足这些主机镜像前提条件后,才配置并准备受管卷。不要向正在运行或已分配的 inventory 添加非空的存储声明。
有关准备和验证操作步骤,请参见 Manage Data Disks on Bare-Metal Hosts。
前提条件
开始之前,请确认满足以下所有前提条件:
- Distribution Version 升级已完成。
- 已安装的 Bare Metal provider 版本为
v0.0.1或更高,并且其AppRelease报告的 requested revision 与 installed revision 相同,且phase=Success。 - control plane 可通过现有的
<control-plane-vip>:<control-plane-port>访问。 - 当前所有节点均健康且处于
Ready状态。 - 在更改 Kube-OVN 或 reprovision 任何节点之前,请使用 ACP Cluster Enhancer 创建当前的按需 etcd 备份。验证最新的
status.records条目报告result: Success,记录其backupTimestamp和fileName,并确认对应的备份归档存在,且如果任何 control-plane 节点被 reprovision 或变得不可用时仍可检索。 - 目标 Kubernetes 版本是
elemental-image-catalog中的一个 key。如果不是,请在开始前添加它(参见 更新镜像目录)。 - 已从 OS Support Matrix 中对应的 ACP 行读取目标 kube-ovn (chart) 版本。
BaremetalCluster.spec.networkType为kube-ovn;provider 会跳过任何其他值的 Kube-OVN reconciliation。- 平台 registry 可从集群中的每台主机访问。
KubeadmControlPlane.spec.rolloutStrategy.rollingUpdate.maxSurge = 0和MachineDeployment.spec.strategy.rollingUpdate.maxSurge = 0均已设置——裸金属不会对物理主机进行超额预配。- 相关 pool 具备足够容量,能够一次替换一个节点而不低于期望副本数。
- 每个带有非空存储声明的 inventory 都报告
StoragePrepared=True,并且当前所有已分配的 inventory 都报告StorageActive=True。在滚动前记录每个BaremetalMachine.status.machineInventoryRef以及受管文件系统 UUID,以便在数据未随 Machine 迁移时能够检测到选中了不同的 inventory。
默认位于 /var/cpaas/backup 下的本地归档可用于恢复;不要求使用 S3 兼容存储。不过,裸金属替换可能会使原始节点本地副本不可用,并且不保证替代的 Machine 会使用同一个 MachineInventory。如果你的恢复设计无法保证在节点替换或故障后仍能访问本地归档,请在开始第 2 阶段之前,将一份节点外副本保存在 S3 兼容存储或其他节点外的安全位置。
更新镜像目录
elemental-image-catalog 是将某个 Kubernetes 版本引入裸金属 provider 的资源。
在大多数升级中,你不需要手动编辑这个 ConfigMap。裸金属 provider plugin 会在 Distribution Version 升级期间重新应用时,用新 distribution 随附的 Kubernetes 版本重新渲染 elemental-image-catalog(第 1 阶段)。你的任务通常只是验证目标版本是否存在(参见下面的验证步骤)。以下两个选项仅在技术支持提供了经批准的带外镜像引用时才需要。
选项 A — 添加 chart override。 在 provider.imageCatalog.images 下追加新版本(使用 global.registry.address 作为 registry):
重新应用裸金属 provider plugin。chart 会重新渲染 ConfigMap;provider 的进程内 watch 会在不重启的情况下热加载缓存。
选项 B — 直接 patch ConfigMap。 仅当需要将经批准的镜像引用直接固定在目录中时才使用此方式:
无论使用哪种方式,在继续之前都要验证:
该 key 必须包含前导 v(例如 v1.34.5)。如果在 CAPI 创建替代 Machine 时该 key 缺失,生成的 BaremetalMachine 会进入 Failed,其 ImageResolved=False / Reason=ImageCatalogMiss,并且不会写入 reprovision 计划——稍后添加该 key 会自动重新触发 reconciliation。
当新版本对应一个新的 Alauda OS 发行版时,请从 Alauda technical support 获取匹配的 base-image 和 base-image-iso 引用。裸金属 provider 使用 base-image 进行 reprovision,不会自动重建 SeedImages。在未来进行主机接入之前,请使用受支持的 base-image-iso 引用刷新 MachineRegistration / SeedImage。不要从一个镜像引用推导另一个,也不要用独立构建的镜像替代。
在 control plane 之前升级 Kube-OVN
请遵循 在 control plane 之前升级 Kube-OVN 中的 Bare Metal v0.0.1+ 流程。本档没有更早的受支持 provider 流程。
该通用操作步骤会验证 BaremetalCluster.spec.networkType,更新 CAPI Cluster 注解,让 provider 对完整的 chart 源和规范进行 reconciliation,并检查 chart 名称、requested revision、installed revision、phase 和 conditions。不要手动 patch AppRelease source。
升级 control plane
在继续之前,请完成通用的 在 control plane 之前升级 Kube-OVN 操作步骤,并验证 cni-kube-ovn 已以目标 installed revision 运行且 phase=Success。
将 KubeadmControlPlane.spec.version patch 为新的 Kubernetes 版本。如果组件镜像标签是固定的(DNS、etcd),请在同一次编辑中更新它们:
spec.version← 目标 Kubernetes 版本(必须与elemental-image-catalog的某个 key 匹配)。spec.kubeadmConfigSpec.clusterConfiguration.dns.imageTag← 新发行版对应的 CoreDNS 镜像标签。spec.kubeadmConfigSpec.clusterConfiguration.etcd.local.imageTag← 新发行版对应的 etcd 镜像标签。- 当目标为 Kubernetes 1.35 或更高版本时,请在同一次编辑中按 Kubernetes 1.35 所需的 kubelet patch 的说明,更新
spec.kubeadmConfigSpec.files中的/etc/kubernetes/patches/kubeletconfiguration0+strategic.json。
仅进行 Kubernetes 升级时,裸金属 provider 不需要新的 BaremetalMachineTemplate:该 template 只携带 pool 引用,而升级镜像则通过 Machine.spec.version 经由目录解析。只有当你希望将 control plane 移动到不同的 pool 时,才需要新 template。
由于 maxSurge=0,Cluster API 会一次滚动一个 control-plane 节点:
每个节点上的预期顺序如下:
- CAPI 将一个旧
Machine标记为删除;对应的BaremetalMachine转入Preparing。 - provider 写入一个
clean计划;受管卷会被停用但不会被擦除,inventory 最终变为Available,其所有者注解被清除,存储状态回到Prepared。 - CAPI 创建一个新的
Machine(使用目标版本);同时创建一个新的BaremetalMachine。 - provider 从 control-plane pool 中分配一个
Available的 inventory,解析新镜像,并写入reprovision计划。 - 主机为所选 inventory 的已准备卷执行激活暂存,运行
elemental upgrade --system <new-image>,重启,在 kubelet 之前启动所需挂载单元,并kubeadm join到存活的 control plane。只有在所需存储处于 active 状态后,BaremetalMachine.status.phase才会变为Running。
重复步骤 1–5,直到所有 control-plane 节点都已替换完成。
在整个滚动过程中,alive 会持续管理 VIP。随着 control-plane 成员关系变化,裸金属 provider 会重新渲染 alive chart values(peer 列表和 ipvs.ips),并滚动静态 Pod 清单。
升级 worker
将每个 MachineDeployment.spec.template.spec.version patch 为新的 Kubernetes 版本。CAPI 会在 maxUnavailable 预算内替换 worker——裸金属 provider 会复用同一个 worker pool,并使用与 control plane 相同的镜像目录解析逻辑。
对于 Kubernetes 1.35 或更高版本,首先创建一个新的 worker KubeadmConfigTemplate,其中包含所需的 kubelet patch,然后在同一次 MachineDeployment 编辑中,将 spec.template.spec.bootstrap.configRef.name 与版本升级一起更新。下面的命令包含了该引用。对于不需要更改 bootstrap 的较早目标版本,请省略 bootstrap 对象。按照 更新 Bootstrap 模板 创建不可变模板。
监视:
worker 升级相较于 control plane 的可调项更少:MachineDeployment 上没有 clusterConfiguration 块,因此没有 DNS / etcd 标签需要更新。worker 节点上的 Kubernetes 组件版本会跟随新的基础镜像。
对于更早的版本,只有在发行版更改了 cloud-init 或 kubeletExtraArgs 等设置时,才需要变更 bootstrap template。
跨版本升级
Kubernetes control plane 必须按受支持的 minor 版本跳跃进行升级。请使用 Preparing for Cross-Version Upgrades 找出并预先准备每个中间 ACP 行。
对于每个中间行,以及最终目标行:
- 确保该行的 Kubernetes 版本存在于
elemental-image-catalog中。 - 将 Kube-OVN 升级到该行的 kube-ovn (chart) 版本,并等待
phase=Success。 - 将 control plane 升级到该行的 Kubernetes 版本,并等待所有 control-plane 节点都变为
Ready。 - 将每个 worker
MachineDeployment升级到相同的 Kubernetes 版本,并等待滚动完成后再开始下一次跳跃。
这些版本值始终来自 OS Support Matrix;本指南中的示例并非固定值。裸金属滚动策略已经对节点替换进行了串行化,因此跨版本升级不需要超出同 minor 升级所需的额外 pool 容量。
从失败的 Phase 2 升级中恢复
不要将 Kubernetes minor 降级视为普通回滚:
- 如果尚未创建任何目标版本的 control-plane
Machine,请使用 在 Stage-1 恢复期间恢复 Kube-OVN 恢复 Kube-OVN,然后恢复之前的KubeadmControlPlane和MachineDeployment清单值。 - 如果已有目标 minor 的 control-plane machine 加入集群,请停止进一步滚动,并在目标 minor 上向前修复。如果向前修复无法恢复集群健康,请按照 ACP etcd 恢复操作步骤 的说明,使用已验证的升级前备份恢复集群。不要将 Kubernetes、CoreDNS 或 etcd patch 回之前的 minor 版本。
恢复 etcd 是灾难恢复操作,不是升级前验证步骤。不要仅仅为了验证备份而在健康集群上执行恢复操作。
任何已完成 reprovision 计划的主机,都已经替换了其 OS 镜像并清除了 Kubernetes 管理的状态。修改版本字段不会重建此前的节点状态。
验证
滚动完成后:
cni-kube-ovn 的 AppRelease 应报告目标 installed revision 且 phase=Success。对于目标集群,所有当前的 BaremetalMachine 都应为 Running,所有 CAPI Machine 都应报告新的 spec.version,并且所有业务 Node 都应为 Ready 且使用新的 kubelet 版本。
对于每个当前的 BaremetalMachine,使用 INVENTORY 和 PLAN_SECRET 列来验证支撑正在运行节点的 inventory 和 plan:
每个引用的 MachineInventory 都应报告 Applied,每个引用的 plan Secret 都应报告 reprovision。此检查仅适用于当前 BaremetalMachine 对象所引用的 inventory。未参与滚动的备用 inventory 可能没有 reprovision 计划。已完成 clean 计划但未被选中作为替代 Machine 的 inventory 仍可能报告 clean;这两种情况都不意味着滚动尚未完成。
对于包含受管卷的 inventory,还要验证 status.storage.phase=Active、StoragePrepared=True、StorageActive=True 以及 BaremetalMachine.status.conditions[StorageReady]=True/AllVolumesReady。将其当前文件系统 UUID 与升级前记录进行比较。不同的 UUID 通常意味着选择了不同的 inventory;不能将其解释为原始数据已迁移。
MachineInventoryPool.status 应满足 available + allocated + preparing + reprovisioning + unavailable = total,且 preparing = reprovisioning = 0。当 pool 包含备用 inventory 时,available 仍可能大于 0;这些 inventory 不属于上面的 plan 验证范围。
故障排查
有关完整的 operator 侧状态机参考(每个 condition reason 和恢复操作),请参见 Provider 概览。