欢迎光临
我们一直在努力

Kubernetes Operator CRD/CR 深度解析报告

文章目录

  • Kubernetes Operator CRD/CR 深度解析报告
    • 目录
    • 一、核心概念快速理解
      • 1.0 历史与哲学背景
        • Kubernetes 的历史演进
        • Operator 的哲学本质
      • 1.1 生活场景类比
      • 1.2 概念定义对照表
      • 1.3 Spec vs Status:两个状态字段
      • 1.4 三者关系的精确定义
    • 二、API 资源概览
      • 2.1 `kubectl api-resources` 输出解读
      • 2.2 内置资源 vs 自定义资源
      • 2.3 实际环境中的 OceanBase 资源
    • 三、CRD/CR/Operator 代码级解析
      • 3.1 CRD 定义(YAML → Go 结构体)
        • 实际 CRD 定义
        • CRD 对应的 Go 结构体(生成的代码)
      • 3.2 CR(Custom Resource)的内存结构
    • 四、调谐循环(Reconcile)代码实现
      • 4.1 完整的 Reconcile Loop 流程图
      • 4.2 Reconcile 函数代码详解
    • 五、状态机(State Machine)与事件
      • 5.1 Operator 状态机
      • 5.2 状态机流程图
      • 5.3 Watch 事件驱动机制
    • 六、OceanBase 实战案例
      • 6.1 实际环境信息(脱敏)
      • 6.2 验证步骤与实际输出
      • 6.3 集群架构拓扑
      • 6.4 集群配置参数说明
    • 七、通用学习指南
      • 7.1 学习任何 Operator 的六步法
      • 7.2 主流数据库 Operator 对比
      • 7.3 Operator 开发框架对比
    • 附录:快速参考
      • A. kubectl api-resources 命令详解
      • B. 常用调试命令
      • C. 术语对照表

Kubernetes Operator CRD/CR 深度解析报告

报告日期:2026-03-05 环境目标:生产环境 Kubernetes 集群 主题:从代码级别理解 Operator、CRD、CR 的底层原理


目录

  • 核心概念快速理解
  • API 资源概览
  • CRD/CR/Operator 代码级解析
  • 调谐循环(Reconcile)代码实现
  • 状态机(State Machine)与事件
  • OceanBase 实战案例
  • 通用学习指南
  • 附录:快速参考

  • 一、核心概念快速理解

    1.0 历史与哲学背景

    Kubernetes 的历史演进

    Kubernetes(希腊语"舵手")的诞生并非偶然,而是云计算发展历程中的重要里程碑:

    ┌─────────────────────────────────────────────────────────────────────┐
    │ Kubernetes 哲学观 │
    ├─────────────────────────────────────────────────────────────────────┤
    │ │
    │ 【核心哲学】 │
    │ │
    │ 1. 声明式优于命令式 (Declarative over Imperative) │
    │ "告诉系统你想要什么,而不是如何做" │
    │ │
    │ 2. 控制理论 (Control Theory) │
    │ 从工业控制理论借鉴,引入 Reconciliation Loop(调谐循环) │
    │ │
    │ 3. 不可变基础设施 (Immutable Infrastructure) │
    │ 用声明式配置管理,而非持续修改运行时状态 │
    │ │
    │ 4. 自愈性 (Self-healing) │
    │ "期望 – 实际 – 调整"的持续循环 │
    │ │
    └─────────────────────────────────────────────────────────────────────┘

    关键历史节点:

    时间事件意义
    2014 Google 开源 Kubernetes 将 Google Borg 十年经验公开
    2015 v1.0 发布 生产就绪
    2016 CRD 成为稳定特性 允许用户扩展 API
    2018 Operator 模式普及 CoreOS 提出 Operator 模式
    2020+ Operator 生态爆发 数据库、中间件、AI 等全面 Operator 化

    从 Docker 到 Kubernetes 的哲学转变:

    【命令式思维 – Docker】
    → 手动执行命令
    → 持续修改状态
    → 依赖人工决策

    【声明式思维 – Kubernetes】
    → 定义期望状态
    → 系统自动调谐
    → 状态驱动的自愈

    Operator 的哲学本质

    Operator 模式的提出,源于对 Kubernetes 控制器模式的深刻理解:

    设计哲学:

  • 领域专家知识编码化
    • 将运维专家的经验固化到代码中
    • 让"人"的经验成为"系统"的能力
  • 状态驱动的自动化
    • 声明式描述期望状态
    • 系统持续调谐以达成目标
  • 可扩展性原则
    • Kubernetes 不预设所有应用场景
    • 通过 CRD 和 Operator 扩展能力边界
  • 闭环控制
  • 期望状态 ──▶ 控制器 ──▶ 实际状态
    ▲ │
    └──────── 调谐循环 ───────┘

    1.1 生活场景类比

    想象你在管理一个餐厅:

    ┌─────────────────────────────────────────────────────────────────────┐
    │ 餐厅管理系统 │
    ├─────────────────────────────────────────────────────────────────────┤
    │ │
    │ 内置功能: │
    │ • 桌子预订 │
    │ • 菜单管理 │
    │ • 收银台 │
    │ │
    │ ┌─────────────────────────────────────────────────────────────┐ │
    │ │ 你想添加的特殊功能 │ │
    │ │ │ │
    │ │ ① 定义"包间"这种特殊桌型 ──▶ CRD │ │
    │ │ ② 预订一间具体的包间 ──▶ CR │ │
    │ │ ③ 安排服务员按照包间规则服务 ──▶ Operator │ │
    │ └─────────────────────────────────────────────────────────────┘ │
    │ │
    └─────────────────────────────────────────────────────────────────────┘

    对应关系:

    餐厅场景Kubernetes 概念作用
    定义"包间"是特殊桌型 CRD 定义一种新的资源类型
    预订"202 号包间" CR 具体的资源实例
    安排专门的服务员处理包间 Operator 管理这种资源的专门逻辑

    1.2 概念定义对照表

    概念英文全称一句话定义代码类比
    CRD Custom Resource Definition 扩展 Kubernetes API 的"类型模板",告诉系统"有什么新东西" class User { name, age }
    CR Custom Resource CRD 的具体实例,即"某个东西" user1 = new User("张三", 25)
    Operator 操作器/运算符 结合 CRD + 控制器逻辑,实现应用自动化运维的智能代理 while(true) { sync(user1) }
    Controller 控制器 Operator 的核心组件,负责比较期望与实际状态 循环中的比较逻辑
    Reconcile 调谐 不断比较并调整状态的过程 期望 – 实际 = 差异 → 执行调整

    1.3 Spec vs Status:两个状态字段

    字段含义谁填写例子
    spec 期望状态(用户想要什么) 用户通过 YAML 文件定义 replicas: 3, version: "4.3.5"
    status 实际状态(系统实际是什么) Operator 自动填写 availableReplicas: 3, phase: "Running"

    关键理解:

    • spec 是输入(你告诉系统要做什么)
    • status 是输出(系统告诉你现在怎么样)
    • Operator 的职责就是:不断让 status 向 spec 收敛

    1.4 三者关系的精确定义

    ┌─────────────────────────────────────────────────────────────────────┐
    │ Kubernetes API Server │
    │ (系统的大门,统一 API 入口) │
    ├─────────────────────────────────────────────────────────────────────┤
    │ │
    │ ┌─────────────────────────────────────────────────────────────┐ │
    │ │ 内置资源(Kubernetes 自带的) │ │
    │ │ • Pod • Deployment • Service │ │
    │ │ • ConfigMap • Secret • Ingress │ │
    │ │ (这些是系统自带的,不需要定义) │ │
    │ └─────────────────────────────────────────────────────────────┘ │
    │ │
    │ ════════════════════════════════════════════════════════ │
    │ ║ 自定义资源层(用户扩展的) │ ║
    │ ║ │ ║
    │ ║ CRD(类定义) CR(实例) │ ║
    │ ║ ┌─────────────┐ ┌──────────────────┐ │ ║
    │ ║ │ 【定义】 │ │ 【实例】 │ │ ║
    │ ║ │ "数据库集群" │ │ │ "生产数据库集群" │ │ ║
    │ ║ │ • 副本数 │ │ │ │ • name: prod-db │ │ ║
    │ ║ │ • 版本 │ │ │ │ • replicas: 3 │ │ ║
    │ ║ │ • 存储配置 │ │ │ │ • version: 4.2 │ │ ║
    │ ║ └─────────────┘ └──────────────────┘ │ ║
    │ ║ │ │ ║
    │ ║ ▼ │ ║
    │ ║ ┌─────────────────────────────────────────────┐ │ ║
    │ ║ │ Operator (3) │ │ ║
    │ ║ │ 【智能管家】 │ │ ║
    │ ║ │ │ │ ║
    │ ║ │ 持续监听 CR 的变化 │ │ ║
    │ ║ │ 读取期望状态 │ │ ║
    │ ║ │ 查询实际状态 │ │ ║
    │ ║ │ 计算差异 │ │ ║
    │ ║ │ 执行调谐动作 │ │ ║
    │ ║ │ 更新 CR 的状态 │ │ ║
    │ ║ └─────────────────────────────────────────────┘ │ ║
    │ ╚═════════════════════════════════════════════════════ │
    │ │
    └─────────────────────────────────────────────────────────────────────┘


    二、API 资源概览

    2.1 kubectl api-resources 输出解读

    $ kubectl api-resources

    列名含义示例
    NAME 资源类型全名 pods, services, oceanbaseclusters
    SHORTNAMES 缩写别名 po, svc, obc
    APIGROUP API 组名 v1, apps/v1, oceanbase.woqutech.com/v1
    NAMESPACED 是否命名空间级别 true = 需要指定 namespace
    KIND 资源类型 Pod, Service, CustomResource
    VERBS 支持的 HTTP 动词 create, get, list, watch, patch, update, delete

    2.2 内置资源 vs 自定义资源

    ┌─────────────────────────────────────────────────────────────────────┐
    │ Kubernetes API 资源分层 │
    ├─────────────────────────────────────────────────────────────────────┤
    │ │
    │ ┌─────────────────────────────────────────────────────────────┐ │
    │ │ Core API(核心组,v1) │ │
    │ │ ┌──────────────────────────────────────────────┐ │ │
    │ │ │ • Pod • Node │ │ │
    │ │ │ • Service • Namespace │ │ │
    │ │ │ • ConfigMap • Event │ │ │
    │ │ └──────────────────────────────────────────────┘ │ │
    │ │ APIGROUP: v1, NAMESPACE: true/false │ │
    │ └─────────────────────────────────────────────────────────────┘ │
    │ │
    │ ┌─────────────────────────────────────────────────────────────┐ │
    │ │ Apps API(应用组,apps/v1) │ │
    │ │ ┌──────────────────────────────────────────────┐ │ │
    │ │ │ • Deployment • StatefulSet │ │ │
    │ │ │ • DaemonSet • ReplicaSet │ │ │
    │ │ └──────────────────────────────────────────────┘ │ │
    │ │ APIGROUP: apps/v1, NAMESPACE: true │ │
    │ └─────────────────────────────────────────────────────────────┘ │
    │ │
    │ ══════════════════════════════════════════════════════════════ │
    │ ║ Custom Resource(自定义资源) │ ║
    │ ║ │ ║
    │ ║ OceanBase Cluster: │ ║
    │ ║ apiGroup: oceanbase.woqutech.com/v1 │ ║
    │ ║ kind: OceanbaseCluster │ ║
    │ ║ NAMESPACE: true │ ║
    │ ║ │ ║
    │ ║ MySQL Cluster: │ ║
    │ ║ apiGroup: mysql.woqutech.com/v1 │ ║
    │ ║ kind: MysqlCluster │ ║
    │ ║ NAMESPACE: true │ ║
    │ ║ │ ║
    │ ╚═══════════════════════════════════════════════════ │
    │ │ 这些都是通过 CRD 扩展的资源 │ │
    │ └─────────────────────────────────────────────────────────────┘ │
    │ │
    └─────────────────────────────────────────────────────────────────────┘

    2.3 实际环境中的 OceanBase 资源

    $ kubectl get oceanbasecluster -A
    NAMESPACE NAME AGE
    qfusion-admin ob-2db57f43 2d1h

    $ kubectl api-resources | grep oceanbase
    NAME SHORTNAMES APIGROUP NAMESPACED
    oceanbaseclusters obc oceanbase.woqutech.com/v1 true
    restores obr oceanbase.woqutech.com/v1 true


    三、CRD/CR/Operator 代码级解析

    3.1 CRD 定义(YAML → Go 结构体)

    实际 CRD 定义

    apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    metadata:
    name: oceanbaseclusters.oceanbase.woqutech.com
    spec:
    group: oceanbase.woqutech.com # API 组名
    names:
    kind: OceanbaseCluster # Go 结构体类型名
    listKind: OceanbaseClusterList
    plural: oceanbaseclusters # 复数名
    shortNames:
    obc # 缩写
    singular: oceanbasecluster # 单数名
    scope: Namespaced # 是否命名空间级别
    versions:
    name: v1 # API 版本
    served: true # 是否通过 API 服务
    storage: true # 是否作为存储版本

    CRD 对应的 Go 结构体(生成的代码)

    package v1

    // OceanbaseClusterSpec 定义了期望状态
    // +genclient:noStatus
    // +kubebuilder:object:generate=true
    type OceanbaseClusterSpec struct {
    metav1.TypeMeta `json:"metadata"`

    // 期望状态:用户定义的配置
    AppName string `json:"appName"`
    DatabaseBranch DatabaseBranchSpec `json:"databaseBranch"`
    IsPaused bool `json:"isPaused"`

    // Proxy 配置
    Proxy ProxySpec `json:"proxy"`

    // Server 配置
    Server ServerSpec `json:"server"`
    }

    // OceanbaseClusterStatus 定义了实际状态
    // +kubebuilder:object:root=true
    // +kubebuilder:subresource:status
    // +kubebuilder:resource:shortname=obc
    type OceanbaseClusterStatus struct {
    Stage string `json:"stage"`
    ParametersStatus ParametersStatus `json:"parametersStatus"`
    PauseStage string `json:"pauseStage"`

    // Proxy 状态
    ProxyStatus ProxyStatus `json:"proxyStatus"`

    // Server 状态
    ServerStatus ServerStatus `json:"serverStatus"`

    // 整体状态
    Status ClusterStatus `json:"status,omitempty"`
    }

    // OceanbaseCluster 是顶层结构体
    // +kubebuilder:object:root=true
    // +kubebuilder:subresource:status
    // +kubebuilder:resource:shortname=obc
    type OceanbaseCluster struct {
    metav1.TypeMeta `json:"metadata"`

    // Spec: 期望状态(用户配置)
    Spec OceanbaseClusterSpec `json:"spec"`

    // Status: 实际状态(Operator 填写)
    Status OceanbaseClusterStatus `json:"status,omitempty"`
    }

    3.2 CR(Custom Resource)的内存结构

    ┌─────────────────────────────────────────────────────────────────────┐
    │ CR 在内存中的结构 │
    ├─────────────────────────────────────────────────────────────────────┤
    │ │
    │ ┌─────────────────────────────────────────────────────────────┐ │
    │ │ 对象头 │ │
    │ │ ┌─────────────────────────────────────────────┐ │ │
    │ │ │ name: ob-2db57f43 │ │ │
    │ │ │ namespace: qfusion-admin │ │ │
    │ │ │ uid: 1e1d55cc-… │ │ │
    │ │ │ labels: │ │ │
    │ │ │ AppName: ob-2db57f43 │ │ │
    │ │ │ ClusterName: ob-2db57f43 │ │ │
    │ │ │ CreatedBy: woqutech.com │ │ │
    │ │ └─────────────────────────────────────────────┘ │ │
    │ └─────────────────────────────────────────────────────────────┘ │
    │ │
    │ ┌─────────────────────────────────────────────────────────────┐ │
    │ │ Spec: 期望状态(用户配置) │ │
    │ │ ┌─────────────────────────────────────────────┐ │ │
    │ │ │ appName: ob-2db57f43 │ │ │
    │ │ │ databaseBranch: │ │ │
    │ │ │ name: oceanbase-ce │ │ │
    │ │ │ version: 4.3.5.3 │ │ │
    │ │ │ isPaused: false │ │ │
    │ │ │ proxy: │ │ │
    │ │ │ replicas: 3 │ │ │
    │ │ │ resources: {…} │ │ │
    │ │ │ server: │ │ │
    │ │ │ replicas: 3 │ │ │
    │ │ │ resources: {…} │ │ │
    │ │ │ storages: […] │ │ │
    │ │ │ zone: […] │ │ │
    │ │ └─────────────────────────────────────────────┘ │ │
    │ └─────────────────────────────────────────────────────────────┘ │
    │ │
    │ ┌─────────────────────────────────────────────────────────────┐ │
    │ │ Status: 实际状态(Operator 填写) │ │
    │ │ ┌─────────────────────────────────────────────┐ │ │
    │ │ │ stage: AlreadyDeployed │ │ │
    │ │ │ parametersStatus: │ │ │
    │ │ │ proxyApplied: true │ │ │
    │ │ │ serverApplied: true │ │ │
    │ │ │ proxyStatus: │ │ │
    │ │ │ availableReplicas: 3 │ │ │
    │ │ │ expectedReplicas: 3 │ │ │
    │ │ │ serverStatus: │ │ │
    │ │ │ availableReplicas: 3 │ │ │
    │ │ │ expectedReplicas: 3 │ │ │
    │ │ │ status: │ │ │
    │ │ │ permitRollback: false │ │ │
    │ │ │ customStatus: available │ │ │
    │ │ │ fsmStatus: AC │ │ │
    │ │ └─────────────────────────────────────────────┘ │ │
    │ └─────────────────────────────────────────────────────────────┘ │
    │ │
    └─────────────────────────────────────────────────────────────────────┘


    四、调谐循环(Reconcile)代码实现

    4.1 完整的 Reconcile Loop 流程图

    ┌─────────────────────────────────────────────────────────────────────┐
    │ OceanBase Operator 完整工作流程 │
    ├─────────────────────────────────────────────────────────────────────┤
    │ │
    │ 【用户操作阶段】 │
    │ │
    │ 1. 用户编写 YAML 文件:ob-cluster.yaml │
    │ 2. kubectl apply -f ob-cluster.yaml │
    │ 3. Kubernetes API Server 创建 CR 实例 │
    │ │
    ├─────────────────────────────────────────────────────────────────────┤
    │ │
    │ 【Operator 处理阶段】 │
    │ │
    │ ┌─────────────────────────────────────────────────────────────┐ │
    │ │ 持续运行的 Reconcile Loop │ │
    │ │ │ │
    │ │ ┌─────────────────────────────────────────────┐ │ │
    │ │ │ 步骤 1: Watch(监听) │ │ │
    │ │ │ ┌─────────────────────────────────────┐ │ │
    │ │ │ │ • CR 创建/更新/删除 │ │ │
    │ │ │ │ • Pod 状态变化 │ │ │
    │ │ │ │ • ConfigMap/Secret 变化 │ │ │
    │ │ │ │ • PVC 状态变化 │ │ │
    │ │ │ └─────────────────────────────────────┘ │ │
    │ │ └─────────────────────────────────────────────┘ │ │
    │ │ │ │ │
    │ │ ▼ │ │
    │ │ ┌─────────────────────────────────────────────┐ │ │
    │ │ │ 步骤 2: 获取期望状态 │ │ │
    │ │ │ ┌─────────────────────────────────────┐ │ │
    │ │ │ │ 读取 CR.spec │ │ │
    │ │ │ │ • topology: 3 zones │ │ │
    │ │ │ │ • server.resource.* │ │ │
    │ │ │ │ • databaseBranch.version │ │ │
    │ │ │ └─────────────────────────────────────┘ │ │
    │ │ └─────────────────────────────────────────────┘ │ │
    │ │ │ │ │
    │ │ ▼ │ │
    │ │ ┌─────────────────────────────────────────────┐ │ │
    │ │ │ 步骤 3: 查询实际状态 │ │ │
    │ │ │ ┌─────────────────────────────────────┐ │ │
    │ │ │ │ kubectl get pods -l app=ob │ │ │
    │ │ │ │ kubectl get statefulsets │ │ │
    │ │ │ │ kubectl get services │ │ │
    │ │ │ │ 连接 OB 集群检查服务 │ │ │
    │ │ │ └─────────────────────────────────────┘ │ │
    │ │ └─────────────────────────────────────────────┘ │ │
    │ │ │ │ │
    │ │ ▼ │ │
    │ │ ┌─────────────────────────────────────────────┐ │ │
    │ │ │ 步骤 4: 比较 Diff │ │ │
    │ │ │ ┌─────────────────────────────────────┐ │ │
    │ │ │ │ 期望 vs 实际 │ │ │
    │ │ │ │ │ │ │
    │ │ │ │ replicas: 3 vs 2 → 扩容 │ │ │
    │ │ │ │ version: 4.3 vs 4.2 → 升级 │ │ │
    │ │ │ │ pod Crash → 重启 │ │ │
    │ │ │ │ storage 100Gi vs 80Gi → 扩容 │ │ │
    │ │ │ └─────────────────────────────────────┘ │ │
    │ │ └─────────────────────────────────────────────┘ │ │
    │ │ │ │ │
    │ │ ▼ │ │
    │ │ ┌─────────────────────────────────────────────┐ │ │
    │ │ │ 步骤 5: 执行调谐动作 │ │ │
    │ │ │ ┌─────────────────────────────────────┐ │ │
    │ │ │ │ kubectl apply -f … │ │ │
    │ │ │ │ 创建/更新 StatefulSet │ │ │
    │ │ │ │ 创建/更新 Service/ConfigMap │ │ │
    │ │ │ │ 扩缩容操作 │ │ │
    │ │ │ │ 滚动升级 │ │ │
    │ │ │ │ 添加/删除 PVC │ │ │
    │ │ │ └─────────────────────────────────────┘ │ │
    │ │ └─────────────────────────────────────────────┘ │ │
    │ │ │ │ │
    │ │ ▼ │ │
    │ │ ┌─────────────────────────────────────────────┐ │ │
    │ │ │ 步骤 6: 更新 Status │ │ │
    │ │ │ ┌─────────────────────────────────────┐ │ │
    │ │ │ │ 更新 CR.status.phase │ │ │
    │ │ │ │ 更新 CR.status.conditions │ │ │
    │ │ │ │ 更新 CR.status.availableReplicas │ │ │
    │ │ │ └─────────────────────────────────────┘ │ │
    │ │ └─────────────────────────────────────────────┘ │ │
    │ │ │ │ │
    │ │ ▼ │ │
    │ │ ┌─────────────────────────────────────────────┐ │ │
    │ │ │ 步骤 7: 重新入队(持续) │ │ │
    │ │ │ ┌─────────────────────────────────────┐ │ │
    │ │ │ │ 等待下次事件触发 │ │ │
    │ │ │ │ 或定时触发(如 5 分钟) │ │ │
    │ │ │ └─────────────────────────────────────┘ │ │
    │ │ └─────────────────────────────────────────────┘ │ │
    │ │ │ │ │
    │ └─────────────────────────────────────────────────────┘ │ │
    │ │
    │ └─────────────────────────────────────────────────────────────┘ │
    │ │
    └─────────────────────────────────────────────────────────────────────┘

    4.2 Reconcile 函数代码详解

    // Operator 的核心 Controller 结构
    package controller

    import (
    ctrl "sigs.k8s.io/controller-runtime"
    oceanbasev1 "oceanbase.woqutech.com/api/v1"
    appsv1 "k8s.io/api/apps/v1"
    corev1 "k8s.io/api/core/v1"
    )

    // OceanbaseClusterReconciler 是 Operator 的核心
    // +kubebuilder:rbac:groups=oceanbase.woqutech.com,resources=oceanbaseclusters,verbs=get;list;watch;create;update;patch;delete
    type OceanbaseClusterReconciler struct {
    client.Client // Kubernetes 客户端
    Scheme *runtime.Scheme // 注册所有相关的类型
    Recorder record.EventRecorder // 事件记录器
    }

    // SetupWithManager 注册 Controller
    func (r *OceanbaseClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
    return ctrl.NewControllerManagedBy(mgr).
    Named("oceanbasecluster"). // Controller 名称
    For(&oceanbasev1.OceanbaseCluster{}). // 监听的对象类型
    Owns(&appsv1.StatefulSet{}). // 拥有的资源类型
    Owns(&appsv1.Deployment{}). // 拥有的资源类型
    Owns(&corev1.Service{}). // 拥有的资源类型
    Owns(&corev1.ConfigMap{}). // 拥有的资源类型
    Build(r)
    }

    // Reconcile 是核心调谐函数
    func (r *OceanbaseClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // req.NamespacedName: ob-2db57f43
    // req.Namespace: qfusion-admin

    log := log.FromContext(ctx)
    log.Info("=== 开始调谐", "name", req.NamespacedName, "namespace", req.Namespace)

    obCluster := &oceanbasev1.OceanbaseCluster{}
    if err := r.Get(ctx, req.NamespacedName, req.Namespace, obCluster); err != nil {
    // CR 被删除了,不做任何操作
    return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // ===========================================
    // 步骤 1: 判断是否需要删除
    // ===========================================
    if !obCluster.DeletionTimestamp.IsZero() {
    log.Info("CR 被标记删除,执行清理")
    // 删除关联的所有资源
    r.deleteAllResources(ctx, obCluster)
    // 移除 finalizer
    if err := r.removeFinalizer(ctx, obCluster); err != nil {
    return ctrl.Result{}, err
    }
    return ctrl.Result{}, nil
    }

    // ===========================================
    // 步骤 2: 查询实际状态
    // ===========================================

    // 2.1 查询 StatefulSet
    statefulSet := &appsv1.StatefulSet{}
    statefulSetKey := types.NamespacedName{
    Namespace: req.Namespace,
    Name: fmt.Sprintf("%s-server", req.NamespacedName),
    }
    if err := r.Get(ctx, statefulSetKey, statefulSet); err != nil {
    if !errors.IsNotFound(err) {
    return ctrl.Result{}, err
    }
    // StatefulSet 不存在,需要创建
    log.Info("创建 StatefulSet", "replicas", obCluster.Spec.Server.Replicas)
    newStatefulSet := r.makeStatefulSet(obCluster)
    if err := r.Create(ctx, newStatefulSet); err != nil {
    return ctrl.Result{}, err
    }
    return ctrl.Result{RequeueAfter: 10 * time.Second}, nil
    }

    // 2.2 查询 Pods(可选,用于详细状态)
    podList := &corev1.PodList{}
    listOpts := []client.ListOption{
    client.MatchingLabels{
    "AppName": obCluster.Spec.AppName,
    },
    client.InNamespace(req.Namespace),
    }
    if err := r.List(ctx, podList, listOpts); err != nil {
    return ctrl.Result{}, err
    }

    // ===========================================
    // 步骤 3: 比较差异
    // ===========================================

    // 计算期望的副本数
    desiredReplicas := obCluster.Spec.Server.Replicas
    actualReplicas := *statefulSet.Spec.Replicas

    // 判断需要什么操作
    var action string
    if actualReplicas != desiredReplicas {
    if desiredReplicas > actualReplicas {
    // 需要扩容
    action = "扩容"
    statefulSet.Spec.Replicas = &desiredReplicas
    log.Info("扩容 StatefulSet", "from", actualReplicas, "to", desiredReplicas)
    } else {
    // 需要缩容
    action = "缩容"
    statefulSet.Spec.Replicas = &desiredReplicas
    log.Info("缩容 StatefulSet", "from", actualReplicas, "to", desiredReplicas)
    }
    // 执行更新
    if err := r.Update(ctx, statefulSet); err != nil {
    return ctrl.Result{}, err
    }
    } else {
    action = "无操作"
    }

    // ===========================================
    // 步骤 4: 更新 Service
    // ===========================================
    if err := r.ensureServices(ctx, obCluster); err != nil {
    return ctrl.Result{}, err
    }

    // ===========================================
    // 步骤 5: 更新 ConfigMap
    // ===========================================
    if err := r.ensureConfigMaps(ctx, obCluster); err != nil {
    return ctrl.Result{}, err
    }

    // ===========================================
    // 步骤 6: 更新 CR Status
    // ===========================================

    // 6.1 更新 ServerStatus
    obCluster.Status.ServerStatus.AvailableReplicas = actualReplicas
    obCluster.Status.ServerStatus.ExpectedReplicas = desiredReplicas

    // 6.2 更新 ProxyStatus
    proxyPodList := &corev1.PodList{}
    proxyListOpts := []client.ListOption{
    client.MatchingLabels{
    "AppName": fmt.Sprintf("%s-proxy", obCluster.Spec.AppName),
    },
    client.InNamespace(req.Namespace),
    }
    if err := r.List(ctx, proxyPodList, proxyListOpts); err == nil {
    obCluster.Status.ProxyStatus.AvailableReplicas = len(proxyPodList.Items)
    obCluster.Status.ProxyStatus.ExpectedReplicas = obCluster.Spec.Proxy.Replicas
    }

    // 6.3 更新阶段
    if actualReplicas == desiredReplicas {
    obCluster.Status.Stage = "Running"
    } else {
    obCluster.Status.Stage = "Updating"
    }

    // 6.4 执行更新
    if err := r.Status().Update(ctx, obCluster); err != nil {
    log.Error("更新 Status 失败", "error", err)
    return ctrl.Result{}, err
    }

    log.Info("调谐完成", "action", action, "replicas", actualReplicas)

    // ===========================================
    // 步骤 7: 返回结果,决定下次何时再次调谐
    // ===========================================

    if obCluster.Spec.IsPaused {
    // 暂停状态,不重新入队
    log.Info("集群已暂停,不继续调谐")
    return ctrl.Result{}, nil
    }

    // 正常情况,30 秒后再次调谐
    return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
    }


    五、状态机(State Machine)与事件

    5.1 Operator 状态机

    // 集群状态机定义
    type ClusterPhase string

    const (
    // ================================
    // 等待状态
    // ================================
    PhasePending ClusterPhase = "Pending" // 等待创建资源
    PhaseCreating ClusterPhase = "Creating" // 正在创建资源

    // ================================
    // 运行状态
    // ================================
    PhaseRunning ClusterPhase = "Running" // 正常运行
    PhaseUpgrading ClusterPhase = "Upgrading" // 正在升级
    PhaseScaling ClusterPhase = "Scaling" // 正在扩缩容

    // ================================
    // 错误状态
    // ================================
    PhaseFailed ClusterPhase = "Failed" // 创建/更新失败
    PhaseDegraded ClusterPhase = "Degraded" // 部分故障
    )

    // 状态转换规则
    var stateTransitions = map[ClusterPhase][]ClusterPhase{
    PhasePending: {PhaseCreating, PhaseFailed},
    PhaseCreating: {PhaseRunning, PhaseFailed},
    PhaseRunning: {PhaseScaling, PhaseUpgrading, PhaseDegraded, PhaseFailed},
    PhaseScaling: {PhaseRunning, PhaseDegraded, PhaseFailed},
    PhaseUpgrading: {PhaseRunning, PhaseDegraded, PhaseFailed},
    PhaseDegraded: {PhaseRunning, PhaseFailed},
    PhaseFailed: {}, // 终态
    }

    5.2 状态机流程图

    ┌─────────────────────────────────────────────────────────────┐
    │ Operator 状态机 │
    ├─────────────────────────────────────────────────────────────┤
    │ │
    │ ┌────┐ │
    │ │ Pending │ │
    │ └─┬─┘ │
    │ │ │
    │ ├──▶ Creating │
    │ │ │ │
    │ │ └─┬─┘ │
    │ │ ┌──────────┐ │
    │ │ │ Running │ │
    │ │ └─┬───┬───┬──────────┐ │
    │ │ │ │ │ └──┬────┘ │
    │ │ ▼ ▼ ▼ ▼ │
    │ │ Scaling Upgrading Degraded │
    │ │ │ │ │ └─┬───────┘ │
    │ │ │ │ │ ▼ │
    │ │ └─────┴────────┘ │ │
    │ │ │ │
    │ └─────────────────────────────────────────────┘ │
    │ │
    │ ▼ Failed
    │ │ │
    └─────────────────────────────────────────────────────┘

    5.3 Watch 事件驱动机制

    // Watch 事件类型定义
    const (
    // ================================
    // CR 事件(用户操作)
    // ================================
    EventAdded EventType = "Added" // CR 被创建
    EventUpdated EventType = "Updated" // CR 被更新
    EventDeleted EventType = "Deleted" // CR 被删除

    // ================================
    // 关联资源事件(系统状态变化)
    // ================================
    PodAdded EventType = "PodAdded" // Pod 创建
    PodReady EventType = "PodReady" // Pod Ready
    PodNotReady EventType = "PodNotReady" // Pod NotReady
    PodDeleted EventType = "PodDeleted" // Pod 删除
    )

    // Watch 处理逻辑(伪代码)
    func (r *OceanbaseClusterReconciler) setupWatch(mgr ctrl.Manager) error {
    return ctrl.NewControllerManagedBy(mgr).
    For(&oceanbasev1.OceanbaseCluster{}). // 监听 CR 变更

    // 关联资源 Watch
    Owns(&appsv1.StatefulSet{}). // 监听拥有的 StatefulSet
    Owns(&appsv1.Deployment{}). // 监听拥有的 Deployment
    Owns(&corev1.Service{}). // 监听拥有的 Service
    Owns(&corev1.ConfigMap{}). // 监听拥有的 ConfigMap

    // 设置事件处理器
    WithEventFilter(r.podFilter). // 过滤 Pod 事件
    WithEventFilter(r.serviceFilter). // 过滤 Service 事件

    Build(r)
    }

    // 事件过滤示例
    func (r *OceanbaseClusterReconciler) podFilter(eventObj client.Object) bool {
    pod, ok := eventObj.(*corev1.Pod)
    if !ok {
    return true
    }

    // 只关心属于当前集群的 Pod
    return pod.Labels["AppName"] == r.currentAppName
    }


    六、OceanBase 实战案例

    6.1 实际环境信息(脱敏)

    项目值
    目标环境 生产环境 Kubernetes 集群
    数据库标识 ob-2db57f43
    Operator OceanBase ob-operator (database-operator)
    命名空间 qfusion-admin

    6.2 验证步骤与实际输出

    # 1. 查看已注册的 OceanBase CRD
    $ kubectl get crd | grep oceanbase
    NAME CREATED AT
    oceanbaseclusters.oceanbase.woqutech.com 2026-01-22T04:19:53Z
    restores.oceanbase.woqutech.com 2026-01-22T04:19:53Z

    # 2. 查看已部署的 OceanbaseCluster 实例
    $ kubectl get oceanbasecluster -A
    NAMESPACE NAME AGE
    qfusion-admin ob-2db57f43 2d1h

    # 3. 查看 OceanBase 相关 Pods
    $ kubectl get pods -n qfusion-admin | grep ob-2db57f43
    NAME READY STATUS AGE
    ob-2db57f43-obproxy-0-0 1/1 Running 47h
    ob-2db57f43-obproxy-1-0 1/1 Running 47h
    ob-2db57f43-obproxy-2-0 1/1 Running 47h
    ob-2db57f43-observer-obzone1-0-0 2/2 Running 47h
    ob-2db57f43-observer-obzone2-0-0 2/2 Running 47h
    ob-2db57f43-observer-obzone3-0-0 2/2 Running 47h

    6.3 集群架构拓扑

    OceanBase 集群架构图

    OceanBase Operator (database-operator)
    监听 OceanbaseCluster CR 变化
    调谐集群状态

    Proxy 层 (OBProxy) – 3副本

    ob-2db57f43-obproxy-0-0 (Pod IP)
    ob-2db57f43-obproxy-1-0 (Pod IP)
    ob-2db57f43-obproxy-2-0 (Pod IP)
    Port: 2883 (SQL), 2884 (RPC)

    Observer 层 – 3 Zone

    Zone 1: obzone1 Zone 2: obzone2
    ┌───────────────────┐ ┌───────────────────┐
    │ observer Pod │ │ observer Pod │
    │ Port: 2881/2882 │ │ Port: 2881/2882 │
    └───────────────────┘ └───────────────────┘

    Zone 3: obzone3
    ┌───────────────────┐
    │ observer Pod │
    │ Port: 2881/2882 │
    └───────────────────┘

    Region: shanghai
    Storage: 26Gi datafile + 26Gi datalog per zone

    6.4 集群配置参数说明

    参数分类参数名值说明
    数据库版本 oceanbase-ce 4.3.5.3
    Proxy 副本数 replicas 3
    Proxy CPU limits 2 核
    Proxy 内存 limits 4Gi
    Server CPU cpu_count 4 核
    Server 内存 memory_limit 8Gi
    Datafile 大小 datafile_size 20G
    Log Disk 大小 log_disk_size 20G
    System Memory system_memory 3G
    存储类 StorageClass csi-localpv
    区域 Region shanghai
    分区 Zone obzone1, obzone2, obzone3

    七、通用学习指南

    7.1 学习任何 Operator 的六步法

    当你遇到任何新的 Operator 时,按照以下步骤学习:

    步骤 1: 找 CRD
    kubectl get crd | grep <app-name>
    kubectl describe crd <crd-name>
    kubectl get crd <crd-name> -o yaml

    步骤 2: 看结构 Schema
    kubectl explain <cr-name>
    kubectl explain <cr-name>.spec
    kubectl explain <cr-name>.status

    步骤 3: 看实例 CR
    kubectl get <cr-name> -A
    kubectl get <cr-name> <instance-name> -o yaml
    kubectl describe <cr-name> <instance-name>

    步骤 4: 理解状态 status
    关注 status 下的字段:
    • phase – 当前阶段
    • conditions – 健康检查条件
    • availableReplicas – 可用副本数
    • observedGeneration – 已处理的配置代次

    步骤 5: 看 Operator 日志
    kubectl get pods -n <operator-namespace> -l app=<operator-name>
    kubectl logs -n <operator-namespace> -l app=<operator-name> -f

    步骤 6: 看关联资源
    kubectl get all -l app=<cr-name>

    7.2 主流数据库 Operator 对比

    数据库CRD 名称Operator 项目核心功能
    MySQL mysqlclusters.mysql.com MySQL Operator 集群管理、备份、高可用
    PostgreSQL postgresclusters.postgresql.org Zalando Postgres Operator 集群管理、备份、版本升级
    MongoDB mongodbcommunity.mongodb.com MongoDB Atlas Operator 分片集群、备份
    Redis redis.redis.io Redis Operator 集群管理、持久化、哨兵模式
    Kafka kafka.strimzi.io Strimzi Kafka Operator 主题管理、消费者组、连接器
    Elasticsearch elasticsearch.k8s.elastic.co Elasticsearch Operator 节点管理、索引生命周期
    Prometheus monitoring.coreos.com Prometheus Operator Prometheus、Alertmanager、Thanos
    OceanBase oceanbaseclusters.oceanbase.woqutech.com ob-operator 集群管理、Proxy、Observer 管理
    TiDB tidbclusters.pingcap.com TiDB Operator 分布式数据库管理
    RabbitMQ rabbitmqclusters.rabbitmq.com RabbitMQ Cluster Operator 消息队列集群

    7.3 Operator 开发框架对比

    框架特点适用场景
    Kubebuilder 官方推荐,生成代码量少 大多数 Operator 开发
    Operator SDK 官方 SDK,简化开发 需要 Webhook 的 Operator
    KUDO 声明式编程,不需要写 Go 快速开发简单 Operator
    Headlamp 可视化 Operator 管理 需要 UI 的场景
    OAM Kubernetes 标准应用模型 需要应用模型的复杂系统

    附录:快速参考

    A. kubectl api-resources 命令详解

    # 列出所有 API 资源
    kubectl api-resources

    # 列出所有资源,显示额外信息
    kubectl api-resources -o wide

    # 列出特定资源组的资源
    kubectl api-resources –api-group=oceanbase.woqutech.com

    # 查看 CRD 详情
    kubectl get crd

    # 解释 CRD 结构
    kubectl explain oceanbasecluster
    kubectl explain oceanbasecluster.spec
    kubectl explain oceanbasecluster.status

    B. 常用调试命令

    # 查看 OceanBase 相关 CRD
    kubectl get crd | grep oceanbase

    # 查看所有 OceanbaseCluster 实例
    kubectl get oceanbasecluster -A

    # 查看特定 OceanbaseCluster 详情
    kubectl describe oceanbasecluster <name> -n <namespace>

    # 查看 OceanbaseCluster YAML
    kubectl get oceanbasecluster <name> -n <namespace> -o yaml

    # 编辑 OceanbaseCluster
    kubectl edit oceanbasecluster <name> -n <namespace>

    # 删除 OceanbaseCluster
    kubectl delete oceanbasecluster <name> -n <namespace>

    # 查看 Operator 日志
    kubectl logs -n <operator-namespace> -l app=<operator-name> -f

    # 查看 CR 变化事件
    kubectl get events -n <namespace> –field-selector involvedObject.kind=OceanbaseCluster

    C. 术语对照表

    中文英文缩写代码示例
    自定义资源定义 Custom Resource Definition CRD apiextensions.k8s.io/v1.CustomResourceDefinition
    自定义资源 Custom Resource CR v1alpha1.OceanbaseCluster{}
    操作器/运算符 Operator controller-runtime.Controller
    调谐循环 Reconcile Loop func Reconcile(…) ctrl.Result
    期望状态 Desired State cr.Spec
    实际状态 Actual State 实际运行的 Pod/StatefulSet 状态
    控制器 Controller 实现 Reconcile 逻辑的组件
    工作队列 WorkQueue workqueue.RateLimitingInterface
    事件过滤 Event Filter WithEventFilter()
    最终保护器 Finalizer cr.Finalizers[]
    观察代次 Observed Generation cr.Status.ObservedGeneration

    报告生成日期: 2026-03-05

    参考资料:

    • Kubernetes CRD 官方文档
    • Kubernetes Operator 模式文档
    • Kubebuilder 文档
    • Controller Runtime 文档
    • OceanBase ob-operator 仓库
    赞(0)
    未经允许不得转载:171主机测评 » Kubernetes Operator CRD/CR 深度解析报告
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址