CRD 自定义资源
本教程共 65 篇 · 第 55 篇 · 更新于 2026-08-14 · 约 13 分钟阅读
本节目标:理解定制资源(CR)与定制资源定义(CRD)的关系,能写一个 apiextensions.k8s.io/v1 的 CRD,并知道它和聚合 API 该怎么选。
Kubernetes 内置了 Pod、Service、Deployment 这些资源。但总有些场景,内置资源表达不了。比如你想让集群理解”一个数据库实例""一个定时备份任务”,这就需要扩展 API。CRD 就是做这件事的。
55-1 什么是定制资源
资源(Resource)是 Kubernetes API 里的一个端点,存放某一类对象,比如内置的 pods 资源里是一堆 Pod 对象。
定制资源(Custom Resource,简称 CR)是对 Kubernetes API 的扩展。它不一定随默认安装就存在,而是你按需注册进去的。注册之后,你就能像操作 Pod 一样,用 kubectl 创建和查看它。
但光有 CR 还不够。它本身只能存取结构化数据。只有当 CR 配上”定制控制器(Custom Controller)“,才真正构成声明式 API:你描述期望状态,控制器负责把它变成现实。把 CR 和控制器结合,就是下一章要讲的 Operator 模式。
Note很多 Kubernetes 核心功能现在都用 CRD 实现,比如让集群更模块化。所以 CRD 既是”扩展手段”,也是”内部构件”。
55-2 用 CRD 定义新资源
定义 CRD 用的是 apiextensions.k8s.io/v1 这个 API 版本。下面是一个简化示例:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
image:
type: string
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
几个关键点:
metadata.name必须是<plural>.<group>的形式,且是合法 DNS 子域名。group是你的 API 分组,建议用公司域名倒写,避免冲突。scope可以是Namespaced(按命名空间隔离)或Cluster(集群级)。names里kind是资源类型名,shortNames是命令行简写,比如kubectl get ct。
CRD 创建好后,就可以像内置资源那样使用了:
kubectl apply -f my-crontab.yaml
kubectl get crontabs
55-3 给字段加校验
CRD 的 schema.openAPIV3Schema 不仅能描述字段类型,还能强制校验。比如要求 cronSpec 匹配某个正则、replicas 必须是 1 到 10 的整数:
schema:
openAPIV3Schema:
type: object
properties:
spec:
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
replicas:
type: integer
minimum: 1
maximum: 10
提交不符合规范的实例时,API 服务器会直接拒绝。这样能把错误挡在入口,而不是等控制器运行时才崩溃。
Tip把校验写在 CRD 里,是防止”脏数据”进入集群最省力的办法。字段类型、必填项、取值范围都能管。
55-4 status 与 scale 子资源
如果想让”用户写 spec、控制器写 status”,可以开启 status 子资源。它带来更细的权限控制,控制器只改 status 部分,用户只改 spec 部分。
subresources:
status: {}
scale:
specReplicasPath: .spec.replicas
statusReplicasPath: .status.replicas
开了 scale 子资源后,你甚至能对自定义资源用 kubectl scale。这让自定义资源能接入 HPA 这类依赖 scale 的子系统。
55-5 CRD 还是聚合 API
向集群加定制资源,Kubernetes 提供两条路:
- CRD:简单,不用写代码。声明式定义 schema,API 服务器帮你存、帮你校验。
- 聚合 API(AA):需要自己写一个 API 服务器挂到主 API 后面,灵活但复杂。
怎么选?CRD 适合字段不多、在团队内部或小开源项目使用的场景。聚合 API 适合需要定制存储层(比如用时间序列数据库)、需要 exec 这类额外子资源的场景。
Warning不要把 CRD 当成普通数据库来存业务数据、用户数据或监控数据。把大量应用数据塞进 API 服务器,是一种过度耦合的设计,会让集群变重。
55-6 访问与权限
CRD 创建后,你可以用 kubectl、动态客户端、或者代码生成的客户端来访问它。Go 和 Python 客户端都支持。
在权限方面,CRD 沿用集群的认证、鉴权和审计机制。但 RBAC 默认不会给新资源授权——除了 cluster-admin,大多数角色访问不了它。所以发布 CRD 时,通常会配套带上对应的 Role/ClusterRole 定义。
55-7 它解决了什么
CRD 最妙的在于:你不必改 Kubernetes 源码,就能让集群”听懂”一种新的资源类型。配合下一章的控制器,你可以把运维知识固化成声明式 API。
比如 Prometheus Operator 用 CRD 定义了 Prometheus、Alertmanager 等资源,用户写一份 YAML,Operator 就去把整套监控系统搭起来。这就是 CRD 的威力:把”复杂操作”变成”写一份配置”。