1. CRD 基础概念:CustomResourceDefinition 的定义、作用与生命周期
CustomResourceDefinition(CRD)是 Kubernetes 内置的一种 API 资源,它允许用户在不修改核心 Kubernetes 源码的前提下,向集群声明新的自定义资源类型。CRD 是 Operator 模式的基石——没有 CRD,Operator 就失去了它所管理的“物”。理解 CRD 的定义、作用与生命周期,是掌握 Operator 控制面蓝图的第一步。
1.1 什么是 CRD?
CRD 本质上是一个资源类型的元描述。当你创建一个 CRD 对象时,你实际上是在告诉 Kubernetes API Server:“请注册一个新的 RESTful 资源路径,并按照我定义的 schema 来验证和存储该资源的数据。” 从此,用户可以通过 kubectl 或 API 调用来创建、读取、更新、删除该自定义资源的实例(即 Custom Resource,CR)。
| 概念 | 类比 | Kubernetes 中的角色 |
|---|---|---|
| CRD | 数据库中的表结构定义(DDL) | 声明一种新的资源类型及其验证规则 |
| CR(Custom Resource) | 表中的一行记录 | 该资源类型的一个具体实例 |
| API Server | 数据库引擎 | 提供 REST 端点、存储、认证与校验 |
关键认知: CRD 本身是一个 Kubernetes 资源(属于
apiextensions.k8s.io/v1 API 组),而它定义出来的自定义资源则属于你指定的 group/version。两者处于不同的 API 层级。
1.2 CRD 的核心作用
CRD 在 Operator 生态中承担三个不可替代的作用:
- 扩展 API 面:将领域对象(如数据库集群、消息队列、监控告警规则)映射为 Kubernetes 原生的 API 资源,使它们可以被
kubectl、RBAC、审计日志等统一管理。 - 声明式配置入口:用户通过 YAML 声明期望状态,Operator 通过控制器循环不断调和实际状态,CRD 就是这份“期望状态”的载体。
- 版本化演进:CRD 支持多个 API 版本共存(如
v1alpha1、v1beta1、v1),允许资源 schema 在不中断现有用户的情况下逐步成熟。
1.3 CRD 的生命周期
一个 CRD 从创建到最终被清理,经历以下四个阶段:
| 阶段 | 触发动作 | 关键行为 | 注意事项 |
|---|---|---|---|
| 1. 注册 | kubectl apply -f crd.yaml |
API Server 注册新的 REST 路径,生成 OpenAPI schema | 同名 CRD 不可重复注册;spec.names.singular 必须唯一 |
| 2. 版本发布 | 更新 CRD 的 spec.versions 字段 |
新增/废弃/升级 API 版本;可设置 storage 版本与 served 版本 |
废弃版本需通过 deprecated 标记,不能直接删除 |
| 3. 实例管理 | 用户创建/更新/删除 CR | CR 数据按 CRD schema 校验后存入 etcd;Operator 监听并调和 | 删除 CRD 前必须先清理所有 CR 实例,否则会残留孤儿对象 |
| 4. 注销与清理 | kubectl delete crd <name> |
API Server 移除 REST 路径;如果存在 Finalizer 则阻塞删除 | Finalizer 机制是安全清理的关键,也是本课程后续重点 |
1.4 CRD 定义的关键字段
一个典型的 CRD YAML 包含以下核心结构:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: mongodbs.example.com # 必须格式:<plural>.<group>
spec:
group: example.com # API 组
names:
plural: mongodbs # 复数名,用于 URL 路径
singular: mongodb # 单数名
kind: MongoDB # 资源类型名,用于 YAML 的 kind 字段
shortNames: # 简写,可选
- mdb
scope: Namespaced # 作用域:Namespaced 或 Cluster
versions:
- name: v1alpha1 # 版本名
served: true # 是否对外提供该版本 API
storage: true # 是否将该版本数据持久化到 etcd
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
replicas:
type: integer
version:
type: string
subresources:
status: {} # 启用 /status 子资源
additionalPrinterColumns: # kubectl 额外输出列
- name: Replicas
type: integer
jsonPath: .spec.replicas
conversion:
strategy: None # 版本转换策略:None 或 Webhook
设计要点:
- scope:
Namespaced资源受命名空间隔离,适合多租户场景;Cluster资源全局唯一,适合集群级配置。 - storage:只能有一个版本标记为
storage: true,该版本决定 etcd 中实际存储的数据结构。 - subresources.status:启用后,Operator 可以独立更新
status而不触发 spec 的调和循环。
1.5 CRD 与 Operator 的关系
CRD 和 Operator 是“契约”与“执行者”的关系:
- CRD 定义契约:规定用户能写什么(spec)、系统能报什么(status)、资源如何被分类(group/version/kind)。
- Operator 履行契约:监听 CR 的增删改事件,读取 spec,创建/更新/删除下层 Kubernetes 资源,并将运行状态写回 status。
没有 CRD,Operator 就失去了与用户交互的标准化接口;没有 Operator,CRD 只是一堆躺在 etcd 中的静态 JSON 数据。两者共同构成了 Kubernetes 声明式自动化的闭环。
常见陷阱: 初学者容易混淆 CRD 与 CR。CRD 是“资源类型的定义”,全局只有一个;CR 是“资源实例”,可以有成千上万个。删除 CRD 会级联删除所有 CR 实例(除非有 Finalizer 拦截),务必在生产环境中谨慎操作。
1.6 小结
CRD 是 Kubernetes 扩展性的核心机制,它让平台能够理解并管理任意领域对象。作为 Operator 开发者,你需要:
- 精确设计 CRD 的 group/version/kind 命名空间,避免与现有资源冲突。
- 合理规划 版本演进策略,利用
served和storage字段实现平滑升级。 - 深刻理解 CRD 的 生命周期,特别是删除阶段 Finalizer 的作用——这是下一章将要深入的主题。