StatefulSet是Kubernetes中唯一能同时满足固定Pod名称、稳定DNS、有序启停和专属持久化存储的原生控制器,专用于MySQL、ZooKeeper等有状态服务。

要在Kubernetes中部署一个真正可用的有状态服务(比如MySQL主从、ZooKeeper集群或Kafka Broker),必须让每个Pod拥有固定名称、稳定DNS、启动顺序可控,并且挂载专属且不共享的持久化存储——StatefulSet是唯一能同时满足这四点的原生控制器。
准备Headless Service与StorageClass
StatefulSet必须搭配Headless Service才能生成稳定的DNS记录,否则Pod无法通过pod-name.service-name.ns.svc.cluster.local互相发现。先创建Service资源:
执行kubectl apply -f headless-svc.yaml,其中spec.clusterIP必须设为None;若漏掉这行,所有Pod将共享同一个ClusterIP,彻底失去独立网络身份。
确认StorageClass已就绪:运行kubectl get sc,确保至少有一个BINDINGMODE为WaitForFirstConsumer的可用类——这是避免PVC提前绑定到错误节点的关键前提。
编写StatefulSet YAML核心字段
重点配置三项不可省略的字段:
① serviceName:必须与上一步创建的Headless Service名称完全一致,大小写敏感;否则Pod启动后无法注入DNS条目,连接集群会直接超时。
② replicas:设为3表示要启动web-0、web-1、web-2三个有序Pod;缩容时会从web-2开始终止,确保主节点(通常为web-0)最后下线。
③ volumeClaimTemplates:定义PVC模板,注意metadata.name值(如www)将作为PVC名称前缀,后续会自动生成www-web-0、www-web-1等独立PVC。
这一步不能用Deployment的volumes字段替代——那是共享卷,会导致所有Pod写入同一块磁盘,数据立即损坏。
应用YAML并验证Pod与存储绑定关系
方法一:直接部署
运行kubectl apply -f statefulset.yaml,等待所有Pod进入Running状态。
方法二:分步观察(推荐调试时使用)
先执行kubectl create -f statefulset.yaml --dry-run=client -o yaml > debug.yaml检查字段合法性;再用kubectl get pvc确认是否生成了3个独立PVC;最后用kubectl get pv核对每个PVC是否绑定到不同PV(若全部绑定到同一PV,说明StorageClass配置错误或底层存储插件未启用volumeBindingMode: WaitForFirstConsumer)。
【关键验证命令】运行kubectl exec web-0 -- df -h /usr/share/nginx/html,输出应显示挂载点来自pvc-xxxxx而非tmpfs或overlay——否则说明volumeClaimTemplates未生效,Pod仍在使用容器根文件系统。
检查DNS解析与启动顺序
第一步:确认Headless Service生效
执行kubectl run dns-test --rm -it --image=busybox:1.35 --restart=Never -- nslookup web-0.nginx-svc.default.svc.cluster.local,返回IP必须是web-0的真实Pod IP;若返回server can't find...,说明Service未关联到StatefulSet或selector标签不匹配。
第二步:验证有序启动
运行kubectl get pods -w,观察Pod状态变化:web-0先变成Running → 约10秒后web-1才开始ContainerCreating → 最后web-2启动;若三者几乎同时变为Running,说明StatefulSet的podManagementPolicy被误设为Parallel,需修正为默认的OrderedReady。
第三步:模拟节点故障
手动删除web-1:kubectl delete pod web-1,观察重建行为——新Pod仍叫web-1,且自动挂载原PVCwww-web-1,【数据不会丢失】;若重建后名称变成web-3或挂载了其他PVC,则volumeClaimTemplates中的name或storageClassName配置有误。











