一、为什么需要 StatefulSet?
Kubernetes 的 Deployment 非常适合无状态服务,Pod 可以随意重建、替换。但当我们面对以下场景时,它就显得力不从心了:
- MySQL 主从部署,Pod 需要固定身份;
- Kafka、Zookeeper 等分布式系统,需要唯一标识和顺序启动;
- Redis Cluster、ElasticSearch 等组件,要求持久化存储和网络恒定性。
这时候,就轮到 StatefulSet 上场了。
二、StatefulSet 到底解决了什么问题?
StatefulSet 是为有状态应用设计的控制器,它解决了以下关键问题:
| 问题 | StatefulSet 的解决方式 |
|---|---|
| Pod 名称和身份不固定 | Pod 有固定序号(如 mysql-0, mysql-1) |
| 网络地址不稳定 | 每个 Pod 都有唯一 DNS(基于 Headless Service) |
| 存储卷被重新绑定或覆盖 | 每个 Pod 绑定一个持久化 PVC,删除 Pod 不会删数据卷 |
| 启动顺序与关闭顺序无法控制 | 按编号有序创建、删除、终止(比如 0 → 1 → 2) |
✅ StatefulSet = 有序编号 + 网络恒定 + 存储稳定
三、核心组件拆解
1. Pod 命名机制
metadata:
name: mysql
最终生成的 Pod 名为:
mysql-0
mysql-1
mysql-2
Pod 顺序是稳定的,每次重建也不会变化。
2. Headless Service 必不可少
spec:
serviceName: mysql-headless # 必须绑定 Headless Service
搭配 Headless Service 后,Pod 的 DNS 形式如下:
mysql-0.mysql-headless.default.svc.cluster.local
3. 每个 Pod 都绑定唯一 PVC
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
最终生成的 PVC 如下:
mysql-data-mysql-0
mysql-data-mysql-1
每个 Pod 永久使用对应 PVC,Pod 删除时 PVC 不会丢失。
四、完整 YAML 示例
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
spec:
clusterIP: None
selector:
app: mysql
ports:
- port: 3306
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql-headless
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
五、使用 StatefulSet 的注意事项
⚠️ 1. 删除顺序影响数据安全
StatefulSet 删除时,会按序逐个删除 Pod,并保留 PVC,这是为了数据安全。
如需连 PVC 一起清理,请手动删除对应的 PVC 资源。
⚠️ 2. 扩容建议逐步推进
扩容 StatefulSet 会新增 mysql-3、mysql-4 等 Pod。
由于状态相关,请保证应用支持新节点加入,如 Kafka 的 broker.id。
⚠️ 3. 禁止同时使用 RollingUpdate 和 Init Containers 执行数据库初始化
会导致多个 Pod 同时初始化数据,造成覆盖或数据冲突,建议通过 job+PVC 预写入。
六、StatefulSet vs Deployment 对比
| 特性 | Deployment | StatefulSet |
|---|---|---|
| Pod 命名 | 随机 | 有序、固定命名 |
| 网络地址 | 动态 | DNS 恒定 |
| 存储卷 | 可共享/动态挂载 | 固定绑定 PVC |
| 适用场景 | 无状态微服务 | 数据库、消息中间件 |
七、进阶技巧:如何与 Volume、Init、Affinity 结合使用?
- 利用 volumeClaimTemplates 实现数据分片;
- 结合 Pod Anti-Affinity 保证多个副本分布在不同节点上;
- 加入 Init Container 执行启动前依赖检查;
- 利用 readinessProbe 精细控制流量接入时机。
八、总结
StatefulSet 是 Kubernetes 中为有状态服务量身定做的解决方案。在你部署 MySQL、Redis Cluster、Kafka、Zookeeper、Elasticsearch 时,它都是你值得信赖的选择。
掌握 StatefulSet,意味着你迈出了从“用得起 Kubernetes”到“玩得转 Kubernetes”的关键一步。