StatefulSet故障恢复:Pod-0启动失败时能否跳过启动后续Pod?
嘿,我之前在运维Percona XtraDB Cluster的StatefulSet部署时,碰到过几乎一模一样的问题——强制双节点故障后,StatefulSet死磕Pod-0启动失败,整个集群卡着没法恢复。给你分享下当时的解决思路和步骤:
StatefulSet的**OrderedReady(有序就绪)**部署策略是核心问题:它会严格按照Pod序号从0到N的顺序启动/恢复,Pod-0启动失败的话,后续的Pod-1完全不会被调度启动。而Percona集群在全节点故障后,Pod-0启动时会尝试寻找原有集群的节点,找不到就会触发WSREP的启动报错,直接卡壳。
1. 先清理残留的故障Pod
先把所有残留的故障Pod和StatefulSet的副本数临时置0,确保环境干净:
# 调整副本数为0,删除所有Pod kubectl scale statefulset <你的StatefulSet名称> --replicas=0 # 等待所有Pod被彻底删除 kubectl wait --for=delete pod/<你的StatefulSet名称>-0 pod/<你的StatefulSet名称>-1
2. 临时修改StatefulSet策略,优先启动Pod-1
把StatefulSet的podManagementPolicy改成Parallel(并行),这样就不会卡死在Pod-0的启动上,先让Pod-1起来:
kubectl patch statefulset <你的StatefulSet名称> -p '{"spec":{"podManagementPolicy":"Parallel"}}' # 调整副本数为1,只启动Pod-1 kubectl scale statefulset <你的StatefulSet名称> --replicas=1
等Pod-1启动成功后,进入Pod确认集群状态:
kubectl exec -it <你的StatefulSet名称>-1 -- mysql -u root -p # 执行以下命令确认单节点集群正常运行 SHOW STATUS LIKE 'wsrep_cluster_size'; SHOW STATUS LIKE 'wsrep_ready';
只要看到wsrep_cluster_size=1且wsrep_ready=ON,就说明Pod-1已经形成可用的单节点集群了。
3. 修复/重建Pod-0
这里分两种情况处理:
情况A:Pod-0的存储卷数据完好,只是无法加入集群
直接把副本数调回2,让Pod-0启动,然后手动让它加入Pod-1的集群:
kubectl scale statefulset <你的StatefulSet名称> --replicas=2 # 等Pod-0启动(可能处于CrashLoopBackOff,先进入Pod) kubectl exec -it <你的StatefulSet名称>-0 -- bash # 停止mysql服务 service mysql stop # 执行同步命令,替换成你的集群服务地址(比如<你的StatefulSet名称>-1.<你的服务名称>.svc.cluster.local) wsrep_sst_xtrabackup-v2 --address=<Pod-1的集群地址> --user=sstuser --password=<你的SST同步密码> --socket=/var/run/mysqld/mysqld.sock --datadir=/var/lib/mysql/ # 重启mysql服务 service mysql start
回到Pod-1里执行SHOW STATUS LIKE 'wsrep_cluster_size';,看到数值变成2就说明集群恢复了。
情况B:Pod-0的存储卷数据损坏
直接删除Pod-0绑定的PVC,让StatefulSet重新创建一个新的存储卷,Pod-0会自动从Pod-1同步完整数据:
# 删除Pod-0的PVC,注意替换成你的PVC名称(一般是<PVC前缀>-0) kubectl delete pvc <你的PVC名称>-0 # 调整副本数为2,Pod-0会重新创建并自动同步数据 kubectl scale statefulset <你的StatefulSet名称> --replicas=2
4. 恢复StatefulSet的有序部署策略(可选但建议)
集群恢复正常后,把podManagementPolicy改回默认的OrderedReady,保证后续的扩容/恢复是有序的:
kubectl patch statefulset <你的StatefulSet名称> -p '{"spec":{"podManagementPolicy":"OrderedReady"}}'
- 操作前一定要确认Pod-1的数据是完整的,可以通过查看Pod-1的mysql日志或者执行数据校验命令来确认,避免同步坏数据
- 日常运维要做好定期备份,比如用Percona XtraBackup或者Kubernetes的Volume快照功能,防止全节点故障后数据丢失
- 可以给StatefulSet配置PodDisruptionBudget,限制同时故障的Pod数量,降低这类极端场景的发生概率
内容的提问来源于stack exchange,提问作者StokeHead

