CRD 基础:概念、与原生资源的关系、YAML 结构定义

Custom Resource Definition(CRD)是 Kubernetes 扩展机制的核心,它允许你在集群中定义全新的资源类型,而无需修改任何 Kubernetes 源码。CRD 的本质是一个 API 资源描述文件,它告诉 API Server:“我要新增一种资源,它的名字、结构、作用域是什么”。一旦 CRD 被创建,Kubernetes 就会自动生成对应的 RESTful API 端点,你可以像操作 Pod、Service 一样,通过 kubectl 或 API 调用来管理这种自定义资源。

CRD 与原生资源的关系

Kubernetes 原生资源(如 Pod、Deployment、Service)与 CRD 定义的自定义资源在 API 层面遵循完全相同的生命周期和操作模式。下表从多个维度对比两者的异同:

对比维度 原生资源 CRD 自定义资源
定义来源 Kubernetes 源码内置 用户通过 CRD YAML 声明
API 端点 由 API Server 硬编码提供 CRD 创建后自动生成
存储方式 etcd,由 API Server 管理 etcd,与原生资源共用存储层
验证机制 内置 OpenAPI 校验 + 准入控制器 OpenAPI v3 模式校验 + 可选的 Webhook
默认控制器 有(如 kube-controller-manager) 无,需要用户自行实现
版本管理 内置版本转换 需在 CRD 中声明版本转换策略
作用域 集群级别或命名空间级别 由 CRD 的 scope 字段指定
关键理解:CRD 不提供业务逻辑。它只负责定义资源的“数据结构”和“API 行为”。真正的业务逻辑(如创建 Pod、调整副本数、处理状态更新)需要由独立的控制器程序来驱动。CRD + 控制器 = 完整的扩展能力。

CRD 的 YAML 结构定义

一个标准的 CRD 定义包含三个核心部分:元数据、Spec 结构、版本与作用域。下面是一个完整的 CRD 示例,定义了一种名为 AppDeployment 的自定义资源:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: appdeployments.apps.example.com   # 必须为 {复数名}.{组名}
spec:
  group: apps.example.com                  # API 组
  names:
    plural: appdeployments                 # 复数名,用于 kubectl
    singular: appdeployment                # 单数名
    shortNames:                            # 短名称
      - appdep
    kind: AppDeployment                    # 资源类型名
    listKind: AppDeploymentList            # 列表类型名
  scope: Namespaced                        # 作用域:Namespaced 或 Cluster
  versions:
    - name: v1
      served: true                         # 是否在 API 中提供
      storage: true                        # 是否作为 etcd 存储版本
      schema:
        openAPIV3Schema:
          type: object
          required:
            - spec
          properties:
            spec:
              type: object
              required:
                - replicas
                - image
              properties:
                replicas:
                  type: integer
                  minimum: 1
                  maximum: 100
                image:
                  type: string
                env:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                      value:
                        type: string
            status:
              type: object
              properties:
                availableReplicas:
                  type: integer
                conditions:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                      status:
                        type: string
                      lastTransitionTime:
                        type: string
                        format: date-time
结构要点:
  • spec.versions[].schema.openAPIV3Schema 是资源的数据模型定义,所有字段类型、约束、嵌套结构都在这里声明。
  • status 字段通常不由用户写入,而是由控制器在运行时填充,用于反映资源的实际状态。
  • scope: Namespaced 表示资源属于命名空间级别;Cluster 表示集群级别(如 ClusterRole)。

CRD 的核心字段速查表

字段路径 说明 示例值
spec.group API 组,用于组织资源 apps.example.com
spec.names.kind 资源类型名称,首字母大写 AppDeployment
spec.names.plural 复数名,用于 URL 路径 appdeployments
spec.scope 资源作用域 Namespaced
spec.versions[].name 版本名称 v1
spec.versions[].served 是否对外暴露该版本 true
spec.versions[].storage 是否作为存储版本(只能一个为 true) true
spec.versions[].schema.openAPIV3Schema 资源的 JSON Schema 定义 嵌套对象

CRD 在 Kubernetes 控制面中的位置

下图展示了 CRD 如何融入 Kubernetes 控制面的核心组件,以及自定义资源的数据流路径:

CRD 在 Kubernetes 控制面中的数据流 用户 / kubectl API Server etcd CRD 注册表 自定义资源实例 自定义控制器 控制器工作流程 Watch → 对比 → 调谐 → 更新状态 (调谐循环) 创建 CRD 存储 CRD 定义 注册新资源类型 生成 API 端点 Watch 事件 更新状态 创建/更新实例
常见误区:
  • CRD 不等于控制器。CRD 只定义数据结构,控制器才是执行调谐逻辑的组件。
  • 不要将业务逻辑写在 CRD 的 openAPIV3Schema 中。Schema 只负责数据校验,不负责行为控制。
  • CRD 的 metadata.name 必须遵循 {复数名}.{组名} 格式,否则 API Server 会拒绝创建。

创建 CRD 后的效果

当 CRD 被成功创建后,你可以立即使用 kubectl 操作自定义资源:

# 查看 CRD 是否注册成功
kubectl get crd

# 创建自定义资源实例
kubectl apply -f appdeployment-instance.yaml

# 查看实例
kubectl get appdeployment
kubectl get appdep  # 使用短名称

# 查看实例详情(包含 status 字段)
kubectl describe appdeployment my-app

# 删除实例
kubectl delete appdeployment my-app

自定义资源实例的 YAML 文件示例如下:

apiVersion: apps.example.com/v1
kind: AppDeployment
metadata:
  name: my-app
  namespace: default
spec:
  replicas: 3
  image: nginx:1.25
  env:
    - name: ENV
      value: production
实践建议:在定义 CRD 的 Schema 时,尽量使用 required 字段约束必填项,使用 minimum/maximum 约束数值范围,使用 pattern 约束字符串格式。这些校验会在 API 层拦截非法数据,减轻控制器的处理负担。