K8S删除命名空间卡住一直Terminating状态

背景

在命名空间下有资源,直接删除命名空间的时候一直Terminating状态,看样子是一直在处理删除操作,但卡在这里没有继续进度,导致实际完全没有执行删除操作。

在解决这个问题前需要先了解下k8s删除相关的概念

以我的总结就是卡在Terminating状态,资源Finalizer处理堵塞未完成导致关联存在无法删除成功,一直处于在处理中但实际并没有处理任务。

Finalizer是什么?

在 Kubernetes(K8s)中,Finalizer 是一种用于控制资源删除流程的 "钩子机制",它的核心作用是:确保资源在被彻底删除前,必须完成预设的前置操作(如数据清理、外部系统同步、依赖关系解除等)。

简单来说就是在删除前,解决这个资源所有与之相关的调用使用占用解绑,比如说pod绑定了pvc,要删除这个pod,就会通过Finalizer解除pod与pvc的关联,然后K8S再执行删除操作。

Finalizer 是存储在资源对象 metadata.finalizers 字段中的一组字符串列表(格式通常为 /,如 kubernetes.io/pvc-protection)。

例如,一个带有 Finalizer 的 PVC 资源可能长这样:

yaml 复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
  finalizers:  # Finalizer 列表
  - kubernetes.io/pvc-protection  # 内置 Finalizer,保护 PVC 不被意外删除
spec:
...

Finalizer 的工作原理

当你对一个带有 Finalizer 的资源执行 kubectl delete 时,Kubernetes 的删除流程会发生变化:

标记 "待删除":K8s 首先会给资源添加 deletionTimestamp 字段(记录删除请求的时间),但不会立即删除资源,资源状态会变为 Terminating。

等待 Finalizer 处理:K8s 会检查 metadata.finalizers 列表,若列表不为空,会等待对应的 "控制器"(Controller)处理这些 Finalizer。

移除 Finalizer:控制器完成预设操作(如 PVC 解绑、数据备份)后,会从列表中移除对应的 Finalizer。

彻底删除资源:当 metadata.finalizers 列表为空时,K8s 才会真正删除该资源(从 etcd 中移除记录)。

Terminating状态问题出现原因

在命名空间包含资源的情况下删除整个命名空间时,可能会出现 Finalizer 阻止删除的情况,但这与 "命名空间内有残留资源" 并非 "冲突关系",而是因果关联或并存关系------Finalizer 往往是导致 "资源无法删除(形成残留)" 的核心原因,进而间接导致命名空间删除停滞。

它分为两种场景,都会影响命名空间删除:

场景 1:命名空间内的资源自身带有 Finalizer,导致资源无法删除(形成 "残留资源")

这是最常见的情况。如果命名空间内的某个资源(如 PVC、Pod、StatefulSet)带有未处理的 Finalizer,会导致该资源无法被删除,进而使得命名空间的 "级联删除" 流程卡在第一步(资源清理阶段),表现为 "命名空间内有残留资源",但根源是 资源的 Finalizer 未被处理。

举例:

PVC 的 kubernetes.io/pvc-protection Finalizer:若 PVC 绑定的 PV 未被正确释放(如 PV 是 Retain 回收策略),该 Finalizer 会阻止 PVC 被删除,导致 PVC 成为 "残留资源",命名空间删除停滞。

Pod 的 pod.kubernetes.io/foregroundDeletion Finalizer:若 Pod 关联的控制器(如 StatefulSet)故障,无法完成 Pod 的前置清理(如数据卸载),该 Finalizer 会阻止 Pod 删除,形成残留。

自定义资源(CR)的 Finalizer:若命名空间内有自定义资源(如 Rook-Ceph 的 CephCluster),其对应的控制器(Operator)未正常运行,无法处理 CR 的 Finalizer(如数据卷解绑),会导致 CR 无法删除,成为残留资源。

此时,"残留资源" 是结果,"资源自身的 Finalizer 未处理" 是原因。

场景 2:命名空间自身带有 Finalizer,导致命名空间无法被最终删除

命名空间对象(Namespace)自身也有 spec.finalizers 字段(默认包含 kubernetes 这个 Finalizer),其作用是:确保 K8s 控制器已完成对该命名空间内所有资源的级联删除后,才允许删除命名空间本身。

若命名空间内的资源因各种原因(包括资源自身的 Finalizer 未处理)无法删除(形成残留),Kubernetes 会认为 "资源清理未完成",从而不会移除命名空间自身的 kubernetes Finalizer,导致命名空间卡在 Terminating 状态。

此时,"命名空间自身的 Finalizer 未被移除" 是结果,"命名空间内有残留资源(可能由资源 Finalizer 导致)" 是原因。

三、"Finalizer 阻止删除" 与 "命名空间内有残留资源" 的关系:不冲突,常伴随

两者并非 "冲突关系"(冲突意味着互斥,只能存在一个),而是 "因果关系" 或 "并存关系":

Finalizer和资源残留导致的无法删除区别

因果关系 资源自身的 Finalizer 未处理 → 资源无法删除(形成残留)→ 命名空间级联删除卡住 → 命名空间自身的 Finalizer 无法移除 → 命名空间删除被阻止。

并存关系 即使资源自身没有 Finalizer,但因控制器故障(如 API Server 异常)导致资源无法删除(残留),同时命名空间自身的 Finalizer 因 "资源未清理" 而无法移除,两者同时存在。

总结:两者本质是 "问题的不同层面"------"残留资源" 是现象,"Finalizer 未处理" 是常见根源(可能是资源的 Finalizer,也可能是命名空间自身的 Finalizer)。

Terminating状态问题处理方法

以我的环境为例,在有资源的情况下直接删除monitoring结果卡住无法删除

先看下运行中的yaml文件内容

shell 复制代码
kubectl get ns monitoring   -o yaml 

可以发现果然是卡在Finalizer这里

要解决的话也很简单,把Finalizer的值设置为空即可。

把命名空间的配置文件导出为json格式

shell 复制代码
kubectl get ns monitoring  -o json > monitoring.json

编辑monitoring.json文件,把其中"kubernetes"包括引号全部删除

shell 复制代码
vim monitoring.json

变成实际上的空状态

接着同节点新开个终端,临时启动个api代理

shell 复制代码
kubectl proxy --port=8080

回到原终端执行api命令

shell 复制代码
curl -X PUT http://localhost:8080/api/v1/namespaces/monitoring/finalize -H "Content-Type: application/json" -d @monitoring.json

curl -X PUT http://localhost:8080/api/v1/namespaces/命名空间/finalize -H "Content-Type: application/json" -d @导出的文件名.json

这个 curl 命令的作用是 通过 Kubernetes API 强制完成 monitoring 命名空间的删除流程,主要用于解决该命名空间卡在 Terminating 状态的问题。以下是各部分的详细解释:

命令拆解

bash 复制代码
curl -X PUT \
  http://localhost:8080/api/v1/namespaces/monitoring/finalize \
  -H "Content-Type: application/json" \
  -d @monitoring.json

curl

是一个命令行工具,用于发送 HTTP/HTTPS 请求,这里用于与 Kubernetes API 服务器交互。

-X PUT

指定 HTTP 请求方法为 PUT,用于更新已存在的资源。在 Kubernetes 中,PUT 通常用于修改资源的配置(这里是修改命名空间的删除相关配置)。

http://localhost:8080/api/v1/namespaces/monitoring/finalize

这是请求的目标 URL,指向 Kubernetes API 的特定端点,含义如下:

  • localhost:8080:通过 kubectl proxy 启动的本地代理端口(用于将请求转发到Kubernetes 集群的 API 服务器,避免直接处理认证复杂问题)。

  • /api/v1:Kubernetes 核心 API 的版本路径(固定格式)。

  • /namespaces/monitoring:指定操作的资源是名为 monitoring 的命名空间。

  • /finalize:命名空间删除的 "终结端点",专门用于处理命名空间删除时的最终清理(尤其是解决 Finalizers 阻塞问题)。

-H "Content-Type: application/json"

设置 HTTP 请求头,声明请求体的数据格式为 JSON(Kubernetes API 仅接受 JSON 格式的请求数据)。

-d @monitoring.json

指定请求体的内容来源:

-d 表示 "请求体数据"。

@monitoring.json 表示读取当前目录下 monitoring.json 文件的内容作为请求体(@ 符号是 curl 中 "读取文件内容" 的语法)。

该 monitoring.json 文件需要包含 monitoring 命名空间的关键配置,通常需满足:

保留原命名空间的 metadata.uid(确保操作的是同一个命名空间)。

将 spec.finalizers 设为 [](空数组),以移除阻塞删除的终结器(Finalizers)。

最终目的

通过这个命令,向 Kubernetes API 发送修改后的 monitoring 命名空间配置(清除阻塞删除的 Finalizers),强制触发命名空间的删除流程,解决其卡在 Terminating 状态的问题。

重新再查看下发现已经被删除了

相关推荐
牛奔15 分钟前
docker compose up 命令,默认配置文件自动查找规则
java·spring cloud·docker·容器·eureka
BigBigHang15 分钟前
【docker】离线设备安装镜像
运维·docker·容器
学好statistics和DS20 分钟前
Docker文件与本地文件,系统
运维·docker·容器
liuc031723 分钟前
docker下安装SearXNG
运维·docker·容器
oMcLin34 分钟前
如何在CentOS 8上配置并优化Docker与Kubernetes结合的容器集群,提升微服务部署效率?
docker·kubernetes·centos
可爱又迷人的反派角色“yang”1 小时前
k8s(一)
linux·运维·网络·云原生·容器·kubernetes
可爱又迷人的反派角色“yang”2 小时前
CICD持续集成Ruo-Yi项目
linux·运维·网络·ci/cd·docker·容器
星环处相逢2 小时前
K8s 网络插件选型:Flannel vs Calico 深度对比
网络·容器·kubernetes
Zsr10232 小时前
K8s网络方案深度解析:Flannel vs Calico 怎么选?
网络·容器·kubernetes·flannel·calico
白驹过隙^^3 小时前
windows通过docker compose部署oktopus服务
linux·windows·tcp/ip·docker·容器·开源