一、先把问题说清楚:为什么 Kubeflow 要单独做一套监控
机器学习的平台跑起来之后,大家关心什么?关心模型训练有没有挂,关心推理接口是不是变慢了,关心 GPU 有没有被白白占用,关心半夜有没有报警。这些问题落到 Kubeflow 上,就绕不开它的两大核心部分:Pipeline(流水线)和推理服务(InferenceService)。前者管的是训练任务怎么编排,后者管的是模型上线后怎么对外提供预测。两者跑在不同的组件上、生成不同类型的日志和指标,所以监控策略也必须分开考虑。
从实用角度出发,最常用的配套方案是 Prometheus 加 Grafana。Prometheus 负责拉取和存储指标,Grafana 负责把指标画成图表。我们下面所有示例都以这套组合为基础。我们会先解决“指标从哪里来”的问题,然后一步一步把采集链路打通,最后告诉你哪些地方容易踩坑。整个过程我会尽量用买菜做饭的大白话来讲,保证你跟着操作一遍,就能在自己环境里跑起来。
二、先认识 Prometheus:采集指标的基本姿势
Prometheus 的工作方式像一个小区物业巡检:它定期到各个“监控点”去敲门,问一句“你这边有什么指标要报告吗?”。每个“监控点”只要按照约定格式提供一个 HTTP 接口,把指标文本返回出来就行。不需要你主动上报,一切靠 Prometheus 拉取(Pull)。
这种拉取模式最大的好处是省心。只要你的服务能访问到,Prometheus 就能定期去采集。万一某个服务临时挂了,Prometheus 按重试机制隔一段时间再去拉一次,服务恢复了数据又会自动接上。
2.1 四类我们最常用的指标模型
在动手写代码之前,先认识一下最常用的四种指标类型。这四种你搞明白了,后面看任何配置都不会觉得晕。
Counter(计数器):只增不减,比如累计请求数。它是累计值,用来看趋势用的。比如“今天到现在一共调用了多少次推理接口”,这个数字只会变大,不会变小。
Gauge(仪表盘):可增可减,比如当前内存占用、当前活跃连接数。它反映的是某一时刻的状态。
Histogram(直方图):把数据分桶统计,适合看耗时分布。比如“推理耗时在 50 毫秒以内的有多少次,在 100 毫秒以内的有多少次”,它能画出类似“大多数请求都很快,少数请求很慢”的图像。我们通常用它来做 P99 百分位的计算。
Summary(摘要):和直方图类似,但更节省资源。理解起来就用前三种就够日常用了。
2.2 先写一个最简单的指标出口
为了让你更直观地理解,我们做个最简单的演示。用一个 Python 写的 HTTP 服务,暴露一个指标接口。这个示例不依赖 Kubeflow,纯粹为了让你知道“被 Prometheus 采集的服务长什么样”。
# 技术栈:Python 3.9 + prometheus_client
from prometheus_client import start_http_server, Counter, Histogram, Gauge
import random
import time
import threading
# 定义一个计数器,名字叫 http_requests_total,帮忙统计接口被调了多少次
REQUEST_COUNT = Counter(
'http_requests_total',
'总共接收到的请求数量',
['method'] # 用 method 标签区分是 GET 还是 POST
)
# 定义一个直方图,用来统计处理耗时
REQUEST_DURATION = Histogram(
'http_request_duration_seconds',
'接口处理耗时,单位秒',
['path'] # 用 path 标签区分不同的路径
)
# 定义一个仪表盘,用来表示当前排队中的任务数量
QUEUE_SIZE = Gauge(
'http_queue_size',
'当前排队中的任务数量'
)
def process_request():
# 模拟一个耗时操作,费时 0.1 到 0.5 秒
time.sleep(random.uniform(0.1, 0.5))
def run_server():
# 启动一个 HTTP 服务,监听 8000 端口
# 这个服务会自动提供一个 /metrics 路径供 Prometheus 拉取
start_http_server(8000)
print("指标接口已经启动,请访问 http://localhost:8000/metrics 查看结果")
def simulate_requests():
# 循环模拟产生请求数据
while True:
# 每次循环先标记一个请求到来
REQUEST_COUNT.labels(method='POST').inc()
# 更新当前队列大小,+1 表示多了一个任务在排队
QUEUE_SIZE.inc()
path = '/v1/predict'
start_time = time.time()
# 执行模拟任务
process_request()
# 记录本次处理的耗时
REQUEST_DURATION.labels(path=path).observe(time.time() - start_time)
# 排队人数减一
QUEUE_SIZE.dec()
time.sleep(1)
if __name__ == '__main__':
# 先启动服务
run_server()
# 再在另一个线程里模拟请求
t = threading.Thread(target=simulate_requests, daemon=True)
t.start()
# 主线程保持运行
while True:
time.sleep(60)
运行上面这段代码后,在浏览器里打开 http://localhost:8000/metrics,你会看到一堆以 # HELP 和 # TYPE 开头的文本。这就是 Prometheus 能读懂的指标格式。关键部分长这样:
# HELP http_requests_total 总共接收到的请求数量
# TYPE http_requests_total counter
http_requests_total{method="POST"} 12.0
这个输出代表:method 为 POST 的请求一共 12 次。Prometheus 拉到这个数据后,会把这个值存储下来,并记录一个时间戳。后面查询的时候,你就能看到一条随时间上涨的折线。
这段代码你不用完全背下来,只要理解一件事:每个被监控的服务,需要自己提供一个 /metrics 接口,里面是文本格式的键值对。
三、Pipeline 指标怎么采集:从零到一的全过程
Pipeline 在 Kubeflow 里主要负责编排多个步骤。你定义好第一步做什么、第二步做什么,平台会帮你调度起来。我们关心的是每一个步骤有没有成功、耗时多久、在哪一步卡住了。通常在这个环节,我们需要监控三类东西:Kubeflow Pipeline 自身的服务状态、Argo Workflow 的任务状态、每一步 Pod 的资源消耗。
3.1 先安装一个轻量 Prometheus 用来做实验
在正式环境里,你可能已经有现成的 Prometheus 集群了。这里我们先在 Kubernetes 里用最简单的方式安装一个测试版,看看数据长什么样,再考虑怎么接入生产。
# 技术栈:Helm 3 + kube-prometheus-stack
# 第一步:添加 prometheus-community 仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
# 第二步:更新仓库索引
helm repo update
# 第三步:在 monitoring 命名空间安装完整监控栈
# 其中包含 Prometheus、Grafana、AlertManager
helm install kube-prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set grafana.enabled=true
等安装完成,我们验证一下 Prometheus 是否正常启动:
# 查看安装出来的 Pod 情况
kubectl -n monitoring get pod
# 输出大致长这样:
# NAME READY STATUS RESTARTS AGE
# kube-prometheus-grafana-xxxxx 2/2 Running 0 5m
# kube-prometheus-prometheus-xxxxx 2/2 Running 0 5m
# kube-prometheus-operator-xxxxx 1/1 Running 0 5m
到这里,一套完整的监控体系已经搭起来了。只不过现在它还只会收集 Kubernetes 集群本身的指标,比如 CPU、内存、网络。我们接下来要做的是把 Kubeflow 的指标也送进去。
3.2 找到 Pipeline 组件的指标入口
Kubeflow Pipeline 系统主要包含几个部分:Pipeline API Server、Argo Workflow Controller、每个训练任务额外地拉起的 Pod。这几个组件里,Argo Workflow 本身就自带了 Prometheus 指标支持,不需要你写代码,它就会暴露一些基础数据。
我们来看看 Argo Workflow Controller 暴露了哪些指标。用端口转发的方式,先把它服务端的 metrics 接口映射出来。
# 技术栈:kubectl 命令
# 先找到 argo-workflows 所在的命名空间
# 一般 Kubeflow 会把相关组件放在 kubeflow 命名空间
# 查看 kubeflow 命名空间下有哪些服务
kubectl -n kubeflow get svc | grep workflow
# 把 argo-server 的 2746 端口映射到本地 8080
kubectl -n kubeflow port-forward svc/argo-server 8080:2746
然后访问 http://localhost:8080/metrics,你就能看到 Argo 自己的指标。其中有几个比较关键的:
argo_workflows_count{status="Running"} 2
argo_workflows_count{status="Error"} 0
argo_workflow_tasks_count{phase="Succeeded"} 15
argo_workflow_tasks_count{phase="Failed"} 1
看到这些指标后,我们的目标就是让 Prometheus 自动采集它们。
3.3 让 Prometheus 自动发现这些指标端点
Prometheus 在 Kubernetes 里采集服务指标,靠的是 Kubernetes 服务发现机制。你不用在每个配置里写死 IP 地址,只要给服务打上对应的标签(annotations),Prometheus 会自动找到它。
下面这段配置解释一下如何给 argo-server 打上采集标签。我们会创建一个 YAML 文件,然后应用它。
# 技术栈:Kubernetes Service 注解配置
apiVersion: v1
kind: Service
metadata:
name: argo-server
namespace: kubeflow
# annotations 是 Prometheus 自动发现的关键部分
annotations:
# 打开采集开关,Prometheus 会来这里拉数据
prometheus.io/scrape: "true"
# 采集路径,默认是 /metrics
prometheus.io/path: "/metrics"
# 端口号,必须和 service 暴露的端口号一致
prometheus.io/port: "2746"
spec:
selector:
app: argo-server
ports:
- name: metrics
port: 2746
targetPort: 2746
不过这里有个细节:标准的 Service 端口 2746 是 HTTPS 端口,不是纯 HTTP。如果你的 argo-server 启用的是 TLS 加密传输,你还需要在 Prometheus 配置里关闭证书校验。不然 Prometheus 拉取时会报证书错误。
3.4 更常见的是采集每一个 Pipeline 步骤的 Pod 指标
Pipeline 任务跑起来以后,每一个步骤就是一个 Kubernetes Pod。这个 Pod 可能执行的是 Python 训练脚本,也可能是一个数据清洗逻辑。大多数情况下,这种训练脚本内部是不会自己暴露指标的。那怎么办?最实用的办法是通过 Kubernetes 自带的资源监控,用 kube-state-metrics 来获取每个 Pod 的 CPU、内存、重启次数。这些指标已经在 kube-prometheus-stack 里默认安装好了,不需要你做任何额外配置。
你可以先通过下面的命令直观感受一下这些指标:
# 技术栈:kubectl + PromQL 概念演示
# 先查看当前有哪些正在运行的 Pipeline Pod
kubectl -n kubeflow get pod | grep pipeline
# 假设你看到了一个名为 ml-pipeline-xxx 的 Pod
# 在 Prometheus 的查询界面里,你可以输入以下表达式来观察它的 CPU 使用情况
# 这里的 container_cpu_usage_seconds_total 是 kubelet 自己采集的指标
#
# rate(container_cpu_usage_seconds_total{namespace="kubeflow", pod=~"ml-pipeline.*"}[5m])
你会发现,因为我们装的是完整监控栈,刚开始就已经能实时看到每个 Pod 的 CPU 和内存了。这比我们自定义的指标还早一步到位。所以在做 Pipeline 监控时,我给你的第一个建议是:先把 Pod 级别的东西都看一遍,包括状态、重启次数、资源占用。这些数据不用写任何代码就能拿到。
3.5 在训练脚本里埋入自定义指标
上面这些还不够。真实的业务场景里,我们想知道的往往是更偏业务层的数据,例如:
- 每一轮训练的 loss 变化到多少了。
- 训练集和验证集准确率差了多少。
- 某一批数据有多少条被过滤掉了。
这时就需要你自己在代码里埋点。这里我们继续使用 Python 技术栈,展示如何在训练脚本中暴露自定义指标,然后让 Prometheus 从训练容器中采集它。
# 技术栈:Python 3.9 + pytorch + prometheus_client
# 这段代码主要展示训练脚本里怎么暴露指标,
# 并不负责完整训练,只引出思路
from prometheus_client import start_http_server, Gauge, Counter, Summary
import torch
import time
# 训练损失,用 Gauge 类型,因为每一轮的值都在变化,可以上下跳动
TRAIN_LOSS = Gauge('train_loss', '当前训练损失值')
# 训练准确率,同样是 Gauge
TRAIN_ACCURACY = Gauge('train_accuracy', '当前训练准确率')
# 已经完成的训练轮数,用 Counter,只会往上涨
EPOCH_COUNT = Counter('train_epoch_total', '已经完成的总训练轮数')
def train_one_epoch(model, data_loader):
# 这里省略真实的训练代码
# 我们用休眠模拟一下训练耗时
time.sleep(3)
# 模拟返回这一轮的 loss 和 accuracy
return 0.35, 0.86
def start_metrics_server():
# 在 8001 端口暴露指标接口
start_http_server(8001)
print('训练指标接口已启动在 8001 端口')
def main():
# 先启动指标上报服务
start_metrics_server()
# 模拟初始化模型
model = torch.nn.Linear(10, 2)
# 模拟训练 10 个 epoch
for epoch in range(10):
loss, acc = train_one_epoch(model, None)
# 把指标更新到最新值
TRAIN_LOSS.set(loss)
TRAIN_ACCURACY.set(acc)
# 训练轮数加 1
EPOCH_COUNT.inc()
# 打印出来给日志看
print(f"epoch {epoch + 1} loss={loss:.4f} acc={acc:.4f}")
# 为了让 Prometheus 有时间去拉取,每个 epoch 之间停一下
# 实际项目中不需要刻意等待,这里是为了演示方便
time.sleep(10)
if __name__ == '__main__':
main()
在运行这个脚本之前,需要在同一个容器里启动两个进程:一个是训练主进程,另一个是指标暴露服务。上面的示例里把指标启动写在了主函数内,实际你就可以直接这样用。
然后,你在 Kubernetes 中部署这个训练任务时,用下面这种 Pod 配置来写资源清单:
# 技术栈:Kubernetes Pod YAML 配置
apiVersion: v1
kind: Pod
metadata:
name: training-job-001
namespace: kubeflow
# 这里的关键标签,让 Prometheus 发现这个 Pod 的指标接口
annotations:
prometheus.io/scrape: "true"
prometheus.io/path: "/metrics"
prometheus.io/port: "8001"
spec:
containers:
- name: trainer
image: your-registry/trainer:latest
ports:
- name: metrics
containerPort: 8001
# 这里省略了具体的训练命令和参数
# 实际运行时,请用你自己的镜像命令
保存为 training-pod.yaml 以后执行:
# 部署这个训练任务
kubectl apply -f training-pod.yaml
这样 Prometheus 就会自动去 8001 端口拉取训练指标了。之后你在 Grafana 图表里输入 train_loss,就能看到一条随训练时间变化的折线。训练结束 Pod 消失,数据链路也会自动切断,不会对系统造成任何负担。
四、推理服务指标怎么采集:模型上线之后的另一场硬仗
Pipeline 监控解决的是训练阶段的问题。模型训练完成,我们还要把模型部署成在线服务,对外提供实时推理能力。这一环节更贴近我们的直接感受,也很容易出问题。
在 Kubeflow 生态中,最常用的推理服务组件是 KServe。KServe 部署出来的每个模型服务都自带 /v2/metrics 接口。这意味着你不需要改造模型代码,就能拿到标准的监控指标。
4.1 KServe 默认提供的指标有什么用
KServe 默认基于 FastAPI 的推理服务器会暴露这些指标:
# HELP model_request_count 模型请求次数
# TYPE model_request_count counter
model_request_count{model_name="mymodel",version="v1"} 100
# HELP model_request_duration_seconds 请求耗时
# TYPE model_request_duration_seconds histogram
model_request_duration_seconds_bucket{model_name="mymodel",le="0.1"} 10
model_request_duration_seconds_bucket{model_name="mymodel",le="0.5"} 50
model_request_duration_seconds_bucket{model_name="mymodel",le="1"} 80
model_request_duration_seconds_sum{model_name="mymodel"} 67.5
model_request_duration_seconds_count{model_name="mymodel"} 100
这些指标能帮你回答几个很重要的问题:
- 当前模型服务每秒能响应多少个请求?
- 请求的平均耗时是多少?P99 耗时是多少?
- 有没有因为超出并发限制而导致的错误请求?
我们可以先用一个小脚本模拟对推理服务的请求,同时把 KServe 自带的指标拉出来看看:
# 技术栈:curl 命令
# 先部署一个简单的 KServe 模型服务
# 假设它已经跑在 test 命名空间下面
kubectl -n test get inferenceservice
# 获取到模型服务的访问地址
# 假设服务名为 mymodel
# 先用 curl 查看 KServe 的指标接口健康状态
curl http://localhost:8080/v2/metrics 此处省略实际地址
这个命令里 8080 是默认端口,实际请换成你服务地址中的端口。
4.2 为推理服务配置标准的采集规则
KServe 的推理服务本质上是一组 Kubernetes Service 和 Deployment。和前面采集 Pod 指标的方式不同,为它配置采集需要用 ServiceMonitor。ServiceMonitor 是 Prometheus Operator 提供的一种自定义资源,用来描述“需要监控哪些 Service”。
下面这份 YAML 展示了如何为一个名为 mymodel 的推理服务建立一个 ServiceMonitor。
# 技术栈:Prometheus Operator + ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: kserve-models
# 放在和模型服务同一个命名空间中
namespace: test
spec:
# 选择带有名称为 predictor 的 Service
selector:
matchLabels:
serving.knative.dev/service: mymodel
endpoints:
- port: metrics
# KServe 的标准指标路径
path: /v2/metrics
# 每 15 秒拉取一次
interval: 15s
这里的 selector 可能因你的具体部署方式而不同。在我的实践当中,KServe 创建的 Service 标签往往长这样:
selector:
matchLabels:
serving.kubeflow.org/inferenceservice: mymodel
部署 ServiceMonitor 之后就完成了一大半工作。还需要让 Prometheus 知道它要处理这个 ServiceMonitor。在默认的 kube-prometheus-stack 里,Prometheus 会通过 prometheus.yml 配置文件中的 serviceMonitorSelector 来决定采集哪些 ServiceMonitor。
一般默认配置会采集所有命名空间下带有指定标签的 ServiceMonitor。如下配置最常见的写法:
# 技术栈:Prometheus CRD 配置
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
name: kube-prometheus
namespace: monitoring
spec:
serviceMonitorSelector:
matchLabels:
release: kube-prometheus
这意味着你创建 ServiceMonitor 时,需要在 metadata 里加上对应标签,例如 release: kube-prometheus。所以刚才的 YAML 要改一下:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: kserve-models
namespace: test
# 这个标签必须匹配 Prometheus 的 serviceMonitorSelector 才能被采集
labels:
release: kube-prometheus
spec:
selector:
matchLabels:
serving.kubeflow.org/inferenceservice: mymodel
endpoints:
- port: metrics
path: /v2/metrics
interval: 15s
4.3 用 PromQL 看推理服务的真实状态
有了上面这些指标,接下来就是写 PromQL 查询语句了。这些查询语句在 Grafana 里输入后,就能直接画成图表。
看“每秒请求数”:
sum(rate(model_request_count{namespace="test"}[5m])) by (model_name)
看“P99 耗时”:
histogram_quantile(0.99, sum(rate(model_request_duration_seconds_bucket{namespace="test"}[5m])) by (le, model_name))
看“最近5分钟有多少错误请求”:
sum(increase(model_request_count{namespace="test", code=~"5.*"}[5m])) by (model_name)
这些表达式看起来有点复杂,但只需要记住一个逻辑:rate 是求每秒变化率,histogram_quantile 是计算百分位,increase 是求增量。熟练了以后,你看到别人写的表达式基本都能读个七七八八。
五、告警和看板:让数据替你值夜班
数据采集上来了,最后一步是使用它。对我们操作者来说,比较要紧的是看板和告警。看板相当于驾驶舱显示屏,告警相当于报警铃。两者缺一不可。
5.1 Grafana 看板搭建
安装好 kube-prometheus-stack 时,Grafana 已经自带了很多 Kubernetes 相关的看板。我们再补充一个针对模型推理服务的简单看板配置思路。在 Grafana 里,新建 Panel 的时候选择 Prometheus 数据源,输入 PromQL,选择图表类型,就能出图。
一个比较直观的组合是:
- 用折线图展示模型请求 QPS。
- 用柱状图展示不同返回码的错误次数。
- 用热力图展示耗时分布在一天内的变化。
如果你不想从零开始画,社区也有很多现成的 KServe 看板可以直接导入,在 Grafana 中搜索看板 ID 就可以找到。导入后修改一下数据源,就能看到数据和图表了。
5.2 关键告警规则埋点
告警规则的作用是:“当某个数值超过阈值时,自动发消息给值班人员”。我们通过 PrometheusRule 自定义资源来配置规则:
# 技术栈:Prometheus Operator + PrometheusRule
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: kserve-model-alerts
namespace: test
labels:
release: kube-prometheus
spec:
groups:
- name: kserve-inference
rules:
# 当模型推理接口 5 分钟内错误率超过 5% 时触发告警
- alert: HighErrorRate
expr: |
sum(rate(model_request_count{namespace="test", code=~"5.*"}[5m]))
/
sum(rate(model_request_count{namespace="test"}[5m])) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "模型推理错误率超过 5%"
description: "当前错误率已超过阈值,请及时检查模型版本或资源状态。"
# 当 P99 耗时超过 2 秒时触发告警
- alert: HighLatency
expr: |
histogram_quantile(0.99, sum(rate(model_request_duration_seconds_bucket{namespace="test"}[5m])) by (le)) > 2
for: 3m
labels:
severity: critical
annotations:
summary: "模型推理P99耗时超过2秒"
description: "用户感知到明显的响应变慢,建议扩容或优化模型。"
应用这个文件:
kubectl apply -f kserve-alerts.yaml
这样,当线上模型出现大面积错误或明显变慢时,你就会收到告警通知。告警消息可以通过 AlertManager 发到钉钉、企业微信、邮件或者 Slack,这里就不展开讲了。
六、常见坑和调优经验
讲了这么多完整流程,最后聊几个容易踩的坑,帮你少走一些弯路。
6.1 不要重复采集同一个指标
Kubeflow 整个链路中有很多替身组件,比如 Pipeline 本身会暴露指标,Argo 也会暴露指标,Pod 级别的资源采集还在重复工作。如果你不加选择地把所有 Service 都加上 prometheus.io/scrape 注解,那么 Prometheus 会收到大量重复数据,导致存储膨胀,查询变慢。一个比较合理的做法是:Pipeline 阶段以 Pod 资源指标做基础,只在训练脚本内部暴露业务指标;推理阶段用 KServe 自带指标 + 少量自定义指标。
6.2 注意“指标爆炸”的问题
Prometheus 的存储压力很大一部分来自标签基数(cardinality)。如果你在代码里为每个用户ID、每个项目名都设置一个标签,那么标签组合会呈指数级增长。举个例子,一个 Counter 定义了 user_id 标签,有 1 万个用户,那么这个指标在 Prometheus 里就有 1 万个时间序列。在 Kubeflow 场景中,模型名和版本号是合适的标签,但请求里的用户 ID 就千万不要做标签。
6.3 训练脚本的指标接口要设置超时
训练任务通常只在集群空闲时段运行。如果脚本里启动了一个永不退出的指标服务,那么在任务结束时可能会出现资源泄漏。在代码中要给指标服务器加一个关闭机制。比如在训练完成后,显式调用一下 shutdown 函数,或者依靠 Pod 的生命周期自动回收。因为训练容器结束的时候,所有进程都会被杀掉,所以实际影响不大,但如果你的训练任务长期驻留,这个点就需要特别注意。
6.4 使用端口转发做临时排查
生产环境不建议频繁修改 Service 配置。当你想临时测试某个指标接口是否可用时,使用 kubectl port-forward 是最快速的直连方式。等你确认接口正常后,再通过 ServiceMonitor 或注解方式接入正式的采集链路。这样可以避免测试痕迹污染线上配置。
七、优缺点分析和适用场景
聊到这里,我们把整套方案再理性地盘点一下。不要以为用了 Prometheus 就一劳永逸,它也有优点也有缺点。
7.1 优点
这套方案的优点是极其明显。第一,它完全开源,不需要额外购买商业监控软件。第二,它与 Kubernetes 和 Kubeflow 原生结合,很多组件天生就暴露了指标,不需要从头开发。第三,告警和可视化一体化,从数据采集到通知报警的链路很简单,能在短时间内搭建完成。第四,社区非常庞大,遇到的问题大概率都能在网上找到参考方案。
7.2 缺点
缺点也不能回避。第一,Prometheus 的存储是单机阻塞式的,如果不使用 Thanos 或者 VictoriaMetrics 做长期存储,历史数据保存时间很有限。第二,指标采集是拉模式,如果某些推理服务在离线环境或网络隔离的网络中,Prometheus 访问不到服务地址,就采集不了数据。第三,学习曲线相对陡峭,尤其是 PromQL 对新手不太友好。第四,在一些超大规模集群下,指标数量太多会拖垮监控系统自身的性能,对运维能力有一定要求。
7.3 适合用在哪些场景
这套方案特别适合以下几类场景。第一批是内部使用的机器学习平台,团队规模中等,希望能快速看到训练和推理两个阶段的核心状态。第二批是已经在用 Kubeflow 进行全套 ML 流程管理的组织,避免使用过多零散工具增加维护成本。第三批是研究和实验性质的项目,对指标存储周期要求不高,更注重实时观察和快速发现问题。
八、最后的总结
监控体系这件事,不需要做得多么花哨,关键是抓大放小。拿 Kubeflow 来说,只要你把 Pipeline 的任务状态、Pod 资源用量、推理服务的请求量、耗时和错误率放在一块看板上,90% 的日常问题都能一览无余。剩下的细节再靠日志系统去追查。
我们在文章中从 Prometheus 的基础讲起,演示了自定义指标接口的写法,串联了 Pipeline 的采集流程和 KServe 推理服务的采集方式,还配置了告警规则。这一套走通之后,再遇到模型推理变慢、训练任务失败这类问题,你就不会只是干瞪眼等日志了。打开 Grafana,一眼就能定位到是资源不够、代码卡住还是模型包版本有问题。
所有示例你都可以直接复制到自己的环境里跑一下。把你训练任务里的核心指标先暴露出来,部署一个推理服务,拉出它自带的状态指标,然后画一张属于你自己的面板,感受一下手上有数据的踏实感。多试几轮,就会越来越熟练。
评论
围绕“Kubeflow监控体系构建:利用Prometheus采集Pipeline与推理指标的最佳姿势”参与讨论