前言
前面十九篇基本围绕 Kubernetes 自带对象展开:Pod、Deployment、Service、ConfigMap、Secret、PVC、Ingress、NetworkPolicy 等。
如果只是部署一个简单服务,写几份 YAML 还能接受。但真实应用经常不是一个 YAML:
1 | Deployment |
每个环境还要有不同参数:
1 | dev:副本 1,资源小,域名 dev.example.com |
这时就会遇到两个问题:
1 | 复杂 YAML 怎么组织? |
Helm、CRD、Operator 分别在这条线上出现。
我目前先这样理解:
1 | Helm |
Helm:给一组 YAML 做模板和发布
Helm 可以理解成 Kubernetes 的包管理工具。它把一组 Kubernetes 资源打包成 Chart。
一个 Chart 大概像这样:
1 | demo-api-chart |
templates/ 里放模板,values.yaml 里放参数。
例如模板里写:
1 | replicas: {{ .Values.replicaCount }} |
values.yaml 里写:
1 | replicaCount: 3 |
渲染后得到真正提交给 Kubernetes 的 YAML。
1 | Chart templates |
Helm Release
用 Helm 安装一个 Chart,会得到一个 Release。
1 | helm install demo-api ./demo-api-chart |
可以理解成:
1 | Chart |
同一个 Chart 可以安装多次,得到不同 Release:
1 | demo-api-dev |
每个 Release 可以使用不同 values:
1 | helm install demo-api-dev ./demo-api-chart -f values-dev.yaml |
这样就不用维护多份几乎一样的 YAML。
1 | 同一套模板 |
Helm 解决了什么,不解决什么
Helm 主要解决的是 YAML 组织、模板渲染、发布记录等问题。
它适合:
- 一组资源打包发布;
- 多环境参数化;
- 复用第三方组件安装模板;
- 管理应用版本。
它不直接解决:
- 应用自身是否健康;
- 数据库迁移是否安全;
- 复杂状态机怎么自动处理;
- 某个业务系统的运维知识。
可以这样看:
1 | Helm |
Helm 更像安装清单,Operator 更像长期值班的运维同学。
CRD:让 Kubernetes 认识新资源
Kubernetes 自带很多资源:
1 | Pod |
CRD,全称 CustomResourceDefinition,可以让集群认识新的资源类型。
比如定义一个 Backup 资源:
1 | apiVersion: apiextensions.k8s.io/v1 |
创建 CRD 后,就可以创建自定义资源:
1 | apiVersion: example.com/v1 |
这时 Kubernetes API Server 能保存和校验这个新对象。
1 | CRD |
只有 CRD 还不够
CRD 让 Kubernetes 认识新对象,但它不会自动知道怎么处理这个对象。
1 | 创建 Backup 对象 |
这和 Deployment 不一样。Deployment 有 Kubernetes 内置控制器负责管理 ReplicaSet 和 Pod。
自定义资源通常需要配套控制器:
1 | Custom Resource |
所以 CRD 更像“新增表单类型”,Controller 才是“处理表单的人”。
Operator:把运维知识写成控制器
Operator 通常由 CRD 和自定义控制器组成,用来自动化管理复杂应用。
例如数据库 Operator 可能支持:
- 创建数据库集群;
- 配置主从或副本;
- 处理备份;
- 扩容缩容;
- 故障切换;
- 升级版本;
- 更新状态。
用户提交一个自定义资源:
1 | apiVersion: database.example.com/v1 |
Operator 看到后执行:
1 | 创建 StatefulSet |
这和前面控制循环是一脉相承的:
1 | 读取期望状态 |
只不过这次控制器不是 Kubernetes 内置的,而是我们或第三方提供的。
Helm 和 Operator 的区别
我一开始容易把 Helm 和 Operator 混在一起,因为它们都能“安装应用”。
现在我这样区分:
1 | Helm |
例如安装 MySQL:
1 | Helm Chart |
简单服务用 Helm 组织 YAML 已经很好。复杂有状态系统,如果运维流程也要自动化,才更适合看 Operator。
CRD 使用时要注意什么
CRD 很强,但也不能滥用。
我会先问几个问题:
- 是否真的需要一种新资源类型?
- 普通 Deployment、Job、ConfigMap 是否已经够用?
- 有没有控制器持续处理这个资源?
- 版本升级和字段兼容怎么做?
- 删除自定义资源时,关联资源怎么清理?
- 谁维护这个 Operator?
因为 CRD 一旦进入集群,就扩展了 API 面。
1 | 新增 CRD |
如果只是为了少写几行 YAML,就不一定值得创建 CRD。
一个更现实的使用顺序
对普通应用来说,我觉得可以按这个顺序理解:
1 | 第一步:直接写 YAML |
不要一开始就把所有东西都 Operator 化。
很多普通 Web 服务只需要:
1 | Deployment |
再用 Helm 管理参数就够了。
把整个系列串起来
到这一篇,Kubernetes 的基本地图就比较完整了:
1 | 运行单元 |
这些概念看起来很多,但核心思路一直没变:
1 | 声明期望状态 |
小结
这一篇整理下来,我对 Helm、CRD 和 Operator 的理解可以概括成几句话:
- Helm 用来打包、模板化和发布一组 Kubernetes 资源;
- Chart 是包,Release 是安装出来的实例;
- values 用来承载不同环境的参数;
- CRD 可以让 Kubernetes 认识新的资源类型;
- 只有 CRD 没有控制器,通常只是能保存对象,不能自动执行业务逻辑;
- Operator 把特定应用的运维知识写成控制器;
- Helm 更偏交付打包,Operator 更偏运行期自动管理;
- CRD 和 Operator 很强,但要考虑版本、权限、升级和维护成本;
- 普通应用可以先用原生对象和 Helm,复杂有状态系统再考虑 Operator。
这个 Kubernetes 入门系列到这里,可以算先完成了一张基础地图。后面如果继续写,我更想按专题深入,比如 HPA 自动扩缩容、调度策略、服务网格、CI/CD 发布流程、生产集群故障案例等。
参考资料
- Helm Docs:https://helm.sh/docs/
- Custom Resources:https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/
- Operator Pattern:https://kubernetes.io/docs/concepts/extend-kubernetes/operator/
- Extend the Kubernetes API with CustomResourceDefinitions:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/