3. Rook架构与Operator模式

Rook 并不是把 Ceph 的安装脚本包装成容器,而是把 Ceph 集群本身变成 Kubernetes 中的一种“可声明资源”。理解这一点,是掌握 Rook 全部运维行为的前提。Rook 的核心由四部分组成:一组自定义资源定义(CRD)描述期望状态,一个 Rook Operator 负责调谐,若干控制器循环持续比对期望与实际,以及由 Operator 动态创建的一批 Ceph 守护进程 Pod。用户只写 YAML,Operator 负责把 YAML 变成真实运行的 Ceph 集群。

CRD:把 Ceph 集群变成 Kubernetes 对象

Rook 安装时会注册多个 CRD,其中最关键的是 cephclusters.ceph.rook.io。它定义了 CephCluster 这种资源类型,使得 kubectl get cephcluster 成为合法命令。除它之外,还有 CephBlockPool、CephFilesystem、CephObjectStore、CephClient 等,分别描述块存储池、文件系统、对象存储和客户端凭据。CRD 只定义“字段长什么样”,真正的行为由 Operator 中的控制器实现。

一个最小化的 CephCluster 示例(教学示例,非实测结果)如下:

apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
  name: rook-ceph
  namespace: rook-ceph
spec:
  cephVersion:
    image: quay.io/ceph/ceph:v18.2.2
  dataDirHostPath: /var/lib/rook
  mon:
    count: 3
    allowMultiplePerNode: false
  mgr:
    count: 2
  dashboard:
    enabled: true
  storage:
    useAllNodes: false
    useAllDevices: false
    nodes:
      - name: node-1
        devices:
          - name: sdb
      - name: node-2
        devices:
          - name: sdb
      - name: node-3
        devices:
          - name: sdb

这份 YAML 没有描述“先装 mon、再装 mgr、然后装 osd”的步骤,它只声明了最终应该存在 3 个 mon、2 个 mgr、3 个 OSD 节点,以及每个节点使用 sdb 设备。如何达到这个状态,是 Operator 的职责。

Operator 与控制器循环

Rook Operator 是一个长期运行的 Pod,内部包含多个控制器(controller)。每个控制器监听一类资源的事件:创建、更新、删除。事件到达后,控制器不会直接“执行命令”,而是进入调谐(reconcile)循环:读取该资源的期望状态,读取集群中的实际状态,计算差异,然后执行最小必要的动作来消除差异。这个过程反复发生,直到实际状态收敛到期望状态,或遇到无法自动解决的错误并写入事件与状态字段。

调谐循环的关键特征是幂等。同一个 CephCluster 被处理多次,结果应当一致。例如 Operator 发现 mon 数量应为 3、实际为 2,就会创建第 3 个 mon;如果实际已经是 3,则不做任何变更。这种“比对—修正”的循环,使 Rook 能够自动处理 Pod 被驱逐、节点重启、镜像升级等场景,而不需要人工重新执行安装流程。

Rook 声明式管理:期望状态 → 调谐循环 → 实际状态 用户声明 kubectl apply -f CephCluster YAML 期望:3 mon / 2 mgr / 3 osd Kubernetes API Server CRD 校验与持久化 etcd 存储对象 watch 事件推送 Rook Operator Pod Cluster Controller Pool / FS Controller reconcile:比对期望与实际 幂等、持续、事件驱动 实际状态:Operator 动态创建与维护的 Ceph 守护进程 MON × 3 rook-ceph-mon-a/b/c MGR × 2 rook-ceph-mgr-a/b OSD × 3 osd.0 / osd.1 / osd.2 MDS / RGW / Dashboard 按需创建 持续观察实际状态,发现偏差则再次调谐 status 字段回写:phase / cephVersion / conditions

CephCluster 资源与声明式管理机制

CephCluster 是 Rook 中粒度最粗、也最核心的资源。它描述整个 Ceph 集群的形态:Ceph 版本、mon 与 mgr 数量、数据目录、存储设备选择方式、网络配置、Dashboard 开关等。Operator 读取它之后,会依次创建 mon、mgr、osd 等守护进程,并把进展写回 status 字段。用户通过 kubectl -n rook-ceph get cephcluster rook-ceph -o yaml 可以看到 status.ceph 中的版本、健康状态,以及 status.phase 是否达到 Ready。

声明式管理的关键在于“只描述结果,不描述过程”。当需要扩容时,用户不需要登录节点执行 ceph osd add,而是修改 CephCluster 中的 storage.nodes 列表,再 kubectl apply。Operator 检测到期望状态变化,自动创建新的 OSD。缩容同理:从列表中移除节点,Operator 会安全地销毁对应 OSD 并清理设备。这种机制把“集群变更”统一收敛为对 YAML 的修改,使变更可审计、可回滚、可版本化。

判断 Rook 是否完成一次调谐,最直接的依据是 CephCluster 的 status.phase 是否为 Ready,以及 status.ceph.health 是否为 HEALTH_OK。若长时间停留在 Progressing,应查看 Operator 日志与相关 Pod 事件。

一次典型调谐过程

以新增一个 OSD 节点为例,实际发生的过程是:用户编辑 CephCluster,在 storage.nodes 中追加 node-4 及其设备 sdc;API Server 更新对象并触发 watch 事件;Cluster Controller 收到事件后进入 reconcile,读取到期望节点数由 3 变为 4;Operator 在 node-4 上启动 rook-ceph-osd-prepare Job,探测 sdc 是否可用、是否已有分区或文件系统;探测通过后创建 osd Deployment 或直接管理 OSD 进程,并更新 CRUSH map;最后把新的 OSD 数量与状态写回 CephCluster.status。整个过程不需要人工介入 Ceph 命令行。

如果设备已被占用或不可用,Operator 不会强行覆盖,而是把失败原因记录到事件和 status 中,调谐循环会以退避方式重试。这正是控制器循环与一次性安装脚本的本质区别:它持续存在,持续观察,持续修正。

Operator 模式带来的运维变化

在传统部署中,Ceph 的升级、扩容、故障恢复依赖人工执行命令并判断结果。在 Rook 中,这些动作被抽象为对 CRD 对象的修改,由 Operator 自动执行。运维人员的主要工作从“执行命令”转变为“声明期望、观察状态、处理异常”。这也意味着,理解 CephCluster 的字段含义、理解调谐循环的收敛条件、理解 status 字段的判读方式,比记住某条 Ceph 命令更重要。Rook 把 Ceph 的复杂性封装在 Operator 内部,但把控制权通过 CRD 完整地交还给用户。