1. CRD 基础概念
1.1 什么是 CustomResourceDefinition
CustomResourceDefinition(CRD)是 Kubernetes 内置的一种 API 资源类型,它允许用户在不修改核心 Kubernetes 源码的前提下,向集群中注册并管理自定义的资源类型。CRD 本质上是 Kubernetes API 的扩展机制,通过声明式配置定义新资源的名称、分组、版本和结构,Kubernetes 会为其自动生成 RESTful API 端点、存储(etcd)以及基础的 CRUD 操作。
核心定义:CRD 是一个 API 资源,它定义了“如何定义一个新的 API 资源”。一旦创建 CRD,用户就可以像操作 Pod、Deployment 一样,通过
kubectl 或 API 调用来创建、查询、更新和删除该自定义资源的实例。
以下是一个典型的 CRD 定义示例,它定义了一个名为 Application 的自定义资源:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: applications.example.com
spec:
group: example.com
names:
kind: Application
plural: applications
singular: application
shortNames:
- app
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
replicas:
type: integer
image:
type: string
status:
type: object
properties:
availableReplicas:
type: integer
phase:
type: string
| 字段 | 说明 | 示例值 |
|---|---|---|
spec.group |
API 组,用于资源分组和隔离 | example.com |
spec.names.kind |
资源类型名称,用于 YAML 中的 kind 字段 |
Application |
spec.names.plural |
复数名称,用于 API 路径和 kubectl 命令 |
applications |
spec.scope |
资源作用域:Namespaced 或 Cluster |
Namespaced |
spec.versions[].schema |
OpenAPI v3 Schema,定义资源字段结构和校验规则 | JSON Schema 对象 |
1.2 CRD 与原生资源的关系
CRD 定义的自定义资源与 Kubernetes 原生资源(如 Pod、Service、Deployment)在 API 机制上完全对等,但在实现深度上存在本质差异。下表从多个维度对比两者的关系:
| 对比维度 | 原生资源(Pod/Deployment 等) | CRD 自定义资源 |
|---|---|---|
| API 机制 | 内置在 API Server 中,代码级实现 | 通过 CRD 声明式注册,API Server 自动生成端点 |
| 存储 | 存储在 etcd,由 API Server 管理 | 存储在 etcd,由 API Server 管理(完全一致) |
| 校验 | 内置 Go 代码校验 + 准入 Webhook | OpenAPI v3 Schema 校验 + 可选准入 Webhook |
| 默认控制器 | 有(kube-controller-manager 内置) | 无,需要用户自行开发 Operator 或控制器 |
| 状态管理 | 控制器自动更新 status 字段 | 需要 Operator 手动更新 status 子资源 |
| 垃圾回收 | 支持 OwnerReference 级联删除 | 支持 OwnerReference 级联删除(机制相同) |
| 版本管理 | 内置多版本转换 | 需配置 conversion Webhook 或指定 storage 版本 |
关键理解:CRD 让自定义资源在“数据平面”(API、存储、校验)上与原生资源平起平坐,但在“控制平面”(控制器、状态管理、默认行为)上需要用户自行补齐。这也是 Operator 模式存在的根本原因——Operator 就是自定义资源的控制器。
1.3 CRD 在 Kubernetes 生态中的角色
CRD 是 Kubernetes 生态扩展能力的基石,它使得 Kubernetes 从一个容器编排平台演变为一个通用的云原生应用平台。CRD 在生态中扮演以下核心角色:
- 平台扩展层:CRD 允许平台团队定义业务领域模型(如 Database、Certificate、Pipeline),将 Kubernetes 从“资源调度层”提升为“业务抽象层”。
- Operator 模式的基础:几乎所有 Operator(如 etcd-operator、prometheus-operator、cert-manager)都依赖 CRD 定义其管理的资源类型,CRD 是 Operator 的“数据模型”。
- 声明式配置的载体:CRD 实例以 YAML/JSON 形式存在,天然适配 GitOps 工作流,支持版本控制、审计和自动化运维。
- 生态互操作的契约:不同项目通过 CRD 暴露其 API,例如 Istio 的 VirtualService、Knative 的 Service,CRD 成为生态组件之间的标准化接口。
常见误区:CRD 不等于 Operator。CRD 只定义了“数据模型”,而 Operator 是“控制逻辑”。没有 Operator 的 CRD 只能作为静态配置存储,无法实现自动化编排和状态修复。在故障排查时,80% 的问题出在 Operator 逻辑而非 CRD 定义本身。
1.4 CRD 的生命周期与版本管理
CRD 本身也是一种 API 资源,拥有完整的生命周期管理能力。理解 CRD 的生命周期对于 Operator 开发和故障排查至关重要:
- 创建阶段:提交 CRD YAML 到集群,API Server 校验 Schema 合法性,注册新的 RESTful 端点。
- 版本演进:CRD 支持多个版本共存(如 v1alpha1、v1beta1、v1),通过
spec.versions定义。每个版本可以独立定义 Schema,但只有一个版本被标记为storage: true。 - 废弃与删除:删除 CRD 会级联删除所有自定义资源实例(除非设置了
preserveUnknownFields)。建议先移除所有实例再删除 CRD。
| 阶段 | 操作 | 注意事项 |
|---|---|---|
| 创建 | kubectl apply -f crd.yaml |
确保 group 和 kind 不与其他 CRD 冲突;Schema 必须合法 |
| 更新 | kubectl apply -f crd-v2.yaml |
Schema 变更必须向后兼容;已存储的实例不会自动迁移 |
| 版本转换 | 配置 conversion Webhook 或手动迁移 |
不配置 conversion 时,只能通过 storage 版本读写 |
| 删除 | kubectl delete crd applications.example.com |
会删除所有关联的自定义资源实例,操作不可逆 |
最佳实践:在生产环境中,CRD 的 Schema 变更应遵循“先增后删”原则。新增字段时设置
default 或 nullable: true,避免已存储的旧实例因缺少字段而校验失败。对于破坏性变更,建议创建新版本的 CRD 并逐步迁移。