管理裸金属主机上的数据磁盘
使用 MachineInventory.spec.storage 管理已连接到裸金属主机的数据磁盘。存储声明属于长期存在的 MachineInventory,而不属于临时的 Cluster API Machine,因此当节点被移除时,provider 可以保留文件系统和数据,并在之后重新使用相同的 inventory。
此功能不会创建、连接、分离、迁移、备份或复制物理磁盘或 SAN LUN。它只管理在 spec.storage.volumes[] 中明确列出的设备。所有未列出的设备仍会被观测,但不会受到管理。
InitializeIfBlank 可以格式化磁盘
仅当你已确认目标 inventory 上准确的稳定设备 ID、确认该设备是可丢弃的空白数据磁盘,并且已独立备份任何重要数据后,才能使用 InitializeIfBlank。切勿从其他主机复制设备 ID,也不要将 /dev/sdX、/dev/vdX、/dev/nvmeXnY 或 /dev/mapper/mpathX 用作持久身份标识。
目录
可用性和升级边界存储生命周期前提条件步骤 1:验证 Inventory 和 Observer步骤 2:定义受管卷步骤 3:生成并应用原子补丁步骤 4:等待 Prepare 完成步骤 5:分配并验证激活步骤 6:缩减并重新使用清单步骤 7:释放存储所有权失败的操作与重试限制相关文档可用性和升级边界
受管存储需要以下全部三个组件:
- Bare Metal provider,包括其存储控制器和失败即关闭的
MachineInventory准入 webhook。 - 匹配的
elemental-operatorCRD 和 observer API。 - 安装并启用
elemental-storage-observer.service以及早期启动存储集成的主机 OS 镜像。
在启用受管存储之前,请从 Alauda 技术支持获取匹配的 base-image 和 base-image-iso。将 base-image 用于主机重新置备,将 base-image-iso 用于 SeedImage / 实时安装。这些镜像是目标版本支持的配对;不要从一个镜像引用推导另一个镜像引用,也不要替换为独立构建的镜像。
仅在 global 集群上升级 provider 和 elemental-operator,不会在由旧版 OS 镜像创建的主机上安装 observer service。
- 当
spec.storage保持缺失或具有volumes: []时,现有集群在管理侧升级后仍可继续使用非受管存储。此路径不会创建存储计划或修改磁盘。 - 要在旧主机上启用受管存储,请先使用经过批准且支持 observer 的镜像重新安装、重置或替换该主机。在添加任何非空存储声明之前,确认 observer service 和最新的
status.observedStorage报告均已就绪。 - 不要将
spec.storage.volumes[]添加到正在运行或已分配的 inventory 中。只有在 inventory 未分配且所有受管卷均处于非活动状态时,才能更改存储声明。
存储生命周期
删除 Machine 会执行 Deactivate,而不是 Release。因此,正常缩容会保留 inventory 的存储声明和数据,以便日后重用。
前提条件
- 按照安装 Bare Metal Provider 中的说明,在
global集群上安装 Bare Metal Infrastructure Provider,并等待其 manager 部署和准入 webhook 变为 Ready。 - 从 Alauda 技术支持获取匹配的、支持 observer 的
base-image和base-image-iso。使用 ISO 镜像安装主机,并配置配套的基础镜像,以供后续重新置备使用。 - 在 Prepare 成功之前,将目标
MachineInventory保持在生产池之外。它必须为Ready=True、未分配,并且具有默认 plan Secret。 - 独立备份现有数据。保留存储不等同于应用一致性备份。
- 获取由完全相同的 provider 修订版本构建的
storagectl二进制文件。storagectl会复用 provider 的规范化、验证和哈希代码;请勿手动计算初始化授权哈希,也不要使用其他版本的二进制文件。 - 提交
InitializeIfBlank的身份必须拥有虚拟machineinventories/storageinitialize子资源上的update权限。纯Adopt声明不需要此额外权限。
设置特定操作所需的变量:
验证管理组件和授权:
身份在提交或更改初始化授权之前,最后一条命令必须返回 yes。仅向有权格式化磁盘的特定管理员用户或 ServiceAccount 授予此权限。
步骤 1:验证 Inventory 和 Observer
确认 inventory 可用且当前没有所有者:
分配值必须为空或为 Available;所有所有者值都必须为空。如果 inventory 已分配,请删除所属的 CAPI Machine,并等待正常的清理和 Deactivate 流程。请勿手动移除所有者注解或 finalizer。
在主机上验证 observer:
两条状态命令都必须成功。在 global 集群上,检查观察水位标记和设备信息:
仅使用报告最新且 systemRole 为 Data 的设备。
请勿选择系统设备或 Unknown 设备、多路径成员、只读或可移动设备,或具有意外分区表、文件系统、LVM、RAID、LUKS、swap、使用者或挂载的设备。请勿同时选择整块磁盘及其分区。
步骤 2:定义受管卷
创建存储声明。此示例有意使用占位符;请将每个设备 ID、UUID、容量和挂载路径替换为同一目标清单中的实际信息。移除不适用于该主机的卷。
Storage v2 每个清单最多支持 32 个卷。第一个版本支持整块设备上的 XFS 或 ext4、通过 Adopt 管理的现有 XFS/ext4 分区,以及整块多路径映射。它不会创建分区,也不管理 LVM、mdraid、LUKS、swap、共享集群文件系统或多主机读写访问。
required 默认为 true。可选卷仍会经过准备和激活;只有其失败时对 Ready 状态的影响会有所不同。/var/cpaas 必须始终为必需项。provider 会将 nodev,nosuid 添加到受管挂载中,并根据允许列表验证每个额外挂载选项。
在本地验证声明:
步骤 3:生成并应用原子补丁
始终从当前的实时对象开始,以确保补丁包含最新的 UID 和 resourceVersion:
对于包含 InitializeIfBlank 的声明,请选择一个大于 status.storage.lastConsumedInitializationApprovalCounter 的正计数器,并生成补丁:
生成的合并补丁会将批准绑定到当前 Inventory UID、规范化存储哈希、计数器和 resourceVersion。对于仅包含 Adopt 的声明,请省略 --counter。
运行服务器端 dry-run,再次检查生成的 spec.storage、设备 ID、路径和批准,然后再应用补丁:
如果 API 报告 resourceVersion 冲突,请重新获取清单、重新生成补丁、重复服务器端 dry-run,然后再应用。切勿从生成的补丁中移除 resourceVersion。
步骤 4:等待 Prepare 完成
监视存储状态:
在清单可以分配之前,预期结果如下:
此时,已初始化的卷具有文件系统 UUID,而已接管的卷保留其原始 UUID,但业务挂载路径尚未激活。在 Prepare 完成之前,请勿将清单添加到生产 MachineInventoryPool。
步骤 5:分配并验证激活
将已准备的清单添加到目标 MachineInventoryPool,然后按照在裸金属上创建集群和在裸金属上管理节点中的说明创建或扩展 CAPI machine group。
重新置备完成后,验证 machine 和存储状态:
预期结果为 BaremetalMachine.status.phase=Running、StorageReady=True/AllVolumesReady、MachineInventory.status.storage.phase=Active 和 StorageActive=True/AllRequiredVolumesActive。
在主机上,确认每个源 UUID、文件系统类型、挂载路径和挂载选项。所需的挂载单元必须在 kubelet 启动之前进入 active 状态:
步骤 6:缩减并重新使用清单
通过正常的缩减或替换工作流删除拥有该资源的 CAPI Machine。不要删除 MachineInventory,也不要移除其存储 finalizer。
完成 drain、清理和 Deactivate 后,预期结果如下:
再次分配同一清单时,Activate 会重新使用现有的所有权记录和文件系统 UUID;不会再次格式化设备。通用池分配无法保证替换后的 Machine 获得相同的清单。如果应用程序必须返回到特定清单上的主机本地数据,请将该清单置于受控的有序池的首位,或使用专用池,并在依赖这些数据之前验证所选的 BaremetalMachine.status.machineInventoryRef。
步骤 7:释放存储所有权
只有在清单未分配且处于非活动状态时,才能释放卷。移除卷不会破坏数据:它会移除 Storage v2 所有权和激活元数据,但会保留文件系统 UUID 和数据。
要释放所有卷,请创建一个显式的空声明:
获取实时清单,并渲染、执行 dry-run,然后应用不带初始化计数器的补丁:
等待 phase=Unmanaged、StoragePrepared=True/NoManagedVolumes、空的 appliedVolumes[] 和 operation=null。如有需要,使用只读挂载验证保留的数据。实时清单上可能仍会保留存储 finalizer,以便后续对象删除继续遵循正确的清理顺序;不要手动移除它。
失败的操作与重试
存储操作会采取故障关闭策略。缺失、过期、忙碌、容量过小、降级、从未知来源挂载,或不再匹配其声明 UUID 的必需设备,会阻止分配或 Machine 就绪。controller 永远不会自动选择替代磁盘。
在修正 status.storage.operation.phase 为 Failed 的操作的外部原因后,递增 spec.storage.retryNonce,同时保持 volumes[] 不变,并使用 storagectl 渲染新的补丁。retryNonce 会为同一逻辑操作创建另一次执行尝试。它不会授权首次格式化、绕过预检或允许使用不同的存储声明。
不要将重试用作未知或部分变更声明的恢复机制。当 pendingSpecHash 非空,或失败操作报告 mutationState=DurableStateChanged 或 Unknown 时,保留原始声明,并允许同一操作日志逐步收敛。在考虑任何紧急 finalizer 或所有权操作之前,请联系技术支持。
限制
- 当清单已分配或任何受管卷处于活动状态时,不能更改
volumes[]。 - 已准备卷的
deviceID、文件系统策略/类型或名称不能就地更改。先释放旧卷,等待操作完成,然后添加替代声明。 - Storage v2 不会在清单之间移动数据。清单所拥有的数据会保留在该清单标识的物理主机或 LUN 上。
- Multipath 支持仅管理聚合的
wwid:映射。它不会配置 multipath、SAN zoning、LUN masking、fencing 或多主机读写文件系统。 /var/lib/kubelet、/var/lib/containerd、/var/lib/etcd、/etc、/usr、/boot以及其他系统路径均受保护。请使用不与受保护路径重叠的业务路径,例如/var/cpaas、/data/*、/srv/*或/mnt/*。- 不要同时通过
MachineInventory.spec.storage和 kubeadm/cloud-initdisk_setup、fs_setup、mounts、自定义 systemd 单元或主机脚本管理同一设备或路径。