4. Kubernetes 存储组件拓扑图构建:使用 kube-state-metrics 与 csi-metrics 暴露存储资源拓扑

在租户配额校准体系中,存储资源拓扑的精确暴露是核心前提。本章将演示如何通过 kube-state-metrics (KSM) 与 csi-metrics 两个组件,构建完整的 Kubernetes 存储资源拓扑图,为后续 Prometheus 采集与配额计算提供结构化数据源。

4.1 存储拓扑数据源对比

KSM 与 csi-metrics 在存储拓扑暴露中扮演互补角色。KSM 提供控制面对象(PVC、PV、StorageClass)的元数据与状态;csi-metrics 则暴露存储后端(卷、快照、容量)的实时指标。下表对比两者的核心差异:

维度 kube-state-metrics csi-metrics
数据来源 Kubernetes API Server(控制面对象) CSI Driver Sidecar(存储后端)
暴露对象 PVC、PV、StorageClass、Namespace Volume、Snapshot、Capacity、Node
指标类型 元数据标签、状态计数、请求量 容量字节、使用率、IOPS、延迟
更新频率 依赖 API Watch(秒级) 依赖 CSI 驱动轮询(分钟级)
租户关联 通过 Namespace 标签直接关联 通过 VolumeHandle 间接关联
典型指标 kube_persistentvolumeclaim_info csi_volume_capacity_bytes
实践建议:KSM 适合做租户存储对象清单与配额基线;csi-metrics 适合做实际使用量校准。两者必须联合使用,才能形成完整的“申请-分配-使用”拓扑链路。

4.2 kube-state-metrics 存储指标暴露

KSM 默认暴露所有 Kubernetes 对象指标。对于存储拓扑,我们需要重点关注以下指标族:

  • PVC 相关:kube_persistentvolumeclaim_info(名称、命名空间、存储类、访问模式)、kube_persistentvolumeclaim_status_phase(Pending/Bound/Lost)
  • PV 相关:kube_persistentvolume_info(名称、存储类、回收策略)、kube_persistentvolume_capacity_bytes(容量)
  • StorageClass 相关:kube_storageclass_info(名称、Provisioner、参数)
  • Namespace 相关:kube_namespace_labels(租户标签)

部署 KSM 时,建议通过 --metric-whitelist 参数仅暴露存储相关指标,减少 Prometheus 采集压力:

kube-state-metrics \
  --metric-whitelist="kube_persistentvolumeclaim_.*" \
  --metric-whitelist="kube_persistentvolume_.*" \
  --metric-whitelist="kube_storageclass_.*" \
  --metric-whitelist="kube_namespace_labels"

4.3 csi-metrics 存储后端指标暴露

csi-metrics 是 CSI 规范定义的指标暴露接口,由 CSI Sidecar 容器(csi-external-provisioner、csi-external-attacher、csi-external-resizer)在 :9808 端口提供。核心指标包括:

  • 卷容量:csi_volume_capacity_bytes(按 VolumeHandle 和 Node 维度)
  • 卷使用率:csi_volume_used_bytes(实际已用空间)
  • 快照指标:csi_snapshot_info(快照名称、源卷、就绪状态)
  • 节点存储:csi_node_capacity_bytes(节点总容量与可用容量)

验证 csi-metrics 是否正常工作:

# 假设 CSI 驱动部署在 csi-driver 命名空间
kubectl -n csi-driver port-forward pod/csi-external-provisioner-0 9808:9808
curl http://localhost:9808/metrics | grep csi_volume
注意:并非所有 CSI 驱动都完整实现 csi-metrics 规范。生产环境建议先执行 curl /metrics 确认指标存在,再配置 Prometheus 采集。对于不支持的驱动,可考虑使用 node_exporter 的 filesystem 指标作为替代。

4.4 存储拓扑图构建:从指标到关系

将 KSM 与 csi-metrics 的指标关联起来,形成完整的存储拓扑图。核心关联逻辑如下:

  1. PVC → PV 绑定:通过 kube_persistentvolumeclaim_info 中的 volume_name 标签关联到 kube_persistentvolume_info。
  2. PV → CSI VolumeHandle:通过 kube_persistentvolume_info 中的 volume_handle 标签关联到 csi_volume_capacity_bytes 的 volume_handle 标签。
  3. PVC → Namespace → 租户:通过 kube_persistentvolumeclaim_info 的 namespace 标签关联到 kube_namespace_labels 中的租户标签(如 tenant_id)。
  4. PV → StorageClass:通过 kube_persistentvolume_info 的 storage_class 标签关联到 kube_storageclass_info。

下图展示了完整的存储拓扑关系:

Kubernetes 存储组件拓扑图 Kubernetes 存储组件拓扑图 租户 A Namespace: ns-tenant-a PVC: data-pvc-a StorageClass: fast-ssd PV: pv-abc-123 VolumeHandle: vol-001 CSI Volume 容量: 100Gi kube_namespace_labels tenant_id="tenant-a" kube_pvc_info volume_name="pv-abc-123" kube_pv_info volume_handle="vol-001" csi_volume_capacity_bytes volume_handle="vol-001" 拓扑关联说明 1. 租户 → Namespace 标签 2. PVC → PV 绑定 3. PV → CSI VolumeHandle 4. CSI 后端容量指标

4.5 Prometheus 采集配置

在 Prometheus 中配置两个采集目标,分别抓取 KSM 与 csi-metrics 指标:

scrape_configs:
  # kube-state-metrics 采集
  - job_name: 'kube-state-metrics'
    kubernetes_sd_configs:
      - role: endpoints
        namespaces:
          names: ['kube-system']
    relabel_configs:
      - source_labels: [__meta_kubernetes_service_name]
        regex: kube-state-metrics
        action: keep
      - source_labels: [__meta_kubernetes_endpoint_port_name]
        regex: http-metrics
        action: keep
    metric_relabel_configs:
      - source_labels: [__name__]
        regex: 'kube_(persistentvolumeclaim|persistentvolume|storageclass|namespace).*'
        action: keep

  # csi-metrics 采集
  - job_name: 'csi-metrics'
    kubernetes_sd_configs:
      - role: pod
        namespaces:
          names: ['csi-driver']
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        regex: csi-external-provisioner
        action: keep
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
        regex: '9808'
        action: keep
    metric_relabel_configs:
      - source_labels: [__name__]
        regex: 'csi_(volume|snapshot|node).*'
        action: keep

4.6 拓扑验证查询

采集完成后,通过 PromQL 验证拓扑关联是否成功:

# 查询租户 A 的所有 PVC 及其绑定的 PV 容量
kube_persistentvolumeclaim_info{namespace="ns-tenant-a"}
  * on(volume_name) group_left(storage_class)
kube_persistentvolume_info
  * on(volume_name) group_left()
kube_persistentvolume_capacity_bytes

# 查询租户 A 的 CSI 卷实际容量
kube_persistentvolume_info{volume_handle=~".*"}
  * on(volume_handle) group_left()
csi_volume_capacity_bytes
关键检查点:如果上述查询返回空结果,请依次排查:① KSM 是否暴露了存储指标;② csi-metrics 端口是否可达;③ volume_handle 标签是否在 PV 对象中正确设置;④ Prometheus relabel 规则是否过滤掉了必要标签。

至此,Kubernetes 存储组件拓扑图构建完成。下一阶段将基于此拓扑图,实现租户存储配额的自动校准与差异分析。