Operator 模式基础回顾
在深入指标与告警集成之前,必须牢固掌握 Operator 模式的核心原理。Operator 本质上是将运维专家的领域知识编码为软件,通过 Kubernetes 原生机制自动管理复杂有状态应用。本节从概念、组件到循环机制逐层拆解。
2.1 Operator 概念与价值
Operator 是一种扩展 Kubernetes 平台的方法,它利用 自定义资源(CR) 和 自定义控制器 来封装特定应用或组件的运维逻辑。其核心价值在于将“人如何操作”转化为“机器如何自动执行”。
| 维度 | 传统运维 | Operator 模式 |
|---|---|---|
| 知识载体 | 运维手册、Runbook、个人经验 | 代码(Go / Ansible / Helm) |
| 执行方式 | 人工 SSH / 脚本触发 | Kubernetes 控制循环自动驱动 |
| 故障恢复 | 被动告警 + 人工介入 | 主动自愈 + 状态收敛 |
| 版本升级 | 手动执行升级脚本 | CR 字段变更触发滚动升级 |
| 扩展性 | 依赖外围工具链 | 原生 Kubernetes API 扩展 |
关键认知: Operator 不是简单的“部署工具”,而是将期望状态(Spec)与实际状态(Status)之间的差距,通过 Reconcile 循环持续缩小至零的闭环系统。
2.2 CRD 与 Controller 原理
Operator 由两大核心组件构成:自定义资源定义(CRD) 和 Controller。CRD 定义数据模型,Controller 实现业务逻辑。
2.2.1 自定义资源定义(CRD)
CRD 是 Kubernetes API 的扩展机制。通过声明 CRD,你可以定义新的资源类型(如 RedisCluster、Prometheus),Kubernetes 会像处理原生 Pod、Service 一样处理这些资源。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: redisclusters.cache.example.com
spec:
group: cache.example.com
names:
kind: RedisCluster
plural: redisclusters
singular: rediscluster
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
replicas:
type: integer
minimum: 1
version:
type: string
status:
type: object
properties:
readyReplicas:
type: integer
phase:
type: string
设计建议: CRD 的
spec 应只包含用户关心的业务参数(如副本数、版本),而 status 用于反映控制器观测到的实际状态(如就绪副本数、当前阶段)。避免将运维内部状态暴露给用户。
2.2.2 Controller 工作原理
Controller 是一个持续运行的循环,它通过 Informer 机制 监听 CR 和关联资源(如 Pod、Service)的变化。当事件发生时,Controller 将相关对象放入工作队列,由 Reconcile 函数处理。
- Watch: 使用 Informer 监听 CR 和 Owner 资源的变化(Add / Update / Delete)。
- Enqueue: 将变化事件转换为
ReconcileRequest(包含命名空间/名称)放入工作队列。 - Reconcile: 从队列取出请求,读取当前状态,对比期望状态,执行操作(创建/更新/删除子资源)。
- Update Status: 将最新的实际状态写回 CR 的
status字段。
2.3 Reconcile 循环机制
Reconcile 是 Operator 的核心执行单元。每次 Reconcile 请求都代表一次“将实际状态调整为期望状态”的尝试。理解其内部阶段是开发可靠 Operator 的基础。
2.3.1 标准 Reconcile 阶段
| 阶段 | 输入 | 输出 | 典型操作 |
|---|---|---|---|
| 1. 获取 CR | ReconcileRequest (ns/name) | CR 实例(或 NotFound) | r.Get(ctx, req.NamespacedName, &cr) |
| 2. 观测子资源 | CR 的 Spec 字段 | 当前子资源列表 | r.List(ctx, &pods, client.MatchingLabels(...)) |
| 3. 计算差异 | 期望状态 vs 实际状态 | 操作计划(创建/更新/删除) | 比较副本数、镜像版本、端口等 |
| 4. 执行操作 | 操作计划 | 子资源变更结果 | r.Create / r.Update / r.Delete |
| 5. 更新状态 | 最新实际状态 | CR.Status 更新 | r.Status().Update(ctx, &cr) |
| 6. 返回结果 | 成功 / 失败 / 重试 | ReconcileResult | ctrl.Result{Requeue: true} |
2.3.2 重试与背压机制
Reconcile 循环内置了智能重试策略,避免因临时故障导致 API Server 过载:
- 立即重试: 返回
Requeue: true,控制器会立即将请求重新入队。 - 延迟重试: 返回
RequeueAfter: 5 * time.Second,指定延迟时间后重试。 - 指数退避: 连续失败时,工作队列自动增加重试间隔(默认 5ms → 300s)。
- 最大重试次数: 超过阈值后,请求被丢弃并记录 Error 事件。
常见陷阱: 不要在 Reconcile 函数内使用
time.Sleep 实现延迟。这会阻塞整个工作队列的消费者 goroutine,导致其他 CR 的 Reconcile 被饿死。应始终使用 RequeueAfter 机制。
2.4 指标与告警的切入点
理解 Reconcile 循环后,就能精准定位指标采集和告警规则的位置:
- Reconcile 耗时: 每次 Reconcile 的执行时长,反映控制器性能瓶颈。
- Reconcile 错误率: 返回错误结果的 Reconcile 次数,直接反映运维健康度。
- 工作队列深度: 等待处理的 Reconcile 请求数量,预示控制器是否积压。
- CR 状态相位: 自定义资源当前处于
Running、Failed、Pending等状态。 - 子资源偏差: 期望副本数与实际运行副本数的差值。
实战要点: 在 Reconcile 函数的入口和出口处埋点,使用 Prometheus Histogram 记录耗时,使用 Counter 记录错误。这些指标将成为后续告警规则的直接数据源。