DCGM 介绍

DCGM(Data Center GPU Manager)即数据中心GPU管理器,是一套用于在集群环境中管理和监视Tesla™GPU的工具。它包括主动健康监控,全面诊断,系统警报以及包括电源和时钟管理在内的治理策略。它可以由系统管理员独立使用,并且可以轻松地集成到NVIDIA合作伙伴的集群管理,资源调度和监视产品中。DCGM简化了数据中心中的GPU管理,提高了资源可靠性和正常运行时间,自动化了管理任务,并有助于提高整体基础架构效率。

Kubernetes 集群中的每个 pod GPU 指标

dcgm-exporter收集节点上所有可用 GPUs 的指标。然而,在 Kubernetes 中,当一个 pod 请求 GPU 资源时,你不一定知道节点中的哪个 GPUs 将被分配给一个 pod 。从 v1.13 开始,kubelet 添加了一个设备监视功能,可以使用 pod 资源套接字找到分配给 pod—的 pod 名称、 pod 名称空间和设备 ID 的设备。
dcgm-exporter中的 http 服务器连接到 kubelet pod resources 服务器(/var/lib/kubelet/pod-resources),以标识在 pod 上运行的 GPU 设备,并将 GPU 设备 pod 信息附加到收集的度量中。

基于K8S使用DCGM和Prometheus监控GPU

DCGM工具部署

项目地址:DCGM-Exporter

GPU采集指标

dcgm-exporter采集指标项以及含义:

基于K8S使用DCGM和Prometheus监控GPU

节点标签

我们这里使用DaemonSet这种方式部署,所以我们优先将GPU节点服务器打上标签,方便我们后期部署与维护。

# 节点设置 Label 标签
kubectl label nodes fsyy nvidia-gpu=monitoring
# 查看节点是否设置 Label 成功
kubectl get nodes --show-labels
# 删除标签
kubectl label nodes fsyy nvidia-gpu-

k8s上部署

# 部署 default-counters.csv 配置文件
kubectl apply -f dcgm-metrics.yaml
# 部署dcgm工具
kubuctl apply -f dcgm-exporter.yaml

上面服务部署在monitoring命名空间下,查看各资源状态:

# 查看service和pod
kubectl get svc,pod -n monitoring -l app.kubernetes.io/name=dcgm-exporter

查看gpu监控指标收集情况:

# 本地端口转换
kubectl -n monitoring port-forward service/dcgm-exporter 9400
# 获取gpu监控指标
curl 127.0.0.1:9400/metrics

对接prometheus

当上述资源创建完成后,在集群内部的prometheus-server中就可以找到对应的target,确认状态为up即表示prometheus已正常采集集群外gpu的metrics数据了,接下来数据就会以10s为间隔,源源不断的将数据采集到prometheus存储中。
我这边的prometheus使用的是自动发现服务配置,结果如下:

基于K8S使用DCGM和Prometheus监控GPU

Grafana的监控展示

我们可以使用grafana dashboard官网上的模版,我们这里使用12639,需要根据实际情况修改下变量:

基于K8S使用DCGM和Prometheus监控GPU

正确导入和修改变量后,最终的GPU监控图:

基于K8S使用DCGM和Prometheus监控GPU

这里有个问题,grafana上gpu_host的 IP 地址并不是真实的node IP或node name,gpu_host的值其实是dcgm-exporter-xxxxpod的ip,可以使用如下命令查看:

kubectl get pod -n monitoring -o wide

上述问题会造成开发同学获取节点gpu监控信息不是那么直接,他们可能没有查看pod详细信息的权限,过多依赖运维同学,导致工作效率不高。

对于上面的需求,我们只需将“pod ip”更改为“node ip”即可解决上述问题。在动手之前,我们需要了解以下几点信息:

ServiceMonitor配置

在本节“对接prometheus”中,我使用自动服务发现来接入的gpu指标,现在我们需要对标签重写,现在我们来定义一个ServiceMonitor的yaml文件。

# 现将自动发现标签去掉
kubectl edit svc dcgm-exporter -n monitoring
# cat service-monitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: "dcgm-exporter"
  namespace: monitoring
  labels:
    app.kubernetes.io/name: "dcgm-exporter"
    app.kubernetes.io/version: "2.4.0"
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: "dcgm-exporter"
      app.kubernetes.io/version: "2.4.0"
  endpoints:
  - port: "metrics"
    path: "/metrics"
    relabelings:
    - action: replace
      sourceLabels:  [__meta_kubernetes_endpoint_node_name]
      targetLabel: node_name
# 部署ServiceMonitor
kubectl apply -f service-monitor.yaml

然后,登录prometheus-->targets即可查看到serviceMonitor/monitoring/dcgm-exporter/0 (7/7 up)这类信息。

prometheus标签重写

当prometheus加载target实例后,会存在一些默认的标签。我们将鼠标放在标签上面就会显示出来,这些标签都会帮助我们去声明prometheus该如何从target实例中获取指标。

常见系统内置标签

__address__              #当前Target实例的访问地址<host>:<port>
__scheme__               #采集目标服务访问地址的HTTP Scheme,HTTP或者HTTPS
__metrics_path__         #采集目标服务访问地址的访问路径
__param_<name>           #采集任务目标服务的中包含的请求参数

一般来说,targets中以""作为前置的是系统内置标签,这些标签是不会写入到指标数据中的。不过也会有一些例外,比如我们前面得知prometheus采集的数据中都包含了instance的标签,这些标签的内容对应到target实例中的address__的标签,这里实际上是做了一次标签的重写操作。

自定义标签

- job_name: 'node'
  static_configs:
    - targets: ['192.168.1.21:9100'] 
      labels:                    #添加标签
        env: test1-cluster
        __hostname__: localhost

注意:带__前缀的标签是不会出现在指标显示中的。

配置grafana看板

当了解了上面标签重写处理过程,我们重新配置下当前看板下的变量,根据自己实际情况进行调整,最终效果如下:

基于K8S使用DCGM和Prometheus监控GPU

GPU报警

这里放个例子,大家参考下:

# 添加如下规则到prometheus rule文件
name: GPU内存利用率(%)
expr: DCGM_FI_DEV_MEM_COPY_UTIL{kubernetes_namespace="monitoring"} > 80
labels:
  severity: 警告
annotations:
  description: “namespace:{{$labels.namespace}}的pod:{{$labels.pod}},当前GPU内存利用率过高。”
  identifier: {{ $labels.hostname }}
  summary: GPU内存利用率超过80%

登陆prometheusAlerts查看新建的报警规则:

基于K8S使用DCGM和Prometheus监控GPU

参考文档