删除为什么卡住
卷声明带有使用保护终结器:只要还有 Pod 引用它,删除请求只会给对象打上时间戳并让它停在终止状态,底层卷不会释放。这个机制避免正在写入数据的卷被误删。要真正删除,必须先把引用它的工作负载停掉。
基本信息
| 适用平台 | Kubernetes 1.20+,默认启用 |
|---|---|
| 保护范围 | 使用中的卷声明与卷 |
| 关键标记 | kubernetes.io/pvc-protection 终结器 |
| 典型现象 | 对象长期处于终止状态 |
| 正确顺序 | 先停工作负载,再删声明,最后处理后端卷 |
典型使用场景
- 清理测试环境时发现卷声明删不掉,需要查清还有谁在引用
- 有状态服务下线流程:先缩容到零,再删除声明与卷
- 误删声明后发现卷还在,判断数据是否安全
- 排查存储泄漏:确认哪些声明仍被工作负载占用
- 数据迁移前先解绑再删除,避免影响运行中的实例
正确删除流程
正确删除流程
kubectl delete pvc mysql-data # 仍被引用时停在终止状态
kubectl get pvc mysql-data # 确认当前状态
kubectl get pods -A -o json | grep mysql-data # 找出引用它的 Pod
kubectl delete deploy mysql # 释放引用
kubectl get pvc mysql-data # 引用消失后删除完成状态与含义
| 现象 | 含义 | 处理方式 |
|---|---|---|
| 声明停在终止中 | 仍有 Pod 或其他对象引用 | 先处理引用它的工作负载 |
| 声明已删但卷仍在 | 回收策略为保留 | 按策略确认是否需要手动删除 |
| 卷释放失败 | 存储后端仍有挂载点 | 确认节点侧挂载已卸载 |
| 销毁后重建同名声明 | 新卷可能为空 | 确认回收策略与备份情况 |
手动移除保护终结器会绕过整套安全机制,可能在仍有写入时释放底层卷。只在其确认没有任何进程写入的场景下使用。
有状态工作负载的卷声明不会随工作负载一起删除,这是刻意设计的保护:缩容或误删工作负载时数据仍然保留,清理时需要单独处理。