首页 / Kubernetes (k8s) 入门教程 / CRD 自定义资源

Kubernetes (k8s) 入门教程

CRD 自定义资源

本教程共 65 篇 · 第 55 篇 · 更新于 2026-08-14 · 约 13 分钟阅读

KubernetesCRDCustomResourceDefinitionAPI扩展声明式

本节目标:理解定制资源(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(集群级)。
  • nameskind 是资源类型名,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 定义了 PrometheusAlertmanager 等资源,用户写一份 YAML,Operator 就去把整套监控系统搭起来。这就是 CRD 的威力:把”复杂操作”变成”写一份配置”。