彻底解决 k8s xxx 命名空间卡在 Terminating 的问题

前言

在 Kubernetes 集群管理中,命名空间(Namespace)卡在 Terminating 状态是一个常见但棘手的问题。这种状态通常由资源残留、Finalizers 未完成清理或控制器异常导致。本文将结合实践案例和底层原理,提供一套完整的解决方案,彻底解决此类问题。


一。问题现场

问题截图如下

另外 k8s中 命名空间(Namespace)卡在 Terminating 状态 可能还会导致以下问题

1. ​集群网络功能异常

若卡在 ​Terminating 的命名空间属于网络插件(如 Calico),可能导致:

​Pod 网络中断:新创建的 Pod 无法分配 IP 地址,跨节点通信失败。

​网络策略失效:安全策略(如 NetworkPolicy)无法生效,集群暴露于未授权的访问风险中。

​服务发现异常:依赖网络的服务(如 CoreDNS)无法正常工作,导致服务间无法解析域名。

2. 资源泄漏与控制器冲突

​资源占用:残留的 CRD(自定义资源)、ServiceAccount 等资源持续占用集群资源(如 IP 池、存储卷)。

​控制器逻辑混乱:重新部署同类组件时,新旧资源可能因同名 CRD 冲突,触发控制器崩溃或死锁。

​Finalizers 死锁:命名空间的 finalizers 字段未释放,可能阻塞其他资源的删除操作(如 PV/PVC)。

3. ​集群维护与升级受阻

​运维复杂性增加:残留命名空间可能干扰后续组件的升级或迁移流程,导致部署失败。

​监控误报:监控系统(如 Prometheus)可能因残留的指标端点持续告警,干扰运维判断。

​依赖链断裂:若其他组件(如 Istio)依赖该命名空间的资源,可能引发级联故障。

4. ​存储与持久化卷问题

​PV/PVC 清理失败:存储控制器(如 Rook)依赖 Finalizers 确保数据安全,命名空间状态异常可能导致存储资源无法释放。

​存储策略冲突:残留的存储配置可能影响新存储资源的分配策略

二、问题根源分析

  1. Finalizers 未释放

    Kubernetes 通过 finalizers 字段确保资源删除前的清理逻辑(如释放存储卷、级联删除关联资源)。若 Finalizers 中的控制器未响应或资源依赖未解除,删除流程会被阻塞。

  2. 残留资源未清理

    命名空间内可能残留 ServiceAccount、CRD 自定义资源、Pod 等未被完全删除的组件,尤其是通过 Operator 或 Helm 安装的复杂应用(如 Calico、Prometheus)。

  3. API 通信或控制器故障

    集群组件(如 kube-controller-manager)异常或网络问题可能导致 Finalizers 清理失败。


三、解决方案详解

步骤 1:强制删除命名空间

通过 --force 参数跳过优雅终止期,直接触发删除逻辑:

bash 复制代码
kubectl delete ns <NAMESPACE_NAME> --force --grace-period=0

若失败,通常是由于残留资源或 Finalizers 未解除,需进入下一步。


步骤 2:手动清理残留资源

通过以下命令列出命名空间内所有资源并强制删除:

bash 复制代码
# 列出所有命名空间内资源类型
kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get --show-kind --ignore-not-found -n <NAMESPACE_NAME>

# 强制删除残留资源(例如 ServiceAccount)
kubectl delete serviceaccount/<NAME> -n <NAMESPACE_NAME> --force --grace-period=0

关键点

• 若资源删除失败,需手动移除其 Finalizers(参考步骤 3 对命名空间的操作)。


步骤 3:移除命名空间的 Finalizers

方法 1:通过 API 直接操作

bash 复制代码
# 查看命名空间下是否存在资源
kubectl get -n <NAMESPACE_NAME> -- all
# 导出命名空间配置
kubectl get ns <NAMESPACE_NAME> -o json > ns.json
# 删除 finalizers 字段(编辑 JSON 文件,移除 "finalizers": [...] 部分)

删除前

删除后

shell 复制代码
# 新建一个窗口执行
kubectl proxy

# 当前服务器窗口执行
# calico-ns.json 替换为自己的json 文件 
# calico-system 替换为自己的namespace
curl -k -H Content-Type: application/json -X PUT --data-binary @calico-ns.json http://127.0.0.1:8001/api/v1/namespaces/calico-system/finalize

# 执行完成后 关闭另一个窗口的代理
# 再次检查命名空间
kubectl get ns

发现之前命名空间 calico-system 一直在Terminating的状态 现在已经正常了

作用:绕过控制器逻辑,直接解除 Finalizers 阻塞。

方法 2:使用 kubectl patch

bash 复制代码
kubectl patch namespace <NAMESPACE_NAME> -p '{"metadata":{"finalizers":[]}}' --type='merge'

此方法适用于未完全卡死的场景。


步骤 4:检查 Etcd 数据残留(可选)

若上述步骤无效,可能是 Etcd 中残留了命名空间的元数据:

bash 复制代码
# 进入 Etcd Pod 操作(假设使用默认部署)
kubectl exec -it -n kube-system etcd-<NODE_NAME> -- sh

# 查询并删除残留数据
ETCDCTL_API=3 etcdctl get /registry/namespaces/<NAMESPACE_NAME>
ETCDCTL_API=3 etcdctl del /registry/namespaces/<NAMESPACE_NAME>

注意:直接操作 Etcd 存在风险,需谨慎执行。


三、进阶排查与修复

  1. 检查控制器日志

    查看 kube-controller-manager 日志,定位 Finalizers 阻塞原因:

    bash 复制代码
    kubectl logs -n kube-system kube-controller-manager-<NODE_NAME> | grep "namespace/<NAMESPACE_NAME>"
  2. 修复 RBAC 权限问题

    若匿名用户(如通过 kubectl proxy 调用 API)因权限不足导致删除失败,需绑定 ClusterRole:

    bash 复制代码
    kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous

    此操作需评估安全风险。


四、总结与预防建议

  1. 预防措施

    • 删除命名空间前,确保其内资源已清理。

    • 避免直接删除由 Operator 管理的 CRD 资源(需先卸载 Operator)。

  2. 快速恢复流程

    是 否 命名空间卡在 Terminating 是否有残留资源? 强制删除残留资源 移除 Finalizers 验证命名空间删除

  3. 工具推荐

    • 使用 kubectl-neat 插件清理资源 Finalizers。

    • 通过 k9s 可视化工具快速定位残留资源。

通过以上步骤,可彻底解决命名空间卡在 Terminating 状态的问题。若仍存在异常,建议结合集群日志和组件健康状态进一步排查。

相关推荐
木二8 小时前
附035.Kubernetes_v1.25.3高可用部署架构二
云原生·kubernetes
明明跟你说过9 小时前
在【k8s】中部署Jenkins的实践指南
运维·ci/cd·云原生·容器·kubernetes·jenkins
酥暮沐9 小时前
K8S 集群搭建——cri-dockerd版
linux·容器·kubernetes
a_j589 小时前
k8s面试题总结(十)
云原生·容器·kubernetes
沉默的八哥9 小时前
RBAC的工作原理,以及如何限制特定用户访问
运维·kubernetes
一条闲鱼_mytube10 小时前
[Kubernetes] 7控制平面组件
java·平面·kubernetes
海鸥8119 小时前
在 k8s中查看最大 CPU 和内存的极限
linux·容器·kubernetes
rocksun21 小时前
使用GITOPS简化KUBERNETES实施:最佳实践
kubernetes
海鸥811 天前
查看k8s集群的资源使用情况
云原生·容器·kubernetes