3. Operator 核心概念:CRD、CR、Controller 与 Manager 深度解析

在 Operator 开发中,CRD(Custom Resource Definition)、CR(Custom Resource)、Controller 与 Manager 构成了最核心的抽象层。理解这四者的关系与工作原理,是编写稳定、可测试 Operator 的基础。

核心关系速览:CRD 定义“是什么”(资源结构),CR 表达“要什么”(期望状态),Controller 负责“做什么”(调谐逻辑),Manager 管理“怎么活”(生命周期与依赖)。

3.1 CRD 与 CR:资源定义与实例

3.1.1 什么是 CRD?

CRD 是一种 Kubernetes API 扩展机制,允许你定义新的资源类型。它本质上是一个 API 资源的蓝图,描述了该资源的名称、作用域(Namespaced / Cluster)、版本以及 OpenAPI v3 校验 schema。

属性 说明 典型值
group API 组,用于逻辑分组 example.com
names.kind 资源类型名称,首字母大写 MyApp
names.plural 复数名称,用于 URL 路径 myapps
scope 资源作用域 Namespaced 或 Cluster
versions[].schema OpenAPI v3 结构定义 包含 spec 和 status 字段

3.1.2 什么是 CR?

CR 是 CRD 的一个具体实例,类似于面向对象编程中“类”与“对象”的关系。用户通过提交 CR 的 YAML 清单,向 Kubernetes 声明一个期望的应用状态。

apiVersion: example.com/v1
kind: MyApp
metadata:
  name: myapp-sample
spec:
  replicas: 3
  image: nginx:1.25
  serviceType: ClusterIP
测试要点:在自动化测试中,CRD 的 schema 校验是第一个验证点。测试应覆盖:必填字段缺失、字段类型错误、枚举值越界、额外字段拒绝等场景。CR 的创建/更新/删除操作应作为每个测试用例的起点。

3.1.3 CRD 与 CR 的关系图

CRD 与 CR 的关系 CRD (自定义资源定义) kind: MyApp group: example.com/v1 schema: spec, status CR (自定义资源实例) name: myapp-sample spec.replicas: 3 spec.image: nginx:1.25 实例化 测试验证关键点 • CRD 注册后,K8s API Server 才能识别 CR 的 YAML • CR 的 spec 必须严格符合 CRD 定义的 schema

3.2 Controller:调谐循环的核心

3.2.1 工作原理

Controller 是一个持续运行的调谐循环(Reconciliation Loop)。它监听 CR 或其他资源的变化,将当前状态调整为期望状态。每次调谐包含四个步骤:

  1. 观察(Watch):通过 Informer 监听 CR 及关联资源的事件(Add/Update/Delete)。
  2. 读取(Read):从 API Server 获取当前 CR 实例及集群当前状态。
  3. 比较(Diff):对比期望状态(CR.spec)与当前状态(Deployment、Service 等)。
  4. 执行(Act):创建、更新或删除子资源,使集群状态趋近期望状态。
// 伪代码:调谐循环核心逻辑
func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // 1. 获取 CR 实例
    myApp := &examplev1.MyApp{}
    if err := r.Get(ctx, req.NamespacedName, myApp); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // 2. 期望状态:从 CR.spec 中提取
    desiredReplicas := myApp.Spec.Replicas

    // 3. 当前状态:查询 Deployment
    deployment := &appsv1.Deployment{}
    // ... 查询逻辑

    // 4. 比较并执行调谐
    if currentReplicas != desiredReplicas {
        // 更新 Deployment
    }

    return ctrl.Result{}, nil
}

3.2.2 Controller 的稳定性测试要点

测试维度 测试场景 预期行为
事件触发 创建/更新/删除 CR Controller 在合理时间内触发调谐
幂等性 重复调谐同一 CR 不产生重复资源,状态不漂移
错误恢复 API Server 临时不可用 重试队列机制生效,不丢失事件
并发安全 多个 CR 同时变更 调谐互不干扰,无竞态条件

3.3 Manager:Controller 的运行时容器

3.3.1 Manager 的职责

Manager 是 controller-runtime 库提供的顶层抽象,负责管理多个 Controller 的生命周期、共享依赖和健康状态。它解决了以下问题:

  • 共享客户端:所有 Controller 共用同一个缓存 Client,减少 API Server 压力。
  • Leader 选举:高可用部署时,确保同一时刻只有一个 Manager 实例执行调谐。
  • 健康探针:内置 /healthz 和 /readyz 端点,供 Kubernetes 存活/就绪检查。
  • 优雅关闭:收到 SIGTERM 信号时,等待正在执行的调谐完成再退出。
// Manager 初始化示例
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
    Scheme:             scheme,
    MetricsBindAddress: ":8080",
    HealthProbeBindAddress: ":8081",
    LeaderElection:     true,
    LeaderElectionID:   "myapp-operator-lock",
})
if err != nil {
    setupLog.Error(err, "unable to start manager")
    os.Exit(1)
}

// 注册 Controller 到 Manager
if err = (&controllers.MyAppReconciler{
    Client: mgr.GetClient(),
    Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
    setupLog.Error(err, "unable to create controller")
    os.Exit(1)
}

// 启动 Manager(阻塞)
if err := mgr.Start(ctx); err != nil {
    setupLog.Error(err, "problem running manager")
    os.Exit(1)
}

3.4 Controller 与 Manager 的协作架构

Controller 与 Manager 协作架构 Manager(运行时容器) 共享 Client 缓存 + 读/写 Leader 选举 高可用锁 健康探针 /healthz /readyz Controller A (MyApp) 调谐 MyApp CR 管理 Deployment/Service Controller B (Backup) 调谐 Backup CR 管理 CronJob/PVC 自动化测试关注点 • Manager 启动/停止时,Controller 是否正常注册与注销 • Leader 选举切换时,调谐是否出现重复执行或丢失

3.5 四者协作的完整流程

当用户提交一个 CR 后,Operator 内部的工作流程如下:

  1. API Server 校验:根据 CRD 的 schema 验证 CR 的合法性,存入 etcd。
  2. Informer 通知:Manager 内部的 Informer 监听到 CR 创建事件,将事件放入工作队列。
  3. 调谐触发:Controller 的工作线程从队列中取出事件,调用 Reconcile() 函数。
  4. 状态读取:通过共享 Client 读取 CR 及关联资源(Deployment、Service 等)。
  5. 差异计算:对比期望状态(CR.spec)与当前状态,生成操作列表。
  6. 资源操作:调用 Kubernetes API 创建/更新/删除子资源。
  7. 状态更新:将调谐结果写回 CR 的 status 字段,供用户或其他组件读取。
稳定性陷阱:如果 Controller 在调谐过程中崩溃,Manager 的优雅关闭机制会等待当前调谐完成(最多等待 GracefulShutdownTimeout)。测试中应模拟 SIGTERM 信号,验证未完成的调谐是否被正确重入或丢弃,避免资源状态不一致。

3.6 自动化测试中的核心验证点

组件 验证项 测试方法
CRD Schema 校验、版本兼容性 创建非法 CR 应被 API Server 拒绝;多版本 CRD 应支持转换
CR 创建/更新/删除生命周期 通过 kubectl 或 client-go 操作 CR,验证最终状态
Controller 调谐幂等性、错误重试、并发安全 重复调谐同一 CR;注入 API 错误;并发创建多个 CR
Manager Leader 选举、健康探针、优雅关闭 启动两个副本,验证只有一个 Leader;访问 /healthz;发送 SIGTERM
测试框架建议:使用 envtest(controller-runtime 内置)在本地启动轻量级 API Server 和 etcd,无需真实集群即可测试 CRD 注册、CR 操作和 Controller 调谐逻辑。这是 Operator 单元测试和集成测试的标准实践。