最近在 Kubernetes 使用中,有个 Pod 一直处于 Terminating
状态,通常原因是 Pod 占用的某些资源未被正确释放(如 Finalizers、Volume 挂载、网络资源、节点状态为NotReady等),强制删除也一直卡住,尝试了各种姿势,最后不得不去 ETCD 删除 Pod 数据解决,mark一下。
1. 检查 Finalizers
Finalizers 是 Kubernetes 中用于控制资源删除、防止资源被意外删除的保护机制。如果 Pod 的 metadata.finalizers
字段不为空,Kubernetes 会等待这些 Finalizers 被清除后才能删除 Pod。
解决方法:
手动编辑 Pod,移除 Finalizers:
kubectl edit pod <pod-name> -n <namespace>
找到 metadata.finalizers
字段,将其设置为空数组 []
,然后保存退出。
或者使用
patch
命令直接移除 Finalizers:
# 查看 Pod 的 Finalizers kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.metadata.finalizers}' # 移除 Pod 的 Finalizers kubectl patch pod <pod-name> -n <namespace> -p '{"metadata":{"finalizers":[]}}' --type=merge
2. 检查节点状态
如果 Pod 所在的节点(Node)出现问题(如节点宕机或网络断开),Pod 可能会一直卡在 Terminating
状态。
方法:
检查节点状态:
kubectl get nodes
如果节点状态为 NotReady
,尝试重启节点或修复节点问题,通常包括。
检查节点硬件资源,确保资源充足。
检查节点网络状态,确保节点能够正常通信。
检查节点上的容器运行状态,确保容器正常运行。
3. 检查 Volume 挂载
如果 Pod 使用了持久卷(Persistent Volume,PV),并且 PV 无法卸载,可能会导致 Pod 卡在 Terminating
状态。
方法:
检查 PV 和 PVC 的状态:
kubectl get pv kubectl get pvc -n <namespace>
如果 PV 或 PVC 处于异常状态,尝试手动修复或删除它们。
4. 重启 Kubelet
如果问题依然存在,可能与节点上的 Kubelet 有关,可以查看异常Pod 所在节点 Kubelet日志并尝试重启 Kubelet:
# 查看 kubelet 日志 journalctl -u kubelet -f # 重启 kubelet systemctl restart kubelet
5. 检查 API Server 日志
如果问题仍然存在,可以检查 Kubernetes API Server 的日志,查看是否有相关错误信息。
方法:
查看 API Server 日志:
kubectl logs -n kube-system kube-apiserver-<node-name> kubectl logs -n kube-system -l <label-name>=kube-apiserver
6. 强制删除 Pod
如果 Finalizers 已经移除,但 Pod 仍然卡在 Terminating
状态,可以尝试强制删除。
解决方法:
使用
kubectl delete
的--force --grace-period=0
参数:
kubectl delete pod <pod-name> -n <namespace> --force --grace-period=0
这会立即强制删除 Pod,但可能会留下一些未清理的资源。如果还是hang住无法删除,可以尝试直接删除 ETCD 中 Pod 记录。
7. 直接删除 ETCD 中的记录
在 Kubernetes 中,etcdctl
是一个用于直接与 ETCD 交互的命令行工具。ETCD 是 Kubernetes 的后端存储,所有资源(如 Pod、Service、Deployment 等)都存储在 ETCD 中。如果以上方法都无效,可以尝试直接删除 ETCD 中该 Pod 的记录。注意:直接操作 ETCD 可能会破坏 Kubernetes 集群的状态,建议仅在万不得已时使用,请谨慎执行。
步骤:
1、在操作 ETCD 之前,建议先备份 ETCD 数据:
# 备份 ETCD 数据 etcdctl snapshot save snapshot.db # 验证 ETCD 快照 etcdctl snapshot status snapshot.db # 恢复 ETCD 数据 etcdctl snapshot restore snapshot.db --data-dir /var/lib/etcd
2、查看 Pod 的 ETCD 记录:
Kubernetes 资源在 ETCD 中的存储路径遵循以下格式:/registry/<资源类型>/<namespace>/<资源名称>
例如:
Pod:
/registry/pods/default/my-pod
Deployment:
/registry/deployments/default/my-deploy
Service:
/registry/services/default/my-svc
Pod 的路径通常为:/registry/pods/<namespace>/<pod-name>
# 查看某个 Pod 的详细信息 etcdctl get /registry/pods/<namespace>/<pod-name> # 列出所有 Pod 的键 etcdctl get /registry/pods --prefix --keys-only
3、删除 Pod 的 ETCD 记录:
# 使用 etcdctl del 命令删除 Pod 的记录 etcdctl del /registry/pods/<namespace>/<pod-name>
4、验证删除 Pod 的 ETCD 记录:
# 删除后,可以通过以下命令验证 Pod 是否已从 ETCD 中移除 etcdctl get /registry/pods/<namespace>/<pod-name>
如果返回为空,说明 Pod 已成功删除。
5、K8s资源 ETCD 增删改查操作(可选):
# 列出所有 Pod 的键 etcdctl get /registry/pods --prefix --keys-only # 列出所有资源键 etcdctl get / --prefix --keys-only | grep "/registry/" # 修改资源(Update),导出资源为 JSON etcdctl get /registry/pods/default/my-pod --print-value-only > pod-data.json # 使用文本编辑器修改字段(如调整副本数、修复状态),重新写入 ETCD etcdctl put /registry/pods/default/my-pod < pod-data.json # 插入资源(Create),将 Kubernetes 资源 YAML 转换为 JSON,并确保符合 ETCD 存储格式 etcdctl put /registry/pods/default/new-pod < new-pod.json # 删除某个命名空间下的所有 Pod etcdctl del /registry/pods/<namespace> --prefix # 删除所有命名空间下的所有 Pod etcdctl del /registry/pods --prefix # 解码 Protobuf 数据,Kubernetes 默认使用 Protobuf 编码存储数据,可以通过 hexdump 或工具解码 etcdctl get /registry/pods/default/my-pod --print-value-only | hexdump -C
参考: