Operator模式 #

一、Operator概述 #

Operator是Kubernetes的扩展模式,用于自动化管理复杂应用。

1.1 Operator概念 #

text
Operator组成
    │
    ├── CRD (Custom Resource Definition)
    │   └── 自定义资源定义
    │
    ├── CR (Custom Resource)
    │   └── 自定义资源实例
    │
    └── Controller
        └── 控制器逻辑

1.2 Operator优势 #

优势 说明
自动化管理 自动化运维任务
声明式配置 声明期望状态
知识封装 封装运维知识
可扩展性 扩展Kubernetes

二、CRD定义 #

2.1 创建CRD #

yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: applications.example.com
spec:
  group: example.com
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                replicas:
                  type: integer
                  minimum: 1
                  maximum: 10
                image:
                  type: string
                version:
                  type: string
            status:
              type: object
              properties:
                availableReplicas:
                  type: integer
                conditions:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                      status:
                        type: string
  scope: Namespaced
  names:
    plural: applications
    singular: application
    kind: Application
    shortNames:
    - app

2.2 创建CR #

yaml
apiVersion: example.com/v1
kind: Application
metadata:
  name: myapp
spec:
  replicas: 3
  image: nginx
  version: "1.25"

2.3 查看CRD #

bash
# 查看CRD列表
kubectl get crd

# 查看CRD详情
kubectl describe crd applications.example.com

# 查看CR
kubectl get applications
kubectl get app

三、Controller开发 #

3.1 Controller架构 #

text
Controller架构
    │
    ├── Informer
    │   └── 监听资源变化
    │
    ├── WorkQueue
    │   └── 工作队列
    │
    ├── Reconcile
    │   └── 调谐逻辑
    │
    └── Cache
        └── 资源缓存

3.2 使用kubebuilder创建Operator #

bash
# 安装kubebuilder
curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)
chmod +x kubebuilder && mv kubebuilder /usr/local/bin/

# 创建项目
mkdir myoperator
cd myoperator
kubebuilder init --domain example.com --repo example.com/myoperator

# 创建API
kubebuilder create api --group example --version v1 --kind Application

# 安装CRD
make install

# 运行Controller
make run

3.3 Reconcile逻辑 #

go
// application_controller.go
func (r *ApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    log := log.FromContext(ctx)

    // 获取Application实例
    var app examplev1.Application
    if err := r.Get(ctx, req.NamespacedName, &app); err != nil {
        log.Error(err, "unable to fetch Application")
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // 检查Deployment是否存在
    var deploy appsv1.Deployment
    err := r.Get(ctx, req.NamespacedName, &deploy)
    if err != nil && errors.IsNotFound(err) {
        // 创建Deployment
        deploy := r.createDeployment(&app)
        if err := r.Create(ctx, deploy); err != nil {
            log.Error(err, "unable to create Deployment")
            return ctrl.Result{}, err
        }
        return ctrl.Result{Requeue: true}, nil
    }

    // 更新Deployment
    if !reflect.DeepEqual(deploy.Spec.Replicas, app.Spec.Replicas) {
        deploy.Spec.Replicas = &app.Spec.Replicas
        if err := r.Update(ctx, &deploy); err != nil {
            return ctrl.Result{}, err
        }
    }

    // 更新状态
    app.Status.AvailableReplicas = deploy.Status.AvailableReplicas
    if err := r.Status().Update(ctx, &app); err != nil {
        return ctrl.Result{}, err
    }

    return ctrl.Result{}, nil
}

3.4 完整Controller示例 #

go
// application_types.go
type ApplicationSpec struct {
    Replicas int32  `json:"replicas"`
    Image    string `json:"image"`
    Version  string `json:"version"`
}

type ApplicationStatus struct {
    AvailableReplicas int32 `json:"availableReplicas"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
type Application struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   ApplicationSpec   `json:"spec,omitempty"`
    Status ApplicationStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
type ApplicationList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata,omitempty"`
    Items           []Application `json:"items"`
}

func init() {
    SchemeBuilder.Register(&Application{}, &ApplicationList{})
}

四、Operator SDK #

4.1 使用Operator SDK #

bash
# 安装Operator SDK
curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.28.0/operator-sdk_linux_amd64
chmod +x operator-sdk_linux_amd64 && sudo mv operator-sdk_linux_amd64 /usr/local/bin/operator-sdk

# 创建项目
operator-sdk init --domain example.com --repo github.com/example/myoperator

# 创建API
operator-sdk create api --group example --version v1 --kind Application --resource --controller

# 创建Webhook
operator-sdk create webhook --group example --version v1 --kind Application --defaulting --programmatic-validation

4.2 Webhook配置 #

go
// application_webhook.go
func (r *Application) ValidateCreate() error {
    if r.Spec.Replicas < 1 {
        return fmt.Errorf("replicas must be at least 1")
    }
    return nil
}

func (r *Application) ValidateUpdate(old runtime.Object) error {
    if r.Spec.Replicas < 1 {
        return fmt.Errorf("replicas must be at least 1")
    }
    return nil
}

func (r *Application) Default() {
    if r.Spec.Replicas == 0 {
        r.Spec.Replicas = 1
    }
}

五、Operator部署 #

5.1 构建镜像 #

bash
# 构建镜像
make docker-build IMG=myoperator:v1.0.0

# 推送镜像
make docker-push IMG=myoperator:v1.0.0

5.2 部署Operator #

bash
# 部署CRD
make install

# 部署Controller
make deploy IMG=myoperator:v1.0.0

# 查看部署
kubectl get pods -n myoperator-system

5.3 使用Operator #

yaml
# 创建Application
apiVersion: example.com/v1
kind: Application
metadata:
  name: myapp
spec:
  replicas: 3
  image: nginx
  version: "1.25"
bash
# 创建Application
kubectl apply -f application.yaml

# 查看状态
kubectl get application myapp -o yaml

# 查看创建的资源
kubectl get deployment
kubectl get pods

六、Operator最佳实践 #

6.1 设计原则 #

text
Operator设计原则
    │
    ├── 单一职责
    │   └── 一个Operator管理一种资源
    │
    ├── 幂等性
    │   └── Reconcile可重复执行
    │
    ├── 状态管理
    │   └── 正确更新状态
    │
    └── 错误处理
        └── 合理处理错误和重试

6.2 状态条件 #

go
// 更新状态条件
func (r *ApplicationReconciler) updateStatus(ctx context.Context, app *examplev1.Application, conditionType string, status metav1.ConditionStatus, reason, message string) error {
    condition := metav1.Condition{
        Type:               conditionType,
        Status:             status,
        Reason:             reason,
        Message:            message,
        LastTransitionTime: metav1.Now(),
    }
    
    meta.SetStatusCondition(&app.Status.Conditions, condition)
    return r.Status().Update(ctx, app)
}

七、总结 #

7.1 核心要点 #

概念 说明
CRD 自定义资源定义
CR 自定义资源实例
Controller 控制器逻辑
Reconcile 调谐循环

7.2 下一步 #

掌握了Operator后,让我们学习 资源限制,了解Kubernetes资源管理机制。

最后更新:2026-03-28