如何通过fabric8io的Java kubernetes-client获取PVC的已使用存储容量
问题说明
尝试通过fabric8io提供的Java kubernetes-client获取挂载到Pod上的PVC的space used指标,调用kubernetesClient.persistentVolumeClaims()接口仅能查询到PVC的总容量,无法获取已使用存储数据,期望得到如下格式的指标:
pvcs: [{ name: pvc-abc, requests: 500Mi, usedStorage: ???? }]
查询到的PVC原生对象返回示例如下:
PersistentVolumeClaim(apiVersion=v1, kind=PersistentVolumeClaim,..... capacity={storage=500Mi}, conditions=[], phase=Bound, additionalProperties={}), additionalProperties={})
解决方案
核心原理
Kubernetes PVC原生API对象仅存储配置类属性(如申请容量、存储类、绑定状态等),不包含实时存储用量指标。用量数据由集群的Metrics Server组件采集后通过Metrics API暴露,需要通过fabric8客户端的metrics相关接口获取。
实现前提
集群已正确部署Metrics Server组件,否则无法获取到实时用量指标。
代码实现
1. 获取挂载到指定Pod的PVC用量
该方式可以精准获取目标Pod挂载的PVC实际使用量:
import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; import io.fabric8.kubernetes.api.model.metrics.v1beta1.PodMetrics; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class PvcUsageDemo { public static void main(String[] args) { try (KubernetesClient client = new DefaultKubernetesClient()) { String namespace = "your-namespace"; String targetPodName = "your-pod-name"; List<Map<String, Object>> pvcResultList = new ArrayList<>(); // 构建Pod内volume名到实际PVC名的映射 Pod targetPod = client.pods().inNamespace(namespace).withName(targetPodName).get(); Map<String, String> volumeToPvcMap = new HashMap<>(); targetPod.getSpec().getVolumes().forEach(volume -> { if (volume.getPersistentVolumeClaim() != null) { volumeToPvcMap.put(volume.getName(), volume.getPersistentVolumeClaim().getClaimName()); } }); // 获取Pod的metrics数据 PodMetrics podMetrics = client.top().pods().inNamespace(namespace).withName(targetPodName).metrics(); podMetrics.getContainers().forEach(container -> { container.getVolumeMetrics().forEach(volumeMetric -> { String volumeName = volumeMetric.getName(); // 仅处理PVC类型的volume if (volumeToPvcMap.containsKey(volumeName)) { String pvcName = volumeToPvcMap.get(volumeName); // 查询PVC详情获取申请容量 PersistentVolumeClaim pvc = client.persistentVolumeClaims().inNamespace(namespace).withName(pvcName).get(); String requestsStorage = pvc.getSpec().getResources().getRequests().get("storage").getAmount() + pvc.getSpec().getResources().getRequests().get("storage").getFormat(); // 获取PVC已用容量 String usedStorage = volumeMetric.getUsed().get("storage").getAmount() + volumeMetric.getUsed().get("storage").getFormat(); // 拼装结果 Map<String, Object> pvcItem = new HashMap<>(); pvcItem.put("name", pvcName); pvcItem.put("requests", requestsStorage); pvcItem.put("usedStorage", usedStorage); pvcResultList.add(pvcItem); } }); }); // 输出结果 System.out.println("pvcs: " + pvcResultList); } } }
2. 批量获取命名空间下所有PVC的用量
如果不需要关联到具体Pod,直接批量查询所有PVC的用量可以用以下代码:
client.top().persistentVolumeClaims().inNamespace(namespace).list().getItems().forEach(pvcMetrics -> { String pvcName = pvcMetrics.getMetadata().getName(); String usedStorage = pvcMetrics.getUsage().get("storage").getAmount() + pvcMetrics.getUsage().get("storage").getFormat(); System.out.println("PVC名称:" + pvcName + ",已用存储:" + usedStorage); });
注意事项
- 部分低版本fabric8客户端的Metrics相关API可能在
client.metrics()路径下,可根据实际使用的客户端版本调整调用路径 - Metrics Server采集的指标存在1-2分钟的延迟,不属于实时秒级数据
- 部分自定义存储CSI驱动如果未实现用量采集接口,会出现无法获取usedStorage数据的情况
内容的提问来源于stack exchange,提问作者imalik8088
相关产品推荐
相关产品推荐

