节点NotReady时StatefulSet的Jenkins Pod卡在Terminating状态如何处理?
部署了一个副本数为1的Jenkins StatefulSet,运行该Pod的节点进入NotReady状态后,Jenkins Pod进入Terminating状态并长时间卡住,直到节点恢复Ready状态才恢复。希望节点异常时Pod能调度到健康节点,避免应用downtime,请问如何处理?
Kubectl版本信息:
Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.13", GitCommit:"53c7b65d4531a749cd3a7004c5212d23daa044a9", GitTreeState:"clean", BuildDate:"2021-07-15T20:58:11Z", GoVersion:"go1.15.14", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.13", GitCommit:"53c7b65d4531a749cd3a7004c5212d23daa044a9", GitTreeState:"clean", BuildDate:"2021-07-15T20:53:19Z", GoVersion:"go1.15.14", Compiler:"gc", Platform:"linux/amd64"}
核心原因
StatefulSet默认会等待Pod所在节点恢复后才终止或重建Pod,这是因为它需要保证存储卷的唯一性和状态连续性,单副本场景下Kubernetes不会强制驱逐节点NotReady状态下的StatefulSet Pod,进而导致downtime。
解决措施
1. 配置Pod驱逐相关参数
在StatefulSet的Pod模板中添加驱逐容忍规则,并配置PodDisruptionBudget:
- 修改StatefulSet的YAML,添加
spec.podManagementPolicy: Parallel(可选,加速Pod重建流程) - 配置Pod的
tolerations,让节点异常时触发驱逐逻辑:
tolerations: - key: "node.kubernetes.io/unreachable" operator: "Exists" effect: "NoExecute" tolerationSeconds: 300 - key: "node.kubernetes.io/not-ready" operator: "Exists" effect: "NoExecute" tolerationSeconds: 300
- 创建PodDisruptionBudget,确保Pod可被安全驱逐:
apiVersion: policy/v1beta1 kind: PodDisruptionBudget metadata: name: jenkins-pdb spec: minAvailable: 0 selector: matchLabels: app: jenkins
2. 启用StatefulSet强制删除特性
Kubernetes 1.19版本支持通过kube-apiserver启动参数开启强制删除StatefulSet Pod的特性,节点NotReady超过容忍时间后,Kubernetes会直接删除卡住的Pod并在健康节点重建:
# 修改kube-apiserver启动参数,添加如下配置 --feature-gates=ForceDeleteStatefulSetPods=true
3. 应急手动干预
如果Pod已出现卡住的情况,可手动强制删除Pod触发重建:
kubectl delete pod <jenkins-pod-name> --grace-period=0 --force
注意:需确保存储卷支持跨节点挂载(如NFS、Ceph等ReadWriteMany类型存储),否则新Pod可能无法挂载原存储卷导致启动失败。
4. 优化存储卷配置
将Jenkins使用的存储卷替换为支持跨节点访问的类型,比如ReadWriteMany模式的存储类,确保新Pod在健康节点能正常挂载原存储卷,避免存储导致的启动异常。
5. 调整副本数实现高可用(可选)
若业务允许,将StatefulSet副本数调整为2,搭配Jenkins主从或高可用配置实现冗余,一个节点异常时,另一个副本可继续提供服务,彻底消除downtime风险。
内容的提问来源于stack exchange,提问作者user3426197

