2. Kubernetes CRD 基础回顾:CustomResourceDefinition 的定义、结构、版本管理
在 Kubernetes 生态中,CustomResourceDefinition (CRD) 是扩展 API 的核心机制。它允许你定义新的资源类型,使 Kubernetes 能够像管理原生资源(如 Pod、Deployment)一样管理自定义资源。本章将系统回顾 CRD 的定义、结构组成以及版本管理策略,为后续实现 CRD 控制器与自动化回滚验证打下坚实基础。
2.1 CRD 的定义与核心作用
CRD 本身是一种 Kubernetes 原生资源,通过 YAML 或 JSON 声明式定义。一旦创建,Kubernetes API Server 会自动生成对应的 RESTful API 端点,并支持标准的 CRUD 操作。
核心作用: 将领域模型(如“数据库实例”、“发布任务”、“回滚策略”)转化为 Kubernetes 一等公民资源,实现声明式管理与自动化运维。
2.2 CRD 的结构组成
一个标准的 CRD 定义包含以下关键字段,它们共同决定了自定义资源的行为与约束。
| 字段路径 | 类型 | 说明 |
|---|---|---|
apiVersion |
string | CRD 自身的 API 版本,通常为 apiextensions.k8s.io/v1 |
kind |
string | 固定为 CustomResourceDefinition |
metadata.name |
string | 必须与 spec.names.plural + "." + spec.group 一致 |
spec.group |
string | API 组名,如 stable.example.com |
spec.names |
object | 定义资源的 plural、singular、kind、shortNames |
spec.scope |
string | Namespaced(命名空间级)或 Cluster(集群级) |
spec.versions |
[]object | 版本列表,每个版本包含 name、served、storage、schema |
spec.versions[].schema |
object | 使用 openAPIV3Schema 定义资源字段结构与校验规则 |
实践建议: 始终使用
apiextensions.k8s.io/v1 版本,它提供了结构模式(structural schema)的强制校验,避免因字段定义不严谨导致控制器运行时异常。
2.3 CRD 版本管理策略
版本管理是 CRD 长期维护的核心挑战。Kubernetes 支持多版本共存,通过 served 和 storage 字段控制版本的生命周期。
- served: 该版本是否被 API Server 提供服务(可读写)。
- storage: 该版本是否用于持久化存储。同一 CRD 只能有一个版本标记为
storage: true。
版本演进通常遵循以下流程:
- 新增版本
v2,设置served: true,storage: false,同时保留v1作为存储版本。 - 迁移所有存量资源到
v2结构(通过转换 Webhook 或手动更新)。 - 将
v2的storage改为true,v1的storage改为false。 - 废弃
v1,设置served: false,最终移除。
注意: 直接修改存储版本可能导致数据丢失或 API 不兼容。生产环境中建议配合 Conversion Webhook 实现无损版本转换。
2.4 CRD 结构示意图
下图展示了 CRD 定义、API Server 与自定义资源实例之间的核心关系:
2.5 版本管理对比表
不同版本管理策略在稳定性与灵活性上各有侧重,下表对比了常见场景下的选择:
| 策略 | 适用场景 | 优点 | 风险 |
|---|---|---|---|
| 单版本演进 | 早期开发、内部工具 | 简单直接,无转换开销 | 破坏性变更影响所有存量资源 |
| 多版本共存(无 Webhook) | 字段新增、非破坏性变更 | 新旧版本可同时读写 | 存储版本与 served 版本不一致时需手动处理 |
| 多版本共存 + Conversion Webhook | 生产环境、API 对外暴露 | 无损转换,客户端无感知 | 增加运维复杂度,Webhook 需高可用 |
2.6 完整 CRD 示例(RollbackStrategy)
以下是一个用于本课程的 RollbackStrategy CRD 定义示例,包含版本 v1 与 v2:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: rollbackstrategies.stable.example.com
spec:
group: stable.example.com
names:
plural: rollbackstrategies
singular: rollbackstrategy
kind: RollbackStrategy
shortNames:
- rbs
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
strategyType:
type: string
enum: ["canary", "bluegreen", "rolling"]
maxRetries:
type: integer
minimum: 1
maximum: 10
healthCheckEndpoint:
type: string
pattern: "^https?://"
- name: v2
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
strategyType:
type: string
enum: ["canary", "bluegreen", "rolling", "ramped"]
maxRetries:
type: integer
minimum: 1
maximum: 20
healthCheckEndpoint:
type: string
pattern: "^https?://"
timeoutSeconds:
type: integer
minimum: 30
maximum: 3600
版本管理要点: 上述示例中
v2 新增了 timeoutSeconds 字段,并扩展了 strategyType 枚举值。由于 v2 的 storage: false,所有数据仍以 v1 格式存储,但客户端可通过 v2 端点读写。后续课程将演示如何通过 Conversion Webhook 实现字段映射。
2.7 常见避坑指南
- 命名冲突:
metadata.name必须严格遵循<plural>.<group>格式,否则 CRD 创建失败。 - Schema 非结构模式:
apiextensions.k8s.io/v1要求 schema 必须是结构模式(structural schema),禁止使用nullable: true以外的宽松定义。 - 存储版本不可随意切换: 修改
storage字段后,存量资源不会自动转换,需通过控制器或 Webhook 处理。 - 短名称冲突:
shortNames不能与集群中已有资源的短名称重复,建议使用kubectl api-resources检查。