首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Kubernetes 开发自定义CRD资源

Kubernetes 开发自定义CRD资源

作者头像
用户11081884
发布2026-07-20 18:38:50
发布2026-07-20 18:38:50
1970
举报
文章被收录于专栏:科技专栏科技专栏

Kubernetes(简称K8s)已成为容器编排领域的事实标准。其强大之处不仅在于内置的资源管理能力,更在于其高度可扩展的架构设计。自定义资源定义(Custom Resource Definition,CRD)作为Kubernetes的核心扩展机制,允许用户在不修改Kubernetes源代码的情况下,扩展API以管理自定义资源类型。本文将全面介绍CRD的概念、设计原则、开发流程及最佳实践,帮助开发者掌握这一强大工具。

一、CRD基础概念

1. CRD的定义:

CRD全称为Custom Resource Definition,是Kubernetes中用于定义自定义资源类型的机制。通过CRD,用户可以将特定业务逻辑抽象为Kubernetes原生资源,使其能够像内置资源(如Pod、Deployment)一样被API服务器管理。

2、CRD的核心价值:

  • API扩展性:无需修改Kubernetes核心代码即可扩展API功能;
  • 统一管理:自定义资源与内置资源使用相同的工具链(kubectl、API等)进行管理;
  • 声明式API:支持声明式配置,符合Kubernetes设计哲学;
  • 生态整合:可与Operator模式结合,实现复杂业务逻辑的自动化;

3. CRD与相关概念的关系:

Kubernetes生态中,CRD常与几个关键概念相关联:

  • Custom Resource (CR)CRD定义的是资源类型,而CR是该类型的实例。例如,定义“Database” CRD后,创建的“mysql-production”就是一个CR
  • Controller:仅定义CRD而不编写控制器,资源将缺乏实际功能。控制器负责监视CR状态并确保集群实际状态与期望状态一致。
  • Operator:Operator模式CRD+Custom Controller,是管理复杂有状态应用的成熟模式。例如MongoDB Operator就是通过CRD定义MongoDB集群资源,然后由控制器实现部署、扩缩容等操作。

4、CRD 与控制器关系

  • CRD:仅定义资源结构(字段、类型),不包含逻辑。
  • 控制器:监听 CRD 实例的事件(创建/更新/删除),执行调和循环(Reconcile Loop)确保实际状态匹配期望状态。

二、CRD 的设计

开发高质量的CRD需要考虑以下关键因素:

API设计方面:

  • 版本兼容性:采用/格式明确API版本,如example.com/v1,并考虑后续版本演进;
  • 字段设计:明确区分spec(用户期望状态)和status(系统实际状态)字段;
  • 命名规范:遵循DNS子域名规则(小写字母、数字、’-’,不超过253字符);

功能完整性:

  • 验证规则:通过OpenAPI v3 Schema定义字段类型、必填项和默认值
  • 作用域:合理选择NamespacedCluster作用域
  • 子资源:支持/status、/scale等子资源以实现更丰富功能

三、开发自定义的 CRD

1. 定义 CRD 结构(YAML)

通过 OpenAPI Schema 声明字段类型和验证规则:

代码语言:javascript
复制
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: apps.example.com
spec:
  group: example.com
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:  # 字段验证规则
          type: object
          properties:
            spec:
              type: object
              properties:
                appName: { type: string }
                replicas: { type: integer }
                image: { type: string }
  scope: Namespaced       # 命名空间级资源
  names:
    plural: apps          # API 路径:/apis/example.com/v1/apps
    singular: app
    kind: App
    shortNames: ["ap"]    # kubectl get ap 简写

关键字段说明

  • scopeNamespaced(命名空间内)或Cluster(集群级)。
  • validation:通过 OpenAPI Schema 限制字段类型(如 string/integer)。
2. 部署 CRD 到集群
代码语言:javascript
复制
kubectl apply -f app-crd.yaml
kubectl get crd              # 验证 CRD 是否注册成功
3. 创建 CRD 实例

定义资源实例的 YAML:

代码语言:javascript
复制
apiVersion: example.com/v1
kind: App
metadata:
  name: myapp
spec:
  appName: "my-application"
  replicas: 3
  image: "nginx:1.25"

应用实例:

代码语言:javascript
复制
kubectl apply -f myapp.yaml
kubectl get apps            # 查看自定义资源

4、开发控制器(Controller)

1) 工具选择
  • KubebuilderOperator SDK:主流框架,自动生成项目脚手架和 CRD 代码。
  • 安装 Kubebuilder:
代码语言:javascript
复制
curl -L -o kubebuilder https://github.com/kubernetes-sigs/kubebuilder/releases/download/v3.10.0/kubebuilder_linux_amd64
chmod +x kubebuilder && sudo mv kubebuilder /usr/local/bin/
2)控制器逻辑示例(Go)

controllers/app_controller.go 中实现调和逻辑:

代码语言:javascript
复制
func (r *AppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
  // 获取 App 实例
  app := &examplev1.App{}
  if err := r.Get(ctx, req.NamespacedName, app); err != nil {
      return ctrl.Result{}, client.IgnoreNotFound(err)
  }

  // 根据 app.Spec 创建 Deployment
  deployment := &appsv1.Deployment{
      ObjectMeta: metav1.ObjectMeta{Name: app.Name, Namespace: app.Namespace},
      Spec: appsv1.DeploymentSpec{
          Replicas: &app.Spec.Replicas,
          Template: corev1.PodTemplateSpec{
              Spec: corev1.PodSpec{
                  Containers: []corev1.Container{{
                      Name:  "app",
                      Image: app.Spec.Image,
                  }},
              },
          },
      },
  }
  if err := r.Create(ctx, deployment); err != nil {
      return ctrl.Result{}, err
  }

  // 更新状态
  app.Status.Replicas = *deployment.Spec.Replicas
  if err := r.Status().Update(ctx, app); err != nil {
      return ctrl.Result{}, err
  }
  return ctrl.Result{}, nil
}

关键逻辑

  • 监听 App 资源变更,自动创建 Deployment
  • 更新 Appstatus字段反馈实际状态。
3)部署控制器
代码语言:javascript
复制
make manifests  # 生成 CRD 配置
make install    # 部署 CRD
make run        # 运行控制器

5、调试与验证

1)检查 CRD 状态

代码语言:javascript
复制
kubectl get crd apps.example.com -o yaml
kubectl describe app myapp    # 查看事件和状态

2)控制器日志

代码语言:javascript
复制
kubectl logs -l control-plane=controller-manager -c manager

3)触发扩缩容测试

修改 myapp.yaml中的replicas字段,观察 Deployment 是否自动调整。

6、进阶实践

1)Finalizers 机制 防止资源误删,确保删除前执行清理逻辑(如释放外部资源):

代码语言:javascript
复制
app.SetFinalizers([]string{"cleanup.external.com"})

通过Finalizers实现优雅删除:

代码语言:javascript
复制
// 在控制器中添加finalizer
func (r *ApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    app := &appv1.Application{}
    if err := r.Get(ctx, req.NamespacedName, app); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // 检查删除标记
    if app.ObjectMeta.DeletionTimestamp.IsZero() {
        if !controllerutil.ContainsFinalizer(app, finalizerName) {
            controllerutil.AddFinalizer(app, finalizerName)
            if err := r.Update(ctx, app); err != nil {
                return ctrl.Result{}, err
            }
        }
    } else {
        // 执行清理逻辑
        if controllerutil.ContainsFinalizer(app, finalizerName) {
            if err := r.cleanupExternalResources(app); err != nil {
                return ctrl.Result{}, err
            }
            controllerutil.RemoveFinalizer(app, finalizerName)
            if err := r.Update(ctx, app); err != nil {
                return ctrl.Result{}, err
            }
        }
        return ctrl.Result{}, nil
    }
    // 正常调和逻辑...
}

2)多版本支持

支持多版本并存并平滑升级:

代码语言:javascript
复制
versions:
  - name: v1beta1
    served: true  # 提供此版本API
    storage: false # 非存储版本
    schema: {...}
  - name: v1
    served: true
    storage: true # 唯一存储版本
    schema: {...}

3)Operator 模式CRD 与控制器打包为 Operator,管理有状态应用(如数据库集群),实现自愈、备份等高级逻辑:

代码语言:javascript
复制
operator-sdk init --domain=example.com
operator-sdk create api --group=app --version=v1 --kind=App

4)Python 客户端操作 CRD 使用 kubernetes-client 库动态管理 CRD

代码语言:javascript
复制
from kubernetes import client, config
config.load_kube_config()
api = client.CustomObjectsApi()
api.create_namespaced_custom_object(group="example.com", version="v1", namespace="default", plural="apps", body=myapp_data)

5)验证与默认值

通过OpenAPI v3 Schema可以定义详细的验证规则:

代码语言:javascript
复制
validation:
  openAPIV3Schema:
    type: object
    properties:
      spec:
        type: object
        properties:
          cpu:
            type: string
            pattern: '^[0-9]+m?$'
          memory:
            type: string
            pattern: '^[0-9]+(Ei|Pi|Ti|Gi|Mi|Ki)?$'
        required: [cpu, memory]

7、注意事项

  • 字段设计spec 描述期望状态,status 记录实际状态,二者分离。
  • 权限控制:通过 RBAC 限制控制器的最小权限(如仅允许操作特定资源)。
  • 性能优化:避免频繁更新 CRD 状态,减少 API Server 负载。

总结

开发自定义 CRD 的核心流程为:定义 CRD 结构 → 注册到集群 → 编写控制器逻辑 → 部署控制器。结合 Operator 模式和 Finalizer 等机制,充分释放Kubernetes的扩展潜力。可构建生产级自动化运维能力。CRD作为Kubernetes的核心扩展机制,为平台赋予了近乎无限的扩展能力,CRD设计应当:

  • 遵循Kubernetes API约定;
  • 具备清晰的版本管理策略;
  • 提供完善的验证机制;
  • 与控制器紧密配合实现业务逻辑;

如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 一、CRD基础概念
    • 1. CRD的定义:
    • 3. CRD与相关概念的关系:
  • 4、CRD 与控制器关系
  • 二、CRD 的设计
  • 三、开发自定义的 CRD
    • 1. 定义 CRD 结构(YAML)
    • 2. 部署 CRD 到集群
    • 3. 创建 CRD 实例
    • 4、开发控制器(Controller)
      • 1) 工具选择
      • 2)控制器逻辑示例(Go)
      • 3)部署控制器
    • 5、调试与验证
    • 6、进阶实践
    • 5)验证与默认值
    • 7、注意事项
    • 总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档