2. Kubernetes CRD 基础:CRD 定义、CRD 与 API 聚合的区别、CRD 的生命周期管理

2.1 什么是 CRD(Custom Resource Definition)

CRD 是 Kubernetes 原生的扩展机制,允许用户在不修改核心 API Server 代码的前提下,定义全新的资源类型。CRD 本身是一个标准的 Kubernetes API 资源(位于 apiextensions.k8s.io/v1 API 组),一旦创建,Kubernetes API Server 会自动生成对应的 RESTful 端点,并支持标准的 CRUD 操作。

核心价值:CRD 将 Kubernetes 从“容器编排平台”升级为“通用声明式应用平台”。Kyverno 正是利用 CRD 定义 ClusterPolicy、Policy、ReportChangeRequest 等资源,实现策略即代码。

2.2 CRD 定义的结构

一个完整的 CRD 定义包含以下关键字段:

字段路径 说明 是否必填
spec.group API 组名称,如 kyverno.io 是
spec.names.kind 资源类型名称,如 ClusterPolicy 是
spec.names.plural 复数名称,用于 URL 路径,如 clusterpolicies 是
spec.scope Namespaced 或 Cluster 是
spec.versions 版本列表,每个版本包含 schema.openAPIV3Schema 定义资源结构 是
spec.preserveUnknownFields 是否允许未知字段(v1 中推荐使用 x-kubernetes-preserve-unknown-fields) 否
spec.conversion 多版本间的转换策略(Webhook 或 None) 否

以下是一个简化的 CRD 定义示例:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: clusterpolicies.kyverno.io
spec:
  group: kyverno.io
  names:
    kind: ClusterPolicy
    plural: clusterpolicies
    singular: clusterpolicy
    shortNames:
      - cpol
  scope: Cluster
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                rules:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                      match:
                        type: object
                      validate:
                        type: object

2.3 CRD 与 API 聚合(Aggregation)的区别

Kubernetes 提供两种扩展 API 的方式:CRD 和 API 聚合(Aggregation API)。两者在架构、灵活性和运维复杂度上有显著差异。

关键对比:CRD 是“声明式扩展”,无需编写后端代码;API 聚合是“编程式扩展”,需要独立运行一个 API 服务。
对比维度 CRD(Custom Resource Definition) API 聚合(Aggregation API)
实现方式 声明式 YAML 定义,无需编码 需要编写独立的 HTTP API Server
存储后端 默认使用 etcd(与原生资源一致) 自定义存储,可对接外部数据库
验证逻辑 仅支持 OpenAPI v3 Schema 校验 完全自定义的验证逻辑(代码控制)
子资源 支持 /status、/scale 子资源 完全自定义子资源
运维复杂度 低,仅需创建 CRD 对象 高,需部署、监控、升级独立服务
适用场景 策略引擎、配置管理、Operator 模式 需要复杂业务逻辑、外部存储、实时计算
CRD vs API 聚合:架构对比 CRD 扩展 声明式 YAML 定义 自动生成 RESTful 端点 etcd 原生存储 OpenAPI v3 Schema 校验 适用:策略、配置、Operator API 聚合扩展 独立 HTTP API Server 自定义路由和端点 自定义存储(数据库等) 完全自定义业务逻辑 适用:复杂逻辑、外部系统

2.4 CRD 的生命周期管理

CRD 的生命周期包含创建、版本演进、废弃和删除四个阶段。每个阶段都有特定的操作规范和注意事项。

2.4.1 创建阶段

  1. 定义 Schema:使用 OpenAPI v3 规范描述资源的字段结构、类型和约束。
  2. 设置版本策略:指定 served(是否对外暴露)和 storage(哪个版本写入 etcd)。
  3. 提交 CRD:kubectl apply -f crd.yaml,API Server 自动注册新资源。
  4. 验证注册:kubectl get crd 查看状态是否为 Established。
注意:CRD 创建后,其 spec.names 和 spec.group 不可修改。如果命名错误,只能删除重建,且可能导致已有 CR 对象丢失。

2.4.2 版本演进

CRD 支持多版本共存,通过 spec.versions 列表管理。版本演进策略包括:

策略 说明 转换方式
None 所有版本结构相同,无需转换 直接读写
Webhook 通过 Conversion Webhook 实现版本间数据转换 自定义转换逻辑

版本演进最佳实践:

  • 始终保留一个 storage: true 版本作为 etcd 存储版本。
  • 新版本先设为 served: true,旧版本设为 served: false 逐步废弃。
  • 使用 Conversion Webhook 确保数据在不同版本间无损转换。

2.4.3 废弃与删除

CRD 的删除操作会级联删除所有对应的 CR 实例,务必谨慎操作。

# 查看 CRD 当前状态
kubectl get crd clusterpolicies.kyverno.io -o yaml

# 删除 CRD(会删除所有 CR 实例)
kubectl delete crd clusterpolicies.kyverno.io

# 仅停止服务,保留数据(设置 served: false)
kubectl patch crd clusterpolicies.kyverno.io \
  --type='json' \
  -p='[{"op": "replace", "path": "/spec/versions/0/served", "value": false}]'
CRD 生命周期管理流程 1. 创建 定义 Schema 2. 版本演进 多版本共存 3. 废弃 served: false 4. 删除 级联清理 生命周期关键注意事项 • 创建后 spec.names 和 spec.group 不可修改,命名需谨慎 • 版本演进时至少保留一个 storage: true 版本 • 废弃阶段先设置 served: false 观察,确认无依赖后再删除 • 删除 CRD 会级联删除所有 CR 实例,操作前务必备份数据

2.5 CRD 与 Kyverno 的关系

Kyverno 深度依赖 CRD 机制实现策略管理:

  • 策略定义:ClusterPolicy 和 Policy 本身就是 CRD 资源,存储在 etcd 中。
  • 报告资源:ClusterPolicyReport、PolicyReport 等 CRD 用于存储策略执行结果。
  • 后台资源:UpdateRequest、BackgroundScanReport 等 CRD 用于内部协调。
  • 动态注册:Kyverno 安装时会自动创建所需的 CRD,无需手动干预。
学习要点:理解 CRD 的生命周期管理,有助于在生产环境中安全地升级 Kyverno 版本、处理策略迁移,以及在故障时进行数据恢复。