在 Kubernetes 中,Deployment 和 StatefulSet 都是用于管理 Pod 的控制器(Controller),但它们适用于不同类型的负载,主要区别在于对 有状态应用(Stateful Applications) 与 无状态应用(Stateless Applications) 的支持。
下面是两者的主要区别:
1. Pod 标识与网络标识
-
Deployment:
- Pod 是无序且无身份标识的。
- Pod 名称是随机生成的(如
my-app-7d5b8f9c4-xk2vq)。 - 每次重建 Pod,其名称、IP 都会变化。
-
StatefulSet:
- Pod 具有稳定的、唯一的标识。
- Pod 名称是有序的(如
my-statefulset-0,my-statefulset-1)。 - Pod 的主机名、DNS 记录稳定,即使被删除重建,也会保留相同的身份和网络标识。
2. 存储(Volume)
-
Deployment:
- 所有 Pod 共享相同的 Volume 配置,但每个 Pod 的 Volume 实例是独立的(如果使用 PVC 模板,则每个副本会创建自己的 PVC,但通常不推荐用于有状态场景)。
- 更适合临时性或可丢弃的数据。
-
StatefulSet:
- 每个 Pod 有自己专属的持久化存储卷(Persistent Volume Claim)。
- 即使 Pod 被调度到其他节点,其关联的 PVC 仍然绑定到该 Pod(通过 Pod 名称匹配)。
- 数据不会因 Pod 重建而丢失。
3. 部署与扩缩容顺序
-
Deployment:
- Pod 的创建、终止是并行的,没有固定顺序。
- 适合快速扩缩容。
-
StatefulSet:
- Pod 的创建、删除、扩缩容是按序进行的(例如先启动
my-set-0,再my-set-1)。 - 支持“有序部署”和“有序终止”,这对某些分布式系统(如 ZooKeeper、Kafka、MySQL 主从)至关重要。
- Pod 的创建、删除、扩缩容是按序进行的(例如先启动
4. 适用场景
-
Deployment:适用于无状态应用,例如 Web 服务器、API 服务、缓存等。这些应用不需要记住自身状态,可以随时替换。
-
StatefulSet:适用于有状态应用,例如:
- 数据库(MySQL、PostgreSQL、MongoDB)
- 分布式协调服务(ZooKeeper、etcd)
- 消息队列(Kafka、RabbitMQ 集群模式)
- 需要稳定网络标识或持久存储的应用
5. 更新策略
-
Deployment:
- 支持滚动更新(RollingUpdate)、重新创建(Recreate)等策略。
-
StatefulSet:
- 也支持滚动更新,但默认是按序更新(从高序号到低序号,或反之,取决于配置)。
- 可以设置
.spec.updateStrategy.type为RollingUpdate或OnDelete。
总结对比表:
| 特性 | Deployment | StatefulSet |
|---|---|---|
| Pod 身份 | 无身份、随机名 | 有序、稳定唯一标识 |
| 网络标识(DNS) | 不稳定 | 稳定(如 pod-name.svc) |
| 存储 | 通常共享或临时 | 每个 Pod 专属持久卷 |
| 启动/终止顺序 | 并行 | 有序 |
| 适用应用类型 | 无状态 | 有状态 |
| 更新策略 | 滚动更新等 | 按序滚动更新 |
如果你正在部署一个 Web 应用,用 Deployment;
如果你要部署数据库集群或需要稳定身份和存储的服务,用 StatefulSet。