Kubernetes v1.37:用 PVC 的 Unused 条件识别闲置存储

2026-09-22 37 预计阅读时间: 1 分钟
来源: kubernetes.io AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

在大型 Kubernetes 集群里,Pod 删除了,PVC 却通常会被保留下来。这种默认行为可以避免误删数据,但也容易让开发环境和临时任务积累大量无人使用的存储卷。Kubernetes v1.37 将 PersistentVolumeClaimUnusedSinceTime 特性提升到 Beta,并默认启用,让 PVC 自己告诉你:当前是否仍有非终止状态的 Pod 引用了它,以及它从什么时候开始闲置。

为什么 PVC 的闲置状态值得被原生记录

PVC 和 Pod 的生命周期并不绑定。用户删除 Deployment、Job 或临时调试 Pod 后,PVC 可能继续存在,背后的云盘也继续占用容量并产生费用。PVC protection controller 保留 PVC 的主要目的正是防止意外数据丢失,因此 Kubernetes 不会因为引用它的 Pod 消失,就自动删除 PVC。

过去,管理员想回答一个简单问题——某个 PVC 现在是否真的被使用——往往需要同时查询 Pod、PVC 和 PersistentVolume,再处理跨命名空间、历史 Pod 和终止状态等细节。集群规模一大,脚本和监控流水线很快就会变得复杂。

v1.37 的新能力把这个判断结果直接写入 PVC 的 status.conditions。只要启用了默认的 Beta 特性,每个 PVC 都会由 PVC protection controller 维护一个 Unused 条件。

Unused 条件到底表示什么

条件状态由当前 Pod 引用关系决定:

场景 status reason
没有任何非终止状态的 Pod 引用 PVC True NoPodsUsingPVC
至少有一个运行中或 Pending 的 Pod 引用 PVC False PodUsingPVC

这里有几个容易误判的边界:

  • Succeeded 或 Failed 的 Pod 不计入使用中。 批处理任务结束后,不会永久阻止 PVC 进入 Unused=True
  • Pending Pod 也计入使用中。 即使 Pod 因节点选择器不可能匹配而一直无法调度,只要它表达了使用该 PVC 的意图,条件仍然是 Unused=False
  • 多个 Pod 共享一个 PVC 时,以最后一个非终止 Pod 为准。 只有所有仍在运行或 Pending 的引用者都消失后,PVC 才会转为闲置。

这意味着 Unused=True 代表当前没有非终止 Pod 引用 PVC,并不等价于可以无条件删除。PVC 可能包含重要数据、被外部系统读取,或者只是暂时等待下一次任务使用。

lastTransitionTime:从状态判断闲置时长

Unused 是标准 Kubernetes condition,因此包含 lastTransitionTime。当条件从 False 变为 True 时,该字段记录 PVC 进入闲置状态的时间。

这比只看 PVC 的创建时间更有用:一个 PVC 可能创建于数月前,但昨天才被最后一个 Pod 释放。清理策略应该关注它闲置了多久,而不是它存在了多久。

例如,可以把规则定义为:

  • 闲置超过 7 天:进入候选列表,等待负责人确认;
  • 闲置超过 30 天:提交工单或进入开发环境自动清理流程;
  • 生产命名空间:只告警,不自动删除。

实际操作:创建、使用并观察 PVC

下面的示例假设集群版本为 v1.37 或更高,并且控制面组件正常运行。先创建一个 PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

保存为 pvc.yaml 后执行:

kubectl apply -f pvc.yaml
kubectl get pvc my-data -o jsonpath='{.status.conditions[?(@.type=="Unused")]}' | jq .

如果当前没有引用它的非终止状态 Pod,结果中应该能看到类似内容:

{
  "lastTransitionTime": "2026-09-14T12:03:11Z",
  "message": "No pods are currently referencing this PVC",
  "reason": "NoPodsUsingPVC",
  "status": "True",
  "type": "Unused"
}

接着创建一个引用 PVC 的 Pod:

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
    - name: app
      image: busybox
      command: ["sleep", "3600"]
      volumeMounts:
        - name: data
          mountPath: /data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: my-data
kubectl apply -f pod.yaml
kubectl get pvc my-data -o jsonpath='{.status.conditions[?(@.type=="Unused")].status}'
printf '\n'

此时输出应为:

False

删除 Pod 后,等待控制器更新状态,再检查条件:

kubectl delete pod my-app
kubectl wait --for=jsonpath='{.status.conditions[?(@.type=="Unused")].status}'=True pvc/my-data --timeout=60s
kubectl get pvc my-data -o jsonpath='{.status.conditions[?(@.type=="Unused")]}' | jq .

实际环境中,条件更新是异步的,因此删除 Pod 后应通过轮询或 kubectl wait 等待,而不是假设状态会立即变化。

集群范围筛选闲置超过 30 天的 PVC

下面的命令需要安装 jq。它会查询所有命名空间,筛选 Unused=TruelastTransitionTime 早于 30 天前的 PVC:

kubectl get pvc -A -o json | jq -r '
  .items[]
  | select(
      .status.conditions[]?
      | select(.type == "Unused" and .status == "True")
    )
  | select(
      (.status.conditions[] | select(.type == "Unused") | .lastTransitionTime) as $t
      | (now - ($t | fromdateiso8601)) > (30 * 86400)
    )
  | "\(.metadata.namespace)/\(.metadata.name) unused since \(.status.conditions[] | select(.type == "Unused") | .lastTransitionTime)"
'

输出可能类似:

team-a/cache-data unused since 2026-08-01T10:15:00Z
sandbox/test-volume unused since 2026-07-22T03:40:11Z

这个结果适合用作清理候选,而不是直接作为删除指令。自动化脚本还应加入命名空间白名单、PVC 标签、存储类和负责人审批等保护条件。

Beta 阶段的采用建议

从 Alpha 升级到 v1.37 Beta 后,特性门默认开启,并拥有完整的端到端测试覆盖。使用者通常不需要额外配置 feature gate,直接检查 PVC 的 status.conditions 即可。

不过,Unused=True 只是控制器根据 Pod 引用关系得出的运行时信号,存在几个边界:

  • 它不判断 PVC 中的数据是否重要;
  • 它不代表底层 PersistentVolume 已经被释放;
  • 它不替代备份、保留策略和业务负责人确认;
  • Pending Pod 会阻止 PVC 进入闲置状态,因此异常调度对象也需要纳入排查;
  • 大规模集群中应避免频繁全量扫描 API,最好将结果导出到监控或定时任务中。

可以采用下面这份落地清单:

  1. 在非生产集群先验证 Unused 条件的更新延迟和命名空间范围。
  2. 为 PVC 增加应用、环境和负责人标签,方便清理前确认归属。
  3. lastTransitionTime 建立 7 天、30 天等分级告警。
  4. 对生产 PVC 先通知和审批,不直接自动删除。
  5. 定期检查长期 Pending 的 Pod,避免错误引用让闲置 PVC 一直显示为使用中。

Kubernetes v1.37 把 PVC 使用情况从需要自行拼接的数据关系,变成了 PVC 状态中的标准条件。它不会替你决定哪些存储可以删除,但能显著降低发现孤立 PVC 的成本,让容量治理从定制脚本走向更一致的原生接口。


相关推荐