Kubernetes 自定义资源、自定义资源定义 (CRD) 与控制器
Source: Dev.to
Kubernetes 并不是因为 Pods 或 Services 而强大。
它之所以强大,是因为可以 在不修改 Kubernetes 本身的情况下进行扩展。
这种可扩展性来源于 Custom Resources(自定义资源)+ CRDs(自定义资源定义)+ Controllers(控制器)。
如果你没有真正理解这三者,你其实并没有在 使用 Kubernetes——你只是在部署 YAML。
为什么会有 CRD
Kubernetes 解决 通用基础设施问题:
- 调度
- 网络
- 存储
- 扩容
但真实的公司面临 特定领域的问题:
- “部署模型”
- “提供数据库”
- “创建服务网格规则”
- “管理证书”
与其把这些硬编码进 Kubernetes,Kubernetes 为我们提供了一种 定义自定义 API 的方式。
框架
| 组件 | 用途 |
|---|---|
| CRD | 定义新的 API 类型 |
| Custom Resource | 该 API 的实例 |
| Controller | 实现业务逻辑的控制器 |
心智模型(重要)
Kubernetes 本身对你的 CRD 什么也不做——它只会存储它们。
如果你创建了一个 没有控制器 的 CRD,Kubernetes 会欣然接受它,但 什么也不做。这不是 bug;这是设计如此。
什么是自定义资源 (CR)?
自定义资源 是 Kubernetes 中的 新对象类型,就像:
PodServiceDeployment
您可以创建自己的,例如:
DatabaseApplicationMLModelCertificateGateway
示例
kubectl get databases
kubectl apply -f myapp.yaml
Kubernetes 并不关心 Database 的含义。
什么是 CRD(CustomResourceDefinition)?
A CRD 在 Kubernetes 中定义了一个新的 API 架构。可以把它理解为:
“嘿,Kubernetes,这里有一种新对象。请把它存储下来。”
CRD 指定了:
- API 组
- 版本
- Kind
- Schema(验证)
简单 CRD 示例
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: databases.mycompany.io
spec:
group: mycompany.io
scope: Namespaced
names:
plural: databases
singular: database
kind: Database
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
engine:
type: string
version:
type: string
storage:
type: string
应用此 CRD 后:
kubectl get databases
Kubernetes 现在 将 Database 识别为有效对象 — 仅此而已。
创建自定义资源 (CR)
apiVersion: mycompany.io/v1
kind: Database
metadata:
name: user-db
spec:
engine: postgres
version: "15"
storage: 20Gi
Apply it:
kubectl apply -f database.yaml
Result:
- 存储在 etcd 中
- 未创建 Pod
- 未启动数据库
这正是大多数初学者感到困惑的地方。
为什么控制器是必需的
A Controller is the brain. It:
- 监视自定义资源
- 比较 期望状态 与 实际状态
- 调和差异
没有控制器时:
- CRD = 死的模式
- CR = 无用的 YAML
控制器调和循环
Every controller follows this loop:
Observe → Compare → Act → Repeat
In code terms:
while True:
desired_state = cr.spec
actual_state = cluster_reality
if desired_state != actual_state:
fix_it()
此循环 永不停止。
CRD + 控制器如何协同工作
User
|
| kubectl apply
v
Kubernetes API Server
|
v
etcd (stores CR)
|
v
Controller watches CR
|
v
Controller creates / updates:
- Pods
- Services
- PVCs
- ConfigMaps
真实示例:数据库操作器
自定义资源
apiVersion: mycompany.io/v1
kind: Database
metadata:
name: user-db
spec:
engine: postgres
version: "15"
storage: 20Gi
控制器逻辑
IF Database CR is created:
- Create StatefulSet
- Create PVC
- Create Service
IF Database CR is deleted:
- Cleanup resources
Kubernetes 并不了解数据库。你的控制器了解。
期望状态 vs 实际状态
Desired State (CR):
Database:
engine: postgres
replicas: 1
Actual State (Cluster):
StatefulSet: missing
Controller Action:
Create StatefulSet
如果有人手动删除 StatefulSet,控制器会重新创建它。
CRDs 与 Deployments 对比
| 功能 | 部署 | CRD |
|---|---|---|
| 内置 | 是 | 否 |
| 包含控制器 | 是 | 仅当你编写时 |
| 逻辑位置 | Kubernetes | 你 |
| 描述 | Deployment 只是一种 CRD + 由 Kubernetes 提供的控制器。 |
Istio 使用 CRD
Istio 通过以下 CRD 扩展 Kubernetes:
VirtualServiceDestinationRuleGateway
示例
kind: VirtualService
spec:
hosts:
- myapp
http:
- ...

route:
- destination:
host: myapp-v2
Istio 控制器将其转换为
- Envoy 配置
- 流量路由
- 负载均衡
注意: Istio 并不修改 Kubernetes。它 正确地对其进行扩展。
为什么公司使用 CRD 构建产品
CRD 允许:
- Kubernetes 原生 API
- 声明式行为
kubectl为先的用户体验- 强大的调和保证
被以下项目使用:
- ArgoCD
- Crossplane
- Cert‑Manager
- Prometheus Operator
- Istio
全部遵循相同的模式。
常见错误
- “CRD 自动创建资源”
- 在 YAML 中编写逻辑
- 忽略
.status字段 - 将 CRD 当作配置文件
CRD 是 API,而不是配置。
何时应使用 CRDs?
使用 CRDs 的情况:
- 您管理的是生命周期,而不仅仅是部署
- 您需要进行 reconciliation(调和)
- 您正在构建平台
不应使用 CRDs 的情况:
- 静态配置
- 一次性任务
- 简单值
最终要点
- CRDs 定义 WHAT 你想要的
- Controllers 定义 HOW 它的实现方式
- Kubernetes 强制执行循环
如果你理解了这些,你就已经超越 YAML 理解了 Kubernetes。
