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。

版本演进通常遵循以下流程:

  1. 新增版本 v2,设置 served: true,storage: false,同时保留 v1 作为存储版本。
  2. 迁移所有存量资源到 v2 结构(通过转换 Webhook 或手动更新)。
  3. 将 v2 的 storage 改为 true,v1 的 storage 改为 false。
  4. 废弃 v1,设置 served: false,最终移除。
注意: 直接修改存储版本可能导致数据丢失或 API 不兼容。生产环境中建议配合 Conversion Webhook 实现无损版本转换。

2.4 CRD 结构示意图

下图展示了 CRD 定义、API Server 与自定义资源实例之间的核心关系:

CRD 定义与资源实例关系图 CustomResourceDefinition group: stable.example.com kind: RollbackStrategy versions: [v1, v2] Kubernetes API Server 自动生成 RESTful 端点 /apis/stable.example.com/v1/ rollbackstrategies 自定义资源实例 apiVersion: stable.example.com/v1 kind: RollbackStrategy metadata.name: canary-rollback 关键流程说明 1. 管理员创建 CRD 定义 → API Server 注册新资源类型 2. 用户提交自定义资源实例 → API Server 校验 schema 并存储 3. 控制器监听实例变化 → 执行对应业务逻辑(如回滚策略验证) 4. 版本管理确保多版本共存与平滑迁移

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 检查。