Kubernetes v1.37:跟踪 PersistentVolumeClaim 的最近使用时间(Beta)

Kubernetes v1.37 将 PersistentVolumeClaimUnusedSinceTime 特性门控提升到 Beta,并默认启用。借助这一功能,PersistentVolumeClaim(PVC)保护控制器会为每个 PVC 添加一个 Unused 状况,告诉你目前是否有运行中的 Pod 引用它——不再需要自定义工具或交叉核对。

PVC 状况的 API 定义见 PersistentVolumeClaim API 参考。下面介绍 Unused 状况的工作方式及用法。

为什么要跟踪 PVC 的使用情况?

在大规模 Kubernetes 集群中,用户经常会创建 PVC,随后删除关联的 Pod,却没有清理存储。为了防止意外丢失数据,Kubernetes 不会在 Pod 被删除时自动删除 PVC。随着时间推移,这些孤立的 PVC 可能不断积累,悄然消耗存储容量并推高云服务费用。

在 Kubernetes v1.37 之前,识别未使用的 PersistentVolume 比较容易,但判断某个 PVC 是否仍在使用就困难得多。这需要在可能很长的时间窗口内交叉核对 Pod、PersistentVolume 和 PVC。管理员往往不得不使用自定义监控流水线或脚本,回答一个看似简单的问题:“真的有东西在使用这个卷吗?”

PersistentVolumeClaimUnusedSinceTime 特性让答案直接出现在 PVC 状态中。启用后,每个 PVC 都会有一个由 PVC 保护控制器管理的 Unused 状况。

用户场景

  • 存储管理员:“我想知道集群中哪些 PVC 没有被任何 Pod 使用,以便安全地识别孤立卷,并安排删除。”
  • DevOps 工程师:“我想列出 Unused 状况为 True 的 PVC,从而自动清理开发环境。”

它如何工作?

PVC 保护控制器原本就会监视 Pod,以执行使用中的存储对象保护;现在它还会管理 PVC 上新增的 Unused 状况。

这个状况的行为如下:

场景 状况状态 原因
没有非终态 Pod 引用该 PVC Unused=True NoPodsUsingPVC
至少一个 Running 或 Pending 的 Pod 引用该 PVC Unused=False PodUsingPVC

需要注意以下细节:

  • 已经终止的 Pod 不计入使用:已经完成的 Pod(阶段为 Succeeded 或 Failed)不会使 PVC 继续保持使用中。这意味着采用 restartPolicy: Never 的批处理任务完成后,不会阻止 PVC 变成 Unused=True。
  • Pending 的 Pod 仍计入使用:即使 Pod 无法被调度(例如指定了不可能满足的节点选择器),它仍算作正在使用 PVC。只要存在使用这个卷的意图就足够了。
  • 多个 Pod:如果多个 Pod 引用同一个 PVC,只有在最后一个尚未终止的 Pod 被移除或终止后,状况才会变为 Unused=True。

使用 lastTransitionTime 判断 PVC 何时开始闲置

与所有 Kubernetes 状况一样,Unused 状况带有标准的 lastTransitionTime 字段。这额外提供了一个实用信息:当状况从 False 变为 True 时,lastTransitionTime 会准确记录 PVC 开始闲置的时间。你可以用这个时间戳回答“这个 PVC 已经闲置多久?”之类的问题,例如查找闲置超过30天的 PVC(见下方查询示例)。

从 Alpha 到 Beta 有哪些变化?

Kubernetes v1.36 以 Alpha 形式引入这项功能,当时需要显式启用 PersistentVolumeClaimUnusedSinceTime 特性门控。在 v1.37 的 Beta 阶段,该门控默认启用,并且该功能已具备完整的端到端测试覆盖。

如何使用

由于该功能在 Kubernetes v1.37 中处于 Beta 且默认启用,PVC 会自动出现 Unused 状况。下面通过一个过程演示它的行为。

  1. 创建 PVC:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
    
  2. 稍等片刻后,检查 PVC 的状况:

    kubectl get pvc my-data -o jsonpath='{.status.conditions[*]}' | jq .
    

    你应当看到 Unused 状况,其状态为 True,原因为 NoPodsUsingPVC:

    {
      "lastProbeTime": null,
      "lastTransitionTime": "2026-09-14T12:03:11Z",
      "message": "No pods are currently referencing this PVC",
      "reason": "NoPodsUsingPVC",
      "status": "True",
      "type": "Unused"
    }
    
  3. 创建一个使用该 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
    
  4. 再次检查状况,此时应显示 Unused=False:

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

    输出:

    False
    
  5. 删除 Pod,并等待状况重新变成 Unused=True:

    kubectl delete pod my-app
    kubectl get pvc my-data -o jsonpath='{.status.conditions[?(@.type=="Unused")]}'
    

    状况应再次显示 Unused=True,原因为 NoPodsUsingPVC。

查找整个集群中未使用的 PVC

要列出所有闲置超过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)"
'

下一步是什么?

根据反馈和采用情况,Kubernetes 项目计划在未来版本中将该功能提升到正式可用(GA)。如果你对这项功能有反馈,请在 kubernetes/kubernetes 仓库中提交 issue。

更多关于这一增强功能的信息,见 KEP-5541:PersistentVolumeClaim 最近使用时间。

参与贡献

Kubernetes 项目始终欢迎新贡献者。如果你希望参与,可以加入 SIG Storage。

如果你希望分享反馈,也可以通过我们的公开 Slack 频道交流(如需邀请,请访问 https://slack.k8s.io/)。

特别感谢参与设计和实现这项功能的贡献者(按字母顺序):

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容