You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:如何开始为Custom Resource创建Custom Controller?

自定义控制器与自定义资源入门指南

一、先搞懂Custom Resource(CR)能做什么

  • 扩展Kubernetes的API体系,让你定义专属的资源类型(比如RedisCluster、MyBusinessApp),和K8s内置的Deployment、Pod一样,用kubectl命令统一管理
  • 把业务逻辑抽象成K8s资源对象,比如你可以定义一个DatabaseCluster CR,指定副本数、存储容量,由控制器自动帮你创建对应的StatefulSet、PersistentVolumeClaim、Service等资源
  • 统一业务与K8s生态的管理方式,用kubectl apply提交业务配置,用kubectl get查看业务状态,不需要单独维护一套业务管理工具

二、从零开始的启动步骤

1. 定义Custom Resource Definition(CRD)

这是第一步,先告诉K8s你的自定义资源是什么结构。创建一个crd.yaml文件:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: myapps.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
                image:
                  type: string
  scope: Namespaced
  names:
    plural: myapps
    singular: myapp
    kind: MyApp
    shortNames:
    - ma

执行kubectl apply -f crd.yaml提交到集群,之后你就能像操作内置资源一样创建MyApp类型的CR了。

2. 编写控制器Go代码(核心逻辑)

控制器的核心是监听CR的变化,执行对应业务逻辑,推荐用K8s官方的controller-runtime框架(简化开发流程),核心流程如下:

  • 初始化K8s客户端:本地开发用~/.kube/config连接集群,集群内部署用ServiceAccount自动认证
  • 注册要监听的CR类型,设置控制器的调和(Reconcile)逻辑
  • 实现Reconcile函数:这是控制器的核心入口,CR创建/更新/删除时都会触发,你在这里写具体的业务逻辑(比如根据CR的spec创建Deployment)

示例Reconcile函数片段:

func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // 1. 获取目标MyApp实例
    var myapp examplev1.MyApp
    if err := r.Get(ctx, req.NamespacedName, &myapp); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // 2. 检查对应的Deployment是否存在,不存在则创建
    var deploy appsv1.Deployment
    deployName := myapp.Name
    err := r.Get(ctx, types.NamespacedName{Name: deployName, Namespace: myapp.Namespace}, &deploy)
    if err != nil && apierrors.IsNotFound(err) {
        // 构造Deployment对象
        deploy = appsv1.Deployment{
            ObjectMeta: metav1.ObjectMeta{
                Name:      deployName,
                Namespace: myapp.Namespace,
            },
            Spec: appsv1.DeploymentSpec{
                Replicas: &myapp.Spec.Replicas,
                Template: corev1.PodTemplateSpec{
                    Spec: corev1.PodSpec{
                        Containers: []corev1.Container{
                            {
                                Name:  "myapp",
                                Image: myapp.Spec.Image,
                            },
                        },
                    },
                },
            },
        }
        if err := r.Create(ctx, &deploy); err != nil {
            return ctrl.Result{}, err
        }
        return ctrl.Result{Requeue: true}, nil
    }

    // 3. 如果Deployment副本数与CR不一致,更新Deployment
    if *deploy.Spec.Replicas != myapp.Spec.Replicas {
        deploy.Spec.Replicas = &myapp.Spec.Replicas
        if err := r.Update(ctx, &deploy); err != nil {
            return ctrl.Result{}, err
        }
    }

    return ctrl.Result{}, nil
}

3. 运行控制器的两种方式

  • 本地开发调试:
    确保本地有kubeconfig文件(默认在~/.kube/config),直接运行Go程序:go run main.go,控制器会自动连接到你的K8s集群(minikube、远程集群都可以)
  • 部署到K8s集群:
    1. 把控制器代码打包成Docker镜像,推送到镜像仓库
    2. 创建Deployment运行控制器,同时创建ServiceAccount并分配必要权限(比如读取MyApp、创建Deployment的权限)
      示例Deployment片段:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp-controller
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: myapp-controller
      template:
        metadata:
          labels:
            app: myapp-controller
        spec:
          serviceAccountName: myapp-controller-sa
          containers:
          - name: controller
            image: your-registry/myapp-controller:v1
            args:
            - --metrics-addr=127.0.0.1:8080
            - --enable-leader-election
    

4. 测试验证

创建一个myapp-sample.yaml:

apiVersion: example.com/v1
kind: MyApp
metadata:
  name: myapp-sample
spec:
  replicas: 2
  image: nginx:latest

执行kubectl apply -f myapp-sample.yaml,然后用kubectl get deploy检查是否自动创建了对应副本数的Deployment;修改CR的replicas值,再看Deployment是否同步更新。

三、关键切入点总结

  1. 先完成CRD定义,确保自定义资源能被K8s正确识别
  2. 基于controller-runtime搭建控制器基础结构,重点实现Reconcile函数的业务逻辑
  3. 本地调试验证逻辑正确性后,再打包部署到集群
  4. 逐步扩展功能,比如处理资源删除、错误重试、状态更新等

内容的提问来源于stack exchange,提问作者Deepak singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 02:40:32