Skip to content

17 — Operator 开发深度教材

Operator 是 K8s 运维自动化的终极形态。本章覆盖 CRD 设计、Kubebuilder、Reconciliation、Status 管理、最佳实践。


1. Operator 模式原理

Operator = CRD(自定义资源) + Controller(自定义控制器)

CRD 定义用户资源结构:
  apiVersion: example.com/v1
  kind: WebApp
  spec:
    replicas: 3
    image: myapp:v1
  status:
    readyReplicas: 3
    phase: Running

Controller 实现调谐逻辑:
  Watch CRD 变更 → Reconcile(调谐)→ 更新 Status
  
  Reconcile 职责:
  1. 读取 CRD Spec(期望状态)
  2. 读取集群实际状态(Deployment/Service/Pod)
  3. 对比差异,执行动作(创建/更新/删除)
  4. 更新 Status(实际状态)

2. Kubebuilder 快速开发

bash
# 初始化项目
kubebuilder init --domain example.com --repo github.com/org/myoperator

# 创建 CRD 和 Controller
kubebuilder create api --group apps --version v1 --kind WebApp --resource --controller

# 生成的目录结构:
# api/v1/webapp_types.go    → CRD 结构定义
# controllers/webapp_controller.go → 调谐逻辑
# config/                    → RBAC、CRD YAML、Manager 配置

# 开发流程
# 1. 修改 api/v1/webapp_types.go 定义 Spec/Status
# 2. make generate → 生成 deepcopy 方法
# 3. make manifests → 生成 CRD YAML
# 4. 实现 controllers/webapp_controller.go 调谐逻辑
# 5. make install → 安装 CRD 到集群
# 6. make run → 本地运行 Controller

3. Reconciliation 实现

go
// controllers/webapp_controller.go
func (r *WebAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    log := ctrllog.FromContext(ctx)
    
    // 1. 获取 CRD 实例
    var webapp appsv1.WebApp
    if err := r.Get(ctx, req.NamespacedName, &webapp); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }
    
    // 2. 调谐 Deployment
    deploy := &appsv1.Deployment{
        ObjectMeta: metav1.ObjectMeta{
            Name:      webapp.Name,
            Namespace: webapp.Namespace,
        },
    }
    _, err := controllerutil.CreateOrUpdate(ctx, r.Client, deploy, func() error {
        deploy.Spec.Replicas = &webapp.Spec.Replicas
        deploy.Spec.Template.Spec.Containers = []corev1.Container{{
            Name:  "app",
            Image: webapp.Spec.Image,
        }}
        return controllerutil.SetControllerReference(&webapp, deploy, r.Scheme)
    })
    
    // 3. 更新 Status
    webapp.Status.ReadyReplicas = deploy.Status.ReadyReplicas
    r.Status().Update(ctx, &webapp)
    
    return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
}

4. 生产最佳实践

1. 幂等性:Reconcile 多次执行结果一致
2. 错误处理:返回错误会自动重试(指数退避)
3. Finalizer:资源删除前执行清理逻辑
4. Owner Reference:子资源自动级联删除
5. Status 条件:使用 Conditions 表达状态
6. Webhook:校验 CRD 合法性
7. Leader Election:多副本时只有一个活跃
8. RBAC:最小权限原则
yaml
# Finalizer 示例
metadata:
  finalizers:
  - example.com/cleanup
# Controller 在删除前执行清理,然后移除 finalizer

5. 面试高频问题

Q: Operator 和 Helm Chart 有什么区别?

Helm Chart:
  - 静态模板渲染 + kubectl apply
  - 无状态:安装后不监控、不调谐
  - 适合:简单应用部署

Operator:
  - 动态调谐 + 状态管理
  - 有状态:持续监控、自动修复、自动升级
  - 适合:复杂有状态应用(数据库、消息队列)

结合使用:
  Helm 安装 Operator → Operator 管理 CRD 资源