前言
这个系列前面大多数示例都围绕 Deployment,因为它最适合长期运行的无状态服务。
但 Kubernetes 不只有 Deployment。不同类型的任务,需要不同的控制器:
1 | Deployment |
我目前把它们理解成不同的“任务安排方式”。不是所有事情都适合用 Deployment 硬套。
Deployment:长期运行的无状态服务
Deployment 的特点前面已经写过:
1 | 保持副本数量 |
适合:
- Web API;
- 前端服务;
- 无状态 worker;
- 多副本等价的服务。
1 | Deployment |
如果一个 Pod 被删除,Deployment 通过 ReplicaSet 补一个新的。对无状态服务来说,这很自然。
但如果应用需要固定名字、固定存储、固定顺序,Deployment 就不一定合适。
DaemonSet:每个节点跑一份
DaemonSet 确保符合条件的每个节点上都运行一个 Pod。
1 | Node A -> Pod |
它适合节点级组件,例如:
- 日志采集 agent;
- 监控 agent;
- 网络插件;
- 存储插件;
- 节点安全扫描组件。
一个简单 DaemonSet:
1 | apiVersion: apps/v1 |
当新节点加入集群:
1 | Node D 加入 |
当节点被移除,对应 Pod 也会消失。
所以 DaemonSet 的核心不是“保持 N 个副本”,而是“每个目标节点一份”。
Job:跑完就结束
Job 用来执行一次性任务,目标是成功完成。
Deployment 追求的是:
1 | 一直运行 |
Job 追求的是:
1 | 成功跑完 |
适合:
- 数据处理任务;
- 一次性迁移;
- 批量计算;
- 手动触发的维护任务。
一个简单 Job:
1 | apiVersion: batch/v1 |
Job 的 Pod 正常结束后,状态会变成完成:
1 | Job |
这和 Deployment 不同。Deployment 里的容器如果退出,通常会被重启,因为它被期望长期运行。
CronJob:按时间跑 Job
CronJob 用来按时间表创建 Job。
适合:
- 定时备份;
- 定时报表;
- 定时清理;
- 周期性同步任务。
示例:
1 | apiVersion: batch/v1 |
可以理解成:
1 | CronJob |
schedule: "0 2 * * *" 表示每天 2 点执行。
CronJob 还有并发策略、成功失败历史保留等配置,真实使用时要关注:
1 | 上一次还没跑完,下一次来了怎么办? |
这里先抓住主线:CronJob 是定时创建 Job,不是自己一直跑业务进程。
StatefulSet:稳定身份和存储
StatefulSet 用来管理有状态应用。
它和 Deployment 最明显的区别是 Pod 身份稳定。
Deployment 管理的 Pod 名字像:
1 | demo-api-7c9d9f-a |
Pod 被替换后名字会变。
StatefulSet 管理的 Pod 名字像:
1 | mysql-0 |
这些序号有稳定意义。
1 | StatefulSet: mysql |
适合:
- 数据库;
- 有主从关系的服务;
- 需要稳定网络身份的服务;
- 每个副本有独立持久存储的服务。
一个简化 StatefulSet:
1 | apiVersion: apps/v1 |
这篇不深入数据库部署,只先建立边界:StatefulSet 比 Deployment 更适合表达“每个副本都有自己的身份和存储”。
Headless Service
StatefulSet 经常配合 Headless Service。
普通 Service 会提供一个稳定入口:
1 | Service: mysql |
Headless Service 不分配普通 ClusterIP:
1 | apiVersion: v1 |
它可以让客户端发现 StatefulSet 中每个 Pod 的稳定 DNS 名称。
1 | mysql-0.mysql.default.svc.cluster.local |
这对有状态服务很有价值,因为有时客户端需要明确连接某个副本,而不是随机打到任意一个。
怎么选择工作负载对象
我现在会先问应用属于哪种类型。
1 | 长期运行、无状态、多副本等价 |
不要为了熟悉 Deployment 就把所有东西都写成 Deployment。
例如:
1 | 定时清理任务用 Deployment |
对象选对,后面的 YAML 和运维逻辑会顺很多。
小结
这一篇整理下来,我对这些工作负载对象的理解可以概括成几句话:
- Deployment 适合长期运行的无状态服务;
- DaemonSet 适合每个节点运行一份的组件;
- Job 适合一次性执行并完成的任务;
- CronJob 适合按时间周期创建 Job;
- StatefulSet 适合需要稳定身份和稳定存储的有状态服务;
- StatefulSet Pod 名字带稳定序号;
- StatefulSet 常配合 Headless Service 提供稳定 DNS;
- 选择工作负载对象前,先判断任务的运行模式。
下一篇准备整理 Helm、CRD 和 Operator。前面看的都是 Kubernetes 自带对象,下一篇会看项目如何组织复杂 YAML,以及 Kubernetes 如何扩展出新的资源类型。
参考资料
- Deployments:https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
- DaemonSet:https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
- Jobs:https://kubernetes.io/docs/concepts/workloads/controllers/job/
- CronJob:https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
- StatefulSet:https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/