为什么卡在 Terminating
命名空间删除不是一个原子动作,而是一次清理流程:apiserver 先把 status.phase 置为 Terminating,然后逐个 API 组枚举并删除命名空间内的全部资源,全部清干净后才会真正移除 Namespace 对象。只要还有资源因为 finalizer 无法完成删除,或某个 API 组不可用导致枚举与删除失败,命名空间就会长期停在 Terminating,同时它的名字也无法被复用。
基本信息
| 触发方式 | kubectl delete namespace <名称> |
|---|---|
| 内部状态 | status.phase 变为 Terminating |
| 卡住条件 | 存在未清理资源,或 API 组不可用导致列表失败 |
| 关键字段 | status.conditions[].message 指明剩余资源 |
| 后果 | 同名命名空间无法重建,直到旧对象真正消失 |
典型使用场景
- 环境下线:删除测试命名空间时卡住,需要先找出是哪些资源没清干净
- 卸载组件:CRD 删除后其自定义资源失去对应 API 组,资源变成删不掉的遗留对象
- Webhook 阻断:命名空间内的资源带 admission 校验,webhook 不可用时删除请求被拒
- finalizer 遗留:控制器已被卸载,资源的 finalizer 永远等不到人来移除
- 审计清理:确认残留资源确实无主后再处理,避免直接清 finalizers 造成对象泄漏
先看剩余什么资源
先看剩余什么资源
kubectl get namespace old-ns -o jsonpath='{.status.conditions[*].message}' # 官方给出的卡住线索
kubectl api-resources --verbs=list --namespaced -o name | xargs -n1 -I{} kubectl get {} -n old-ns --ignore-not-found 2>/dev/null | head -30
kubectl get all,cm,secret,pvc,sa,role,rolebinding,networkpolicy -n old-ns # 常用内建资源快速过一遍
kubectl get namespace old-ns -o json | sed -n '/"spec"/,/}/p' # 看 spec.finalizers 是否还在常见卡住原因
| 原因 | 典型表现 | 处理方向 |
|---|---|---|
| 资源自带 finalizer | 对象 metadata.finalizers 非空,删除请求挂起 | 确认控制器是否还在,移除 finalizer 前先核对资源用途 |
| CRD 已删除 | 自定义资源无对应 API 组,枚举不出也删不掉 | 恢复 CRD 后删除资源,或按官方流程清理 |
| 准入 webhook 不可用 | 删除请求被拒绝并返回 webhook 报错原文 | 恢复 webhook 服务或临时调整策略 |
| API 聚合层异常 | 某些 API 组无法列出,清理流程中断 | 先修复聚合层组件 |
| 集群 API 不可达 | 整体操作超时 | 先恢复控制面,再重试删除 |
直接清空 Namespace 的 spec.finalizers 等于跳过清理流程:命名空间会立刻消失,但里面的资源可能变成无法归属的遗留对象。只有在确认这些资源确实已废弃、且无法通过正常路径删除时才考虑,并做好记录。
不要用重建同名命名空间的办法绕过卡住状态:名字仍被旧对象占用,创建请求会失败或被静默忽略,先让旧的删除流程走完才是正路。