管理裸金属节点

本文档介绍如何在裸金属 provider 上扩缩工作节点、替换指定机器,以及恢复故障节点。节点管理使用 Cluster API Machine 资源,并通过 MachineDeployment 进行编排;provider 会将每个 Machine 绑定到池中的一个 MachineInventory,并通过 clean / reprovision 计划驱动主机。

INFO

如需升级节点的 Kubernetes 版本,请参阅在裸金属上升级 Kubernetes。

先决条件

WARNING

重要先决条件

  • 控制平面必须已在运行。请参阅创建集群。
  • 工作节点 MachineInventoryPool 必须包含至少与目标副本数相同的 Available 库存项,此外还需满足滚动更新策略所需的容量余量。
  • 目标 Machine.spec.version 必须是 elemental-image-catalog ConfigMap 中的一个键。
  • 任何 spec.storage.volumes[] 非空的库存项,在计为 Available 之前,都必须已报告 status.storage.phase=Prepared 和 StoragePrepared=True。在将新注册的存储管理库存项添加到工作节点池之前,请遵循管理裸金属主机上的数据磁盘中的说明。
  • 如需管理 global 集群本身的节点,必须先在 global 上安装 provider;请参阅管理 Alauda OS 集群上的节点。
INFO

配置指南

使用本文档中的配置时:

  • 仅修改 <> 括号内的值。
  • 将占位值替换为适用于您环境的设置。
  • 除非有明确要求,否则保留所有其他默认配置。

概述

组成工作节点组的四种资源:

  1. MachineInventoryPool(<cluster-name>-worker-pool)— 允许使用的 MachineInventory 名称集合。已在创建集群 → 第 2 步中创建。
  2. BaremetalMachineTemplate(<cluster-name>-worker-template)— 引用工作节点池。如需将工作节点移至其他池,请参阅将工作节点移至其他池。
  3. KubeadmConfigTemplate(<cluster-name>-worker-bootstrap)— kubeadm join 的 cloud-init user-data。裸金属 provider 会在重新配置时规范化此用户数据(主机名、provider-id、criSocket);operator 不应预先填充这些字段。
  4. MachineDeployment — 控制副本数、版本和滚动更新策略。

托管数据磁盘不属于 BaremetalMachineTemplate。其声明和保留的数据属于每个长期运行的 MachineInventory,因此,除非 operator 对存储声明进行标准化并验证,否则同一工作节点池中的两个成员可能会公开不同的主机本地数据集。托管存储需在未分配且处于非活动状态的 MachineInventory 上单独更改;请参阅管理裸金属主机上的数据磁盘。

如需使用 YAML 添加另一个工作节点池,请按照集群创建页面中的第 4 步:部署工作节点操作。


节点管理操作

扩缩工作节点

添加工作节点

用例:扩充集群容量。

先决条件:

  • 工作节点池中有足够的 Available 库存项。如果没有,请注册其他主机(启动 SeedImage ISO 并确认新的 MachineInventory 对象),准备好任何托管存储,并将它们添加到 MachineInventoryPool.spec.machineInventories[]。

操作步骤:

  1. 检查当前状态

    kubectl -n cpaas-system get machines.cluster.x-k8s.io \
      -l cluster.x-k8s.io/deployment-name=<cluster-name>-workers
    kubectl -n cpaas-system get machineinventorypools.infrastructure.cluster.x-k8s.io \
      <cluster-name>-worker-pool

    确认 MachineInventoryPool.status.available 足以满足计划增加的数量。

  2. 需要更多库存项时扩展工作节点池

    kubectl -n cpaas-system edit machineinventorypool <cluster-name>-worker-pool

    添加新的 MachineInventory 名称——这些名称对应的库存项必须已注册且处于 Ready 状态。具有托管卷的库存项还必须处于 Prepared 状态;否则,它们会增加 status.total,但仍无法分配。保存并退出,然后确认 status.available 按预期增加。

  3. 扩展 MachineDeployment

    kubectl -n cpaas-system patch machinedeployment <cluster-name>-workers \
      --type='json' -p='[{"op":"replace","path":"/spec/replicas","value":<new-replica-count>}]'
  4. 监控

    kubectl -n cpaas-system get baremetalmachines.infrastructure.cluster.x-k8s.io -w
    kubectl get nodes                # workload cluster

    新的 BaremetalMachine 对象会推进 Pending → Allocated → Reprovisioning → Running;随着新节点绑定,池的 available 计数器会递减。

移除工作节点

支持两种策略,其形式与上游 Cluster API 合约相同:

策略适用情况
随机移除可移除任意节点——例如,临时缩减容量。
定向移除需要释放特定物理主机(硬件维护、更换、IP 回收)。
INFO

库存项回收

clean 计划会停止 kubelet、停用已声明的存储挂载、清除 CRI 工作负载并停止 containerd。它不会擦除托管文件系统、Kubernetes 持久化目录或重置 OS——只有在之后为新的 BaremetalMachine 选择相同或不同的库存项并运行 reprovision 计划时,才会清理 OS。在此之前,库存项会返回 Available,并可再次分配。删除 Machine 执行的是 Deactivate,而不是存储 Release,因此该库存项上的存储声明、文件系统 UUID 和数据都会保留。

随机移除
kubectl -n cpaas-system patch machinedeployment <cluster-name>-workers \
  --type='json' -p='[{"op":"replace","path":"/spec/replicas","value":<new-replica-count>}]'

CAPI 会按照其标准顺序选择要删除的机器。每个选中的 BaremetalMachine 都会进入 Preparing,provider 会写入一个 clean 计划;当计划报告 Applied 后,库存项会返回 Available。

定向移除
  1. 识别机器

    kubectl -n cpaas-system get machines.cluster.x-k8s.io \
      -l cluster.x-k8s.io/deployment-name=<cluster-name>-workers
  2. 为目标机器添加注释

    kubectl -n cpaas-system patch machine <machine-name> \
      --type='merge' -p='{"metadata":{"annotations":{"cluster.x-k8s.io/delete-machine":"true"}}}'

    对要移除的每台机器重复此操作。

  3. 按已添加注释的机器数量精确缩容

    kubectl -n cpaas-system patch machinedeployment <cluster-name>-workers \
      --type='json' -p='[{"op":"replace","path":"/spec/replicas","value":<new-replica-count>}]'

    缩容数量少于目标数量会使部分已添加注释的机器继续保留;缩容数量多于目标数量,则会让其他随机机器也执行 clean 计划。

  4. 验证清理结果

    kubectl -n cpaas-system get baremetalmachines.infrastructure.cluster.x-k8s.io
    kubectl -n cpaas-system get machineinventories.elemental.cattle.io <inventory-name> -o yaml

    已释放的库存项必须显示 baremetal.alauda.io/allocation-state=Available,baremetal.alauda.io/owner-* 注释必须已清除,池注释则必须保留。MachineInventory 本身不会被删除。如果它声明了托管卷,则必须返回 status.storage.phase=Prepared,并带有 StorageActive=False/Inactive;其业务挂载路径必须处于非活动状态,同时文件系统 UUID 和数据保持不变。

替换单个故障节点

如果 BaremetalMachine 进入 Failed,最安全的恢复方法是删除故障的 Machine。CAPI 会立即创建替代的 Machine(因为 replicas 未更改),裸金属 provider 会从同一池中选取一个 Available 库存项。替代节点通常会使用不同的 MachineInventory;provider 不保证会重新选中刚释放的库存项。主机本地的托管数据不会随替代 Machine 一同迁移。如果应用必须重用特定库存项中的数据,请使用专用池或经过有意排序的池,并在依赖这些数据之前验证 BaremetalMachine.status.machineInventoryRef。

kubectl -n cpaas-system delete machine <machine-name>
kubectl -n cpaas-system get baremetalmachines.infrastructure.cluster.x-k8s.io -w

请单独调查原始故障:读取运行计划的主机上的 BaremetalMachine.status.conditions、MachineInventory.status.plan.state,以及失败计划 secret 中的 failed-output 键。常见根本原因记录在下文的常见故障模式部分。

将工作节点移至其他池

BaremetalMachineTemplate 仅包含池引用——模板中没有 CPU、内存或磁盘声明。

用例:新主机已注册并放入新的 MachineInventoryPool,且需要将节点迁移到这些主机上。创建一个指向新池的新 BaremetalMachineTemplate,然后将 MachineDeployment 指向它。节点将逐个替换。

开始之前:

  • 目标池与模板位于同一命名空间中。

  • 目标池中的 Available 库存项数量至少与 MachineDeployment 的副本数相同。每个迁移的节点会使用目标池中的一台主机;旧节点释放的主机会返回旧池,不会加入目标池。通过 status.available 查看数量:

    kubectl -n cpaas-system get machineinventorypools.infrastructure.cluster.x-k8s.io <target-pool-name>
  • 新主机满足与当前主机相同的先决条件:已注册且处于 Ready 状态;如果使用托管数据磁盘,则已准备好;镜像目录中包含目标 Kubernetes 版本和 CPU 架构;并且存在 CNI 网络设备。请参阅确认工作节点池容量。

  • 在迁移完成之前,请保留旧模板和旧池。

操作步骤:

  1. 创建新的 BaremetalMachineTemplate,并使用引用目标池的新 metadata.name。请使用配置工作节点 BaremetalMachineTemplate中的格式。

  2. 应用新模板。

  3. 修补 MachineDeployment:

    kubectl -n cpaas-system patch machinedeployment <cluster-name>-workers \
      --type='merge' \
      -p='{"spec":{"template":{"spec":{"infrastructureRef":{"name":"<new-template-name>"}}}}}'
  4. 观察滚动替换(maxSurge: 0,每次一个节点)以及目标池的 status.available:

    kubectl -n cpaas-system get baremetalmachines.infrastructure.cluster.x-k8s.io -w
    kubectl -n cpaas-system get machineinventorypools.infrastructure.cluster.x-k8s.io <target-pool-name>

预期情况:

  • 旧节点会先被删除,然后才创建替代节点。如果目标池的主机耗尽,节点池会暂时少一个节点,直到添加主机为止。
  • 节点名称和 IP 地址会发生变化。
  • 节点本地数据不会迁移。托管数据磁盘上的数据仍保留在旧主机上,并绑定到其 MachineInventory,不会出现在新主机上。请在新主机上单独声明存储;请参阅管理裸金属主机上的数据磁盘。

如果迁移因没有空闲主机而停滞(BaremetalMachine 显示 InventoryAllocated=False / Reason=PoolExhausted),请向目标池添加 Available 主机;系统会自动选取这些主机。也可以通过将 infrastructureRef.name 修补回旧模板来回滚。已迁移的节点会逐个再次替换,因此旧池必须仍有足够的 Available 主机。

如需迁移控制平面节点,请使用相同的步骤,并改为修补 KubeadmControlPlane.spec.machineTemplate.infrastructureRef.name。节点会逐个替换。此外:

  • maxSurge: 0 要求 replicas 至少为 3。
  • 每次替换期间只有两个 etcd 成员运行。只有在控制平面运行正常时才开始,并确保目标池中有 3 台 Available 主机处于就绪状态。
  • 新主机必须与控制平面 VIP 位于同一二层网络中。

迁移完成后,可以删除旧模板和旧池。旧节点释放的主机会留在旧池中。

更新引导模板

直接修改现有 KubeadmConfigTemplate 不会滚动更新现有机器;只有新创建的机器才会应用更改。

如需滚动应用引导配置更改:

  1. 导出现有模板:

    kubectl -n cpaas-system get kubeadmconfigtemplate <cluster-name>-worker-bootstrap -o yaml \
      > new-worker-bootstrap.yaml
  2. 更改 metadata.name,移除由服务器生成的字段(resourceVersion、uid、creationTimestamp、managedFields、kubectl.kubernetes.io/last-applied-configuration)以及整个 status,然后编辑所需字段。对于 Kubernetes 1.35 或更高版本,请将必需的 kubelet 修补设置添加到 /etc/kubernetes/patches/kubeletconfiguration0+strategic.json。

  3. 应用新模板:

    kubectl apply -f new-worker-bootstrap.yaml
  4. 修补 MachineDeployment,使其引用新模板:

    kubectl -n cpaas-system patch machinedeployment <cluster-name>-workers \
      --type='merge' \
      -p='{"spec":{"template":{"spec":{"bootstrap":{"configRef":{"name":"<new-template-name>"}}}}}}'

    这会触发滚动替换。


Pool 和 Inventory 可观测性

Provider 在每个 MachineInventory 上维护的注解,是了解“此主机当前的用途”的权威来源:

注解值含义
baremetal.alauda.io/poolPool 名称此 Inventory 所属的 Pool。
baremetal.alauda.io/allocation-stateAvailable / Allocated / Preparing / Reprovisioning / Unavailable从 Provider 的角度看所处的生命周期阶段。
baremetal.alauda.io/owner-clusterCluster 名称当前正在使用此 Inventory 的 Cluster(释放时会清除)。
baremetal.alauda.io/owner-machineMachine 名称所属的 Cluster API Machine。
baremetal.alauda.io/owner-baremetalmachineBaremetalMachine 名称所属的 Provider machine。

每个 Inventory 的默认 plan secret 也包含 baremetal.alauda.io/plan.type。正常的节点生命周期使用 clean 或 reprovision;Inventory 存储协调还会使用 storage-prepare 和 storage-release。诊断存储问题时,请结合计划类型检查 MachineInventory.status.storage.conditions 和 .operation。

常见故障模式

场景预期状态检查项
Pool 不存在BaremetalMachine 保持为 Pending、InventoryAllocated=False / Reason=PoolMissingBaremetalMachineTemplate.spec.template.spec.machineInventoryPoolRef.name 和命名空间
Pool 资源耗尽BaremetalMachine 保持为 Pending、InventoryAllocated=False / Reason=PoolExhaustedMachineInventoryPool.status.available;Inventory 所有权注解
成员缺失MachineInventoryPool.MembersValid=False / Ready=FalsePool 的 status.unavailable、失败状态中的消息
Inventory 未 Ready计入 status.unavailableMachineInventory.status.conditions[Ready]、plan secret 是否存在
plan secret 缺失Inventory 不符合分配条件MachineInventory.status.plan.secretRef、被引用的 Secret 是否存在
存储未准备Inventory 不计为 Available;StoragePrepared=FalseMachineInventory.status.storage、status.observedStorage 的新鲜度和内容,以及 storage-prepare plan 输出
Bootstrap secret 缺失BootstrapReady=False / Reason=BootstrapWaitingMachine.spec.bootstrap.dataSecretName
Catalog 未命中BaremetalMachine Failed、ImageResolved=False / Reason=ImageCatalogMiss,未写入 planelemental-image-catalog keys
Registry 注解缺失ImageResolved=False / Reason=ImageRegistryMissingCluster.metadata.annotations["cpaas.io/registry-address"]
重新置备 plan 失败BaremetalMachine Failed,Inventory 标记为 Unavailableplan secret failed-output;主机串行控制台;可访问的平台 Registry
Managed volume 激活失败BaremetalMachine StorageReady=False;必需 volume 导致节点就绪状态受阻稳定的设备标识、文件系统 UUID、挂载单元、重启后的最新观测结果,以及 plan failed-output
Clean 或 Deactivate 失败finalizer 阻止删除;Inventory 标记为 Unavailableclean plan 输出、主机挂载,以及 MachineInventory.status.storage.operation

有关完整的 operator 侧状态机参考,请参阅 Provider Overview → BaremetalMachine。


后续步骤