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 不等于控制器。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 层拦截非法数据,减轻控制器的处理负担。