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 模式 | 需要复杂业务逻辑、外部存储、实时计算 |
2.4 CRD 的生命周期管理
CRD 的生命周期包含创建、版本演进、废弃和删除四个阶段。每个阶段都有特定的操作规范和注意事项。
2.4.1 创建阶段
- 定义 Schema:使用 OpenAPI v3 规范描述资源的字段结构、类型和约束。
- 设置版本策略:指定
served(是否对外暴露)和storage(哪个版本写入 etcd)。 - 提交 CRD:
kubectl apply -f crd.yaml,API Server 自动注册新资源。 - 验证注册:
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}]'
2.5 CRD 与 Kyverno 的关系
Kyverno 深度依赖 CRD 机制实现策略管理:
- 策略定义:
ClusterPolicy和Policy本身就是 CRD 资源,存储在 etcd 中。 - 报告资源:
ClusterPolicyReport、PolicyReport等 CRD 用于存储策略执行结果。 - 后台资源:
UpdateRequest、BackgroundScanReport等 CRD 用于内部协调。 - 动态注册:Kyverno 安装时会自动创建所需的 CRD,无需手动干预。
学习要点:理解 CRD 的生命周期管理,有助于在生产环境中安全地升级 Kyverno 版本、处理策略迁移,以及在故障时进行数据恢复。