4、Kubeflow监控指标采集:Prometheus架构与部署、Kubeflow组件指标暴露、自定义指标采集

监控这件事,说白了就是给系统装个“心电图”。没有它,你根本不知道集群里正在发生什么。我在做 Kubeflow 运维时,最怕的就是半夜被叫醒,说模型训练突然挂了,但日志全被冲掉了。后来我学乖了——先把 Prometheus 架起来,让指标说话。

这一章,我们就聊聊怎么用 Prometheus 把 Kubeflow 的监控指标抓到手。我会从架构讲起,再带你看看 Kubeflow 各组件怎么暴露指标,最后说说自定义指标怎么采集。

4.1 Prometheus 架构与部署

Prometheus 的架构其实不复杂。核心就三块:抓取(Scrape)存储(Store)告警(Alert)。它主动去拉目标服务的指标,而不是等别人推过来。这个设计我个人很喜欢——你想想看,如果每个服务都主动推数据,那网络一堵,数据就全丢了。

核心架构图:

Prometheus 监控架构 Prometheus Server 抓取 / 存储 / 查询 Kubeflow 组件 (Pipelines / Katib / Kserve) Kubernetes 集群 (Node / Pod / 容器指标) 自定义应用 (业务指标 / 模型指标) Alertmanager 告警 Grafana 可视化

部署 Prometheus 到 Kubeflow 环境,我推荐用 kube-prometheus-stack 这个 Helm Chart。它把 Prometheus、Alertmanager、Grafana 打包在一起,省心不少。直接上命令:

# 添加 Helm 仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# 安装 kube-prometheus-stack
helm install prometheus prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace \
  --set grafana.enabled=true \
  --set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false

这里有个坑,我踩过。那个 serviceMonitorSelectorNilUsesHelmValues=false 参数,如果不加,Prometheus 默认只抓取带有特定 Helm 标签的 ServiceMonitor。你自定义的 ServiceMonitor 就抓不到了。嗯,这个细节很容易被忽略。

小技巧:部署完成后,用 kubectl get pods -n monitoring 确认所有 Pod 都 Running。然后通过 kubectl port-forward -n monitoring svc/prometheus-kube-prometheus-prometheus 9090:9090 就能在本地访问 Prometheus UI 了。

4.2 Kubeflow 组件指标暴露

Kubeflow 的各个组件,其实大部分都原生支持 Prometheus 指标。但暴露方式不太一样,我一个个说。

4.2.1 Kubeflow Pipelines 指标

Pipelines 的指标主要集中在 ML Pipeline ServiceArgo Workflows 上。我记得第一次部署时,发现 Pipeline 的指标没出来,查了半天才发现是 ServiceMonitor 没配。

Kubeflow Pipelines 默认会在 /metrics 端点暴露指标。你只需要创建一个 ServiceMonitor 告诉 Prometheus 去抓取:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: ml-pipeline-monitor
  namespace: kubeflow
  labels:
    release: prometheus  # 这个标签要和 Prometheus 的配置匹配
spec:
  selector:
    matchLabels:
      app: ml-pipeline
  endpoints:
  - port: http
    path: /metrics
    interval: 15s

应用之后,去 Prometheus UI 的 Targets 页面看看,如果显示 UP,就说明抓取成功了。

4.2.2 Katib 指标

Katib 是超参调优组件。它的指标暴露方式有点特殊——每个实验(Experiment)会启动多个 Trial Job,每个 Trial 都会暴露自己的指标。我个人习惯在 Katib 的 Suggest 服务 上采集全局指标,比如实验状态、建议次数等。

Katib 的 Suggest 服务默认监听 6789 端口,指标路径是 /metrics。配置 ServiceMonitor 时注意端口名:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: katib-monitor
  namespace: kubeflow
spec:
  selector:
    matchLabels:
      app: katib
  endpoints:
  - port: metrics
    interval: 30s

注意:Katib 的 Trial Job 是临时 Pod,跑完就删。如果你想采集每个 Trial 的详细指标,建议用 Prometheus 的 Pushgateway 模式,让 Trial 在结束时把指标推过去。我曾经因为没处理这个,导致一批实验的指标全丢了,教训深刻。

4.2.3 Kserve 指标

Kserve(原 KFServing)负责模型推理。它的指标很关键——直接影响线上服务的稳定性。Kserve 的 InferenceService 会暴露 /metrics 端点,包含请求延迟、吞吐量、错误率等。

Kserve 默认集成了 Prometheus 指标,你只需要在 InferenceService 的 YAML 里开启:

apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: my-model
spec:
  predictor:
    serviceAccountName: sa
    model:
      modelFormat:
        name: sklearn
      storageUri: gs://my-bucket/model
    # 开启指标暴露
    metrics:
      enabled: true
    # 自定义端口
    ports:
    - containerPort: 8080
      name: http
      protocol: TCP

然后创建对应的 ServiceMonitor,端口名用 http,路径 /metrics。这样 Prometheus 就能抓到推理服务的实时指标了。

4.3 自定义指标采集

除了组件自带的指标,很多时候我们需要采集业务层面的自定义指标。比如模型训练的 loss 曲线、数据预处理的速度、甚至某个 API 的调用次数。

自定义指标采集,我一般用两种方式:

  • 方式一:在应用代码里直接暴露 /metrics 端点,用 Prometheus 客户端库(如 Python 的 prometheus_client)注册自定义指标。
  • 方式二:用 Prometheus 的 Pushgateway,适合短生命周期任务(比如批处理、定时任务)。

举个例子,假设你在训练脚本里想记录每个 epoch 的 loss:

from prometheus_client import start_http_server, Gauge
import time

# 定义指标
loss_gauge = Gauge('training_loss', 'Current training loss', ['epoch'])

def train():
    for epoch in range(10):
        loss = compute_loss()  # 你的训练逻辑
        loss_gauge.labels(epoch=str(epoch)).set(loss)
        time.sleep(1)

if __name__ == '__main__':
    # 启动 HTTP 服务暴露指标
    start_http_server(8000)
    train()

然后给这个 Pod 配一个 Service 和 ServiceMonitor,Prometheus 就能抓到了。说白了,就是让 Prometheus 知道你的 Pod 在哪、端口多少、路径是什么。

避坑指南:我曾经在自定义指标里用了太多 Label(标签),导致 Prometheus 内存暴涨。Label 的基数(Cardinality)一定要控制好,别超过几千。否则 Prometheus 会变得很慢,甚至 OOM。记住:Label 是用来区分维度的,不是用来存数据的。

4.4 指标采集的常见问题

最后,我总结几个实际运维中容易踩的坑:

问题 原因 解决方法
Targets 显示 DOWN ServiceMonitor 的 Label 不匹配 检查 Prometheus 的 serviceMonitorSelector 配置,确保 Label 一致
指标数据为空 路径或端口配置错误 kubectl port-forward 手动访问 /metrics 端点验证
Prometheus 内存高 指标基数过大 减少 Label 数量,或使用 relabel_configs 过滤不必要的指标
短任务指标丢失 Pod 生命周期太短 改用 Pushgateway,或使用 Prometheus Operator 的 PodMonitor

嗯,这一章的内容就这些。监控指标采集是 Kubeflow 运维的基石,把 Prometheus 架好,后面做告警和可视化就顺了。你想想看,没有数据,再好的 Dashboard 也是白搭。


公众号:蓝海资料掘金营,微信deep3321