在Kubernetes生态中,StatefulSet是专为有状态应用设计的控制器对象。与常见的Deployment不同,StatefulSet为每个Pod维护固定的标识符和持久化存储,这使得它成为运行数据库、消息队列等需要稳定网络标识和持久化存储的应用的理想选择。
StatefulSet的核心特性体现在三个方面:
提示:当你的应用需要以下特性时,应该优先考虑StatefulSet:
- 稳定的、可预测的Pod名称
- 持久化存储且数据与Pod生命周期解耦
- 有序的、优雅的部署和扩展
StatefulSet控制器通过以下机制维护应用状态:
通过对比表可以清晰看出两者的设计差异:
| 特性 | StatefulSet | Deployment |
|---|---|---|
| Pod名称 | 固定(web-0, web-1) | 随机哈希(web-59fd8c..) |
| 存储卷 | 每个Pod独立PVC | 所有Pod共享PVC |
| 网络标识 | 稳定的DNS名称 | 共享Service IP |
| 扩缩容顺序 | 严格有序(0→N) | 并行无序 |
| 适用场景 | 数据库、消息队列等有状态应用 | 无状态Web应用 |
以下是一个MySQL集群的StatefulSet配置示例:
yaml复制apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql-service" # 必须关联的Headless Service
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: 10Gi
serviceName:必须指定一个已创建的Headless Service名称,该Service应该:
clusterIP: NonevolumeClaimTemplates:动态创建PVC的核心配置:
podManagementPolicy:可选配置项,默认为OrderedReady(有序部署),对于可以并行启动的应用可以设置为Parallel以加速部署
StatefulSet支持两种更新策略:
RollingUpdate(默认):按逆序(N-1→0)逐个更新Pod,确保集群可用性
spec.updateStrategy.rollingUpdate.partition可以实现金丝雀发布OnDelete:手动删除Pod时才会触发更新,适用于需要人工干预的场景
存储类选择:
备份方案设计:
bash复制# 示例:定期备份MySQL数据
kubectl exec mysql-0 -- mysqldump -u root -p$MYSQL_ROOT_PASSWORD --all-databases > backup.sql
存储扩容操作:
StatefulSet创建的Pod可以通过以下形式互相发现:
bash复制# 在mysql-0中访问mysql-1的服务
mysql -h mysql-1.mysql-service.default.svc.cluster.local -u root -p
对于需要特殊拓扑关系的应用(如ETCD集群),可以通过初始化容器配置成员列表:
yaml复制initContainers:
- name: init-etcd
image: etcd:3.4
command:
- /bin/sh
- -c
- |
peer_url="http://$(hostname).etcd-service:2380"
etcdctl member add $(hostname) --peer-urls=$peer_url
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| Pod卡在Terminating状态 | 存储卷无法卸载 | 检查节点kubelet日志,必要时强制删除 |
| PVC处于Pending状态 | StorageClass配置错误 | 验证StorageClass是否存在且可用 |
| DNS解析不稳定 | Headless Service未正确配置 | 确保Service的clusterIP设置为None |
| 扩缩容操作超时 | Pod未正确报告就绪状态 | 检查readinessProbe配置 |
反亲和性配置:避免所有副本集中在同一节点
yaml复制affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: [mysql]
topologyKey: kubernetes.io/hostname
资源限制与请求:为有状态应用设置合理的资源限制
yaml复制resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "4"
memory: "8Gi"
自定义Pod管理策略:对于支持并行启动的应用,可以设置:
yaml复制podManagementPolicy: Parallel
在实际运维StatefulSet时,有几个容易忽视但至关重要的细节:
初始化顺序问题:对于需要按顺序初始化的集群(如MongoDB副本集),建议:
nslookup命令验证DNS记录是否生效bash复制until nslookup mysql-$((${HOSTNAME##*-}-1)).mysql-service; do sleep 2; done
存储回收策略:默认删除StatefulSet不会自动删除PVC,建议:
persistentVolumeReclaimPolicy: Retainkubectl delete pvc -l app=mysql手动清理监控特别项:除了常规指标外,需要额外关注:
升级注意事项:更新容器镜像版本时,建议: