Rook v1.21 发布解读:OSD 自动化替换、RBD QoS 与 Helm/TLS 关键变更

发布时间:2026/9/23 1:48:26
Rook v1.21 发布解读:OSD 自动化替换、RBD QoS 与 Helm/TLS 关键变更 Rook v1.21 发布解读OSD 自动化替换、RBD QoS 与 Helm/TLS 关键变更【免费下载链接】rookStorage Orchestration for Kubernetes项目地址: https://gitcode.com/gh_mirrors/roo/rook导读Rook v1.21当前仓库对应版本是本项目面向 Kubernetes 的 Ceph 存储编排的一个重要演进版本。本篇技术文章以仓库根目录的 PendingReleaseNotes.md 为主体逐条剖析该版本的 2 项破坏性变更与 6 项新特性并结合仓库内的设计文档design/ceph/osd-replacement.md、CRD API 定义、Helm 图表与源码实现给出可直接落地的操作步骤、参数参考与底层原理。读者读完可以掌握如何利用注释驱动 OSD 就地替换、如何用VolumeAttributesClass为 RBD 卷配置 QoS、如何通过新 Helm 值创建CephObjectStoreUser以及如何理解 Helm OCI 标签与 OSD prepare 行为变更带来的升级影响。说明以下内容均以当前仓库实际代码与文档为准。涉及 Kubernetes / Ceph 版本下限的要求如 VolumeAttributesClass 需要 Kubernetes v1.34属于上游能力约束在文中已明确标注。一、破坏性变更Breaking Changes1.1 Helm OCI Chart 标签不再带v前缀从 v1.21 开始通过 OCI 方式发布的 Helm Chart 标签不再包含v前缀旧格式v1.21.0新格式1.21.0影响范围所有在脚本、CI/CD 流水线或其他工具中按标签引用 Helm Chart 的配置都必须同步更新。例如使用helm pull oci://registry/rook-ceph:1.21.0或helm upgrade --install rook-ceph oci://registry/rook-ceph --version 1.21.0的地方不能继续写v1.21.0。从仓库的发布流程看Chart 的打包与推送由 build/release/Makefile 完成helm package --version $(HELM_CHART_VERSION) --app-version $(VERSION)生成 Chart 包随后helm push ... oci://registry并配合cosign sign进行签名见 build/release/Makefile#L140-L155。标签去除v前缀意味着HELM_CHART_VERSION这一发布变量本身就不再包含v升级脚本若仍按v{{ .Chart.Version }}拼接标签会解析失败。升级建议在升级前 grep 所有引用 Chart 标签的脚本与 Helm 命令统一改为不带v的版本号同时确认依赖 OCI registry 的 GitOps 工具如 Flux、Argo CD中的 chart version 引用方式。1.2 OSD prepare 任务对“已准备设备未出现在 raw list”改为失败重试旧行为当ceph-volume raw list的输出中缺失某个刚刚被 prepare 的设备时OSD prepare 任务会静默通过导致节点上报的 OSD 数量少于实际准备的数量。其后果是OSD 已注册进 osdmap但对应的 OSD Deployment 从未被创建——集群中出现“幽灵 OSD”既无法提供服务又干扰后续的 OSD 管理。新行为prepare 任务现在会显式失败并由 Kubernetes 按 Job 语义自动重试而不是静默少报。源码依据实现在 pkg/daemon/ceph/osd/volume.go 的ensurePreparedDevicesListed函数中volume.go#L254-L278对每个刚在 raw 模式下 prepared 的设备检查其是否出现在ceph-volume raw list的返回结果中若缺失则单独对该设备执行ceph-volume raw list device这种单设备形式的查询不受无参形式可能漏报故障的影响见 volume.go#L233 的注释若单独查询仍无法返回该 OSD则直接返回错误使 prepare Job 以非零退出码结束Kubernetes 会用全新扫描的环境重启 Job而不是带病继续。该行为的测试用例位于 pkg/daemon/ceph/osd/volume_test.go如 volume_test.go#L677-L735 覆盖了“raw 模式 OSD 缺失于 raw list 结果”的场景。运维影响升级后若观察到 OSD prepare Job 反复失败请检查节点上设备状态如磁盘热插拔、udev 链接漂移、LVM 元数据残留因为 Job 重试正是为了暴露这类此前被掩盖的设备级问题。二、新特性一基于注释的自动化 OSD 替换OSD Replacement2.1 解决什么问题在 host-based 集群中当一个 OSD 的数据盘与元数据盘分离通过spec.storage的metadataDevice配置例如 5 块 HDD 共享一块 NVMe 作为block.db时旧版 Rook 无法独立替换其中一块故障盘要么重新供给共享同一元数据设备的所有 OSD要么执行一套包含“将 operator 缩容到零”在内的多步手工流程。raw 模式的单盘 OSD 也需要手工流程。v1.21 提供的自动化替换流程可以原地替换单个故障 OSD 并保留其 OSD ID不影响共享同一元数据设备的其他 OSD也无需 toolbox、无需禁用 operator。完整设计见 design/ceph/osd-replacement.md。适用范围与边界来自设计文档的 Goals / Non-goals支持host-based 集群中的全部 OSD 类型包括共享元数据设备的 OSD、单盘 LVM OSD、raw 模式 OSD、加密 OSD不支持PVC 后端 OSD走不同代码路径、外部集群无 operator 管理的 OSD不做Rook 不负责“检测哪块盘坏了”——由用户判断并触发也不负责替换“共享元数据设备本身”。2.2 触发方式与标记Annotation 协议替换是瞬态操作不适合写入 CR specGitOps 工具如 Flux/Argo 会不断把 CR 对账回检入状态因此采用 Deployment 注释作为触发与状态载体。全部标记定义在 pkg/apis/ceph.rook.io/v1/labels.go标记Key / Value 格式写入方含义触发注释osd.rook.io/replaceyes-really-replace-osd-id用户表达替换意图id必须等于 Deployment 的ceph-osd-id标签防止误操作防复制粘贴守卫见 labels.go#L35-L36进行中注释osd.rook.io/replace-in-progresstrue仅 Rook流程所有权标记只有通过校验后 Rook 才会写goroutine 凭它决定可操作的 Deploymentlabels.go#L40-L44可换盘注释osd.rook.io/replace-ready-for-swaptrue仅 RookOSD 已销毁、物理盘可安全拔出labels.go#L47-L48触发命令示例替换osd.5kubectl -n rook-ceph annotate deployment rook-ceph-osd-5 \ osd.rook.io/replaceyes-really-replace-osd-52.3 完整流程两阶段状态机流程遵循 Ceph 官方的 OSD 替换步骤osd out→safe-to-destroy→osd destroy分为两个阶段阶段一销毁并预留槽位Drain Destroy校验CephCluster 控制器的 predicate 侦测到注释变化后触发 reconcile对应测试见 pkg/operator/ceph/controller/predicate_test.go#L205-L218。控制器执行就地校验确认值匹配且与ceph-osd-id标签一致ceph osd dump确认目标 OSD 存在且未destroyedDeployment 必须无ceph.rook.io/pvc标签即 host-based设备引用当前可解析同一物理设备上没有其他 OSDosdsPerDevice 1场景不在支持范围。上锁移交校验通过后在同一 Deployment 更新中写入ceph.rook.io/do-not-reconcile标签与osd.rook.io/replace-in-progress注释使控制器常规对账不再触碰该 Deployment交由 OSD 健康监控 goroutine 接管控制器 reconcile 是串行的标签写在 reconcile 内才持久可靠goroutine 是独立线程若由它写标签会与在途 reconcile 竞争——这是设计中“为何分工”的关键见设计文档 “Why split the work between the controller and the goroutine”。排空goroutine 每个 60 秒 tick 从持久状态osdmap、Deployment 标记、清理 Job推导当前相位并执行对应动作所有动作幂等operator 重启可从断点恢复相位检测方式本 tick 动作未校验无replace-in-progress注释忽略未开始已标记但 OSD 仍inceph osd out id排空中out但未safe-to-destroy重查safe-to-destroy否则下个 tick 重试可销毁safe-to-destroy通过且槽位未destroyed执行销毁步骤已销毁槽位destroyed且无replace-ready-for-swap写入replace-ready-for-swap注释完成replace-ready-for-swap已存在忽略销毁依次执行——把 Deployment 缩到replicas0并等待 Pod 消失daemon 运行期间持有数据 LV 与 DB LV加密 OSD 需先通过一个以 OSD id 命名的 Kubernetes Job 在节点上执行cryptsetup close关闭 dm-crypt 映射ceph osd down osd.id幂等规避心跳延迟导致的EBUSYceph osd destroy osd.id --yes-i-really-mean-it槽位变为destroyedCRUSH bucket 与权重保留数据盘与 DB LV 均保留DB LV 上的ceph.osd_id标签留待复用最后写入replace-ready-for-swap注释加密 OSD 先清理 Job。阶段二换盘检测与再供给Swap Provision等待换盘旧盘携带 Ceph 签名设备发现getAvailableDevices不会把它当作可用设备用户看到replace-ready-for-swap后物理换上新盘可以晚几分钟甚至几天新盘是空白盘通过发现门槛成为可用设备——这个状态翻转就是换盘信号。同时 prepare-job 上报 OSD 到 per-node 状态 CM 时新增过滤跳过 osdmap 中标记为destroyed的 OSD对应 volume.go#L249 中的destroyedOSDIds过滤。再供给prepare-job 先枚举本节点的 destroyed 槽位ceph osd tree --states destroyed --format json按ROOK_NODE_NAME过滤发现新的空白数据盘通过ceph-volume lvm list id找回幸存 DB LV空结果表示单盘 OSD按布局调用ceph-volumeLVM 共享元数据设备ceph-volume lvm prepare --bluestore --osd-id id --data /dev/newDataDisk --block.db /dev/metadataVG/survivingDbLV [--dmcrypt] --crush-device-class classLVM 单盘同上但省略--block.dbRaw 单盘ceph-volume raw prepare --bluestore --osd-id id --data /dev/newDataDisk--osd-id id会通过内部ceph osd new new-fsid id认领销毁的槽位OSD ID、CRUSH bucket、权重全部保留仅 OSD UUID 更新。注意流程特意使用lvm prepare --block.db vg/lv而非lvm batch因为batch总是新分配 DB 槽位且拒绝幸存兄弟 LV原地复用 DB LV 只会重打标签并重新 mkfs不触碰元数据设备上的其他分配。完成prepare-job 把新 OSDInfo 写入 per-node 状态 CMrook-ceph-osd-node-status控制器下一个 reconcile 发现旧 Deployment 仍带着replace-ready-for-swap识别为已完成替换删除并依据 CM 重建 Deploymentreplicas1无任何替换标记——删除旧 Deployment 即清除了标记。当osd.id变为up且in控制器发出OSDReplaceCompleted事件集群恢复故障前状态。2.4 取消、重试与失败处理销毁前取消移除osd.rook.io/replace注释。goroutine 停止等待safe-to-destroy执行ceph osd in id恢复删除在途清理 Job并把 Deployment 恢复为replicas1、清除replace-in-progress与do-not-reconcile。加密 OSD 的取消可能跨多个 tick必须等cryptsetup closeJob 完全消失才能解除围栏避免与 daemon 重启竞争。销毁后取消不生效——槽位已destroyed。只能让流程走完向该槽位供给新盘或手工放弃ceph osd purge id退役槽位并对幸存 DB LV 执行ceph-volume lvm zap --destroy。供给失败ceph-volume在触碰磁盘前先用ceph osd new认领 id失败时自行回滚ceph osd purge-newceph-volume lvm zap --destroy --osd-id id。注意 zap 按ceph.osd_id标签解析目标且刻意包含db/walLV会销毁流程特意保留的幸存 DB LV——上游不会保护它。此时 destroyed 槽位已消耗、CRUSH bucket 与权重被 purge换入的盘走正常路径成为新 OSD可能复用也可能不复用旧 id。prepare-job 会记录该槽位失败并继续控制器在后续 reconcile 检测到 osdmap 中该 id 已消失absent删除标记 Deployment避免其永远以replicas0被围栏。2.5 与既有配置的交叉影响设计文档明确了三个依赖项见设计文档 “Intersection with existing Rook config”spec.healthCheck.daemonHealth.osd.disabled默认false即启用。销毁逻辑运行在 OSD 健康监控内替换功能依赖它保持启用spec.removeOSDsIfOutAndSafeToRemove默认false。必须保持禁用否则 Rook 会在用户注释前就删除 downout OSD 的 Deploymenthealth.go#L135-L167 区域破坏替换流程rook-discover daemonROOK_ENABLE_DISCOVERY_DAEMON启用时由它触发换盘后的 reconcile 以运行 prepare-job未启用则需要用户在换盘后手动触发一次 reconcile。相关状态机的单元测试覆盖了各相位与取消/守卫场景见 pkg/operator/ceph/cluster/osd/replace_test.go 与 pkg/operator/ceph/cluster/osd/replace_destroy_test.go。三、新特性二RBD QoS基于 VolumeAttributesClass3.1 能力概述RBD QoS 允许管理员为 RBD 块卷设置 IOPS 与带宽上限防止多租户集群中的“吵闹邻居”问题。QoS 通过VolumeAttributesClass资源配置可借助 CSI 的ControllerModifyVolume操作对已存在的卷动态修改 QoS 限额而无需重建卷。支持范围使用默认 krbd内核 RBD挂载器通过 Linux cgroup v2 的io.max控制器在容器层面强制执行。前提条件Kubernetes v1.34VolumeAttributesClass自 v1.34 起 GA节点启用 cgroup v2现代主流发行版默认开启Linux 内核 5.8。3.2 QoS 参数参考以下参数全部可选按需设置完整示例见 deploy/examples/csi/rbd/volumeattributesclass-cgroup.yaml参数说明示例maxReadIops最大读 IOPS1000maxWriteIops最大写 IOPS2000maxReadBps最大读带宽字节/秒104857600100 MiB/smaxWriteBps最大写带宽字节/秒209715200200 MiB/s3.3 全新集群启用步骤确认 StorageClass 带有所需 secret 引用。默认 deploy/examples/csi/rbd/storageclass.yaml 已包含parameters: # 动态 QoS 修改VolumeAttributesClass所需 csi.storage.k8s.io/controller-modify-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/controller-modify-secret-namespace: rook-ceph # namespace:cluster # krbd QoScgroup v2所需 csi.storage.k8s.io/node-publish-secret-name: rook-csi-rbd-node csi.storage.k8s.io/node-publish-secret-namespace: rook-ceph # namespace:cluster创建 VolumeAttributesClasskubectl create -f deploy/examples/csi/rbd/volumeattributesclass-cgroup.yaml创建引用它的 PVCapiVersion: v1 kind: PersistentVolumeClaim metadata: name: rbd-pvc-qos spec: accessModes: - ReadWriteOnce volumeAttributesClassName: rook-ceph-rbd-cgroup-qos resources: requests: storage: 10Gi storageClassName: rook-ceph-block修改既有卷的 QoS更新 PVC 的volumeAttributesClassNamekubectl patch pvc rbd-pvc-qos -p {spec:{volumeAttributesClassName:rook-ceph-rbd-cgroup-qos}}一个 Pod 可通过为不同 PVC 使用不同 VolumeAttributesClass同时挂载多个不同 QoS 限额的卷。3.4 存量集群启用步骤StorageClass 参数不可变存量集群需删除重建 StorageClass删除不影响既有 PV/PVC但重建前新建 PVC 会失败kubectl get storageclass rook-ceph-block -o yaml storageclass-backup.yaml kubectl delete storageclass rook-ceph-block # 编辑 storageclass-backup.yaml按 3.3 第 1 步补充 modify-secret 与 publish-secret 参数 kubectl create -f storageclass-backup.yaml kubectl create -f deploy/examples/csi/rbd/volumeattributesclass-cgroup.yaml kubectl patch pvc pvc-name -p {spec:{volumeAttributesClassName:rook-ceph-rbd-cgroup-qos}}验证 QoS 已生效kubectl get pvc pvc-name -o jsonpath{.status.currentVolumeAttributesClassName}输出应与所应用的 VolumeAttributesClass 名称一致。3.5 故障排查QoS 限额未生效检查 VolumeAttributesClass 存在且 PVC 正确引用查看 CSI 节点插件日志kubectl logs -n rook-ceph -l appcsi-rbdplugin -c csi-rbdplugin --tail100 | grep -i qoscgroup v2 QoS 不工作确认节点使用 cgroup v2cgroup.controllers存在且包含iokubectl debug node/node-name -it --imagebusybox -- cat /host/sys/fs/cgroup/cgroup.controllers并核对 Kubernetes 版本不低于 v1.34kubectl version --short。四、新特性三Helm Chart 支持创建 CephObjectStoreUserrook-ceph-cluster Helm Chart 新增cephObjectStoreUsers值可直接在集群命名空间创建CephObjectStoreUser资源。模板实现deploy/charts/rook-ceph-cluster/templates/cephobjectstoreuser.yaml 遍历该值为每个条目生成一个ceph.rook.io/v1的CephObjectStoreUserspec直接透传。values.yaml 默认注释示例deploy/charts/rook-ceph-cluster/values.yaml#L768-L775# cephObjectStoreUsers create S3 users in a CephObjectStore. They are disabled by default; # remove the comments and set desired values to enable them. See # https://rook.io/docs/rook/latest/CRDs/Object-Storage/ceph-object-store-user-crd/ cephObjectStoreUsers: - name: my-user spec: store: ceph-objectstore displayName: my display nameChart 测试deploy/charts/rook-ceph-cluster/tests/cephobjectstoreuser_test.yaml 覆盖了通过该值渲染用户资源的场景。用户对象的完整 spec 字段store、displayName、capabilities 等可参考 CRD 文档 Documentation/CRDs/Object-Storage/ceph-object-store-user-crd.md仓库中的可运行示例见 deploy/examples/object-user.yaml。五、新特性四工具箱自动重载 keyring 与 ceph.confHelm Chart 与示例清单中的 toolbox Deployment 现在会在 CephX key 轮换、mon 故障转移或 config override 变更后自动重新加载 keyring 与ceph.conf。实现形态工具箱脚本内联在 Chart 模板的 Deployment 中见 deploy/charts/rook-ceph-cluster/templates/deployment.yaml#L50-L51 的注释“The script is inlined because the ceph image does not ship toolbox.sh. AUTOGENERATED from images/ceph/toolbox.sh”即由仓库 images/ceph/toolbox.sh 自动生成。其核心是watch_etc_ceph()函数deploy/examples/toolbox.yaml#L89-L111 区域持续监听/etc/ceph目录比较挂载的 keyring 源文件KEYRING_MOUNT与写入目标KEYRING_FILE的时间戳一旦检测到变化就重写 keyring 与 ceph.conf。这意味着CephX key 轮换后无需再手工重启工具箱 Pod 或手动复制凭据mon 端点变化如 mon 故障转移、IP 变更会自动同步到工具箱配置集群configOverride变更也能被工具箱及时感知。六、新特性五CephCluster Dashboard 自定义 TLS 证书CephCluster 的 Dashboard 现在可通过spec.dashboard.sslCertificateRef引用同命名空间的 Kubernetes TLS Secret 来配置证书需在 dashboard SSL 启用时使用。CRD 字段SSLCertificateRef定义于 pkg/apis/ceph.rook.io/v1/types.go#L580dashboard spec与 pkg/apis/ceph.rook.io/v1/types.go#L2111cluster spec 相关字段。底层实现pkg/operator/ceph/cluster/mgr/dashboard.goconfigureSSLCertificatedashboard.go#L236-L258决定走自定义证书还是自签名证书若曾配置过 Secret 证书而引用被移除会恢复默认自签名证书configureCustomSSLCertificatedashboard.go#L260-L311读取同命名空间 Secret校验其类型必须为kubernetes.io/tls且包含tls.crt/tls.key将证书写入 mgr 配置键mgr/dashboard/crt与mgr/dashboard/key并把 Secret 名记录到rook/dashboard/sslCertificateRef配置键dashboardTLSRefKey见 dashboard.go#L52Rook 会在 reconcile 中持续对账被引用 Secret 的更新证书变更即被重新下发移除引用则回退到自签名证书。使用示例apiVersion: ceph.rook.io/v1 kind: CephCluster metadata: name: rook-ceph namespace: rook-ceph spec: dashboard: enabled: true ssl: true sslCertificateRef: rook-ceph-dashboard-tlsapiVersion: v1 kind: Secret metadata: name: rook-ceph-dashboard-tls namespace: rook-ceph type: kubernetes.io/tls data: tls.crt: base64 编码的证书 tls.key: base64 编码的私钥七、新特性六Object Store reconcile 等待 OSD 升级完成Rook 的 CephObjectStore 控制器现在会在创建/更新 RGW 服务前先等待集群中的 OSD 完成版本升级。源码依据pkg/operator/ceph/object/controller.go#L462-L471。控制器先比较运行中的 Ceph 版本与 CephCluster CR 期望版本若不一致则重入队等待随后通过LeastUptodateDaemonVersion查询 OSD 类型的最低版本config.OsdType若 OSD 尚未达到期望版本同样返回WaitForRequeueIfCephClusterIsUpgrading重入队结果而不是带着版本不一致的 OSD 继续部署 RGW。动机RGW 依赖 OSD 提供底层存储在集群升级过程中若 OSD 尚未全部完成升级就推进 RGW 的创建或更新可能产生新旧版本混跑带来的兼容性问题。等待 OSD 升级完成可保证 RGW 运行在一致的版本环境上。对应测试见 pkg/operator/ceph/object/controller_test.go#L558“requeue - osds still upgrading”。注意外部集群spec.external.enabletrue跳过该等待逻辑。八、升级注意事项汇总变更类型升级动作Helm OCI 标签去v破坏性更新所有引用 Chart 标签的脚本/工具使用1.21.0而非v1.21.0OSD prepare 失败重试破坏性关注 prepare Job 重试日志排查设备漏报根因OSD 自动化替换特性确保spec.removeOSDsIfOutAndSafeToRemovefalse、OSD 健康检查启用RBD QoS特性需要 Kubernetes v1.34、cgroup v2、内核 5.8存量集群需重建 StorageClasscephObjectStoreUsers特性Helm 升级后可在 values 中按需启用toolbox 自动重载特性升级后工具箱自动跟随 keyring/配置变更Dashboard TLS Secret特性设置spec.dashboard.sslCertificateRef指向同命名空间 TLS SecretObject store 等待 OSD 升级特性升级期间 RGW 创建/更新会延迟到 OSD 版本一致后执行参考资源仓库内发布说明原文PendingReleaseNotes.mdOSD 替换设计文档design/ceph/osd-replacement.mdRBD QoS 使用指南Documentation/Storage-Configuration/Block-Storage-RBD/rbd-qos.md替换标记定义pkg/apis/ceph.rook.io/v1/labels.goOSD prepare 设备列表校验pkg/daemon/ceph/osd/volume.goDashboard TLS 实现pkg/operator/ceph/cluster/mgr/dashboard.goObject store 升级等待pkg/operator/ceph/object/controller.goQoS 示例清单deploy/examples/csi/rbd/volumeattributesclass-cgroup.yaml对象存储用户 CRD 文档Documentation/CRDs/Object-Storage/ceph-object-store-user-crd.md【免费下载链接】rookStorage Orchestration for Kubernetes项目地址: https://gitcode.com/gh_mirrors/roo/rook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考