前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DCGM:监控Kubernetes集群的GPU资源

DCGM:监控Kubernetes集群的GPU资源

作者头像
zouyee
发布2021-03-23 16:39:35
3.6K0
发布2021-03-23 16:39:35
举报
文章被收录于专栏:Kubernetes GOKubernetes GO

友情提示:全文3090多文字,预计阅读时间5分钟

摘要

<Kubelet从入门到放弃>系列将对Kubelet组件由基础知识到源码进行深入梳理。因上篇文章Kubelet从入门到放弃系列:GPU加持中介绍了Nvidia系列GPU如何加持Kubernetes,我们除了关注GPU资源的使用,也关注GPU资源的管理,因此本文推出 Kubernetes集群中如何监控GPU资源。

上周CNCF:1)微软Dapr项目拟捐献给CNCF 2)Flux项目进入孵化阶段

一、背景说明

1.1 需求说明

对于SRE团队来说,实现监控AI、高性能计算平台上大规模GPU资源,至关重要。SRE团队可以通过GPU指标了解工作负载等相关性能,从而优化资源分配,提升资源利用率及异常诊断,以提高数据中心资源的整体效能。除了SRE及基础设施团队之外,不管你是从事GPU加速方向的研究人员,还是数据中心架构师,都可以通过相关监控指标,了解GPU利用率和工作饱和度以进行容量规划及任务调度等。

随着AI/ML工作负载的容器化,调度平台采用具备动态扩缩特性的Kubernetes解决方案,针对其监控的急迫性日益提升。在这篇文章中,我们将介绍NVIDIA数据中心GPU管理器(DCGM),以及如何将其集成到Prometheus和Grafana等开源工具中,以实现Kubernetes的GPU监控的整体解决方案。

1.2 NVIDIA DCGM

NVIDIA DCGM是用于管理和监控基于Linux系统的NVIDIA GPU大规模集群的一体化工具。它是一个低开销的工具,提供多种能力,包括主动健康监控、诊断、系统验证、策略、电源和时钟管理、配置管理和审计等。

DCGM提供用于收集GPU遥测的API。特别值得关注的是GPU利用率指标、内存指标和流量指标。DCGM提供了各种语言的客户端,如C和Python。对于与容器生态系统的集成,提供基于DCGM APIs的Go绑定实现。

1.3 NVIDIA exporter

监控系统通常由指标采集器、用于存储指标的时间序列数据库和可视组件组成。例如CNCF毕业项目Prometheus,它和Grafana一起构成监控集成方案。其中Prometheus还包括Alertmanager来创建和管理警报。Prometheus、kube-state-metrics及node_exporter一起部署,以获取Kubernetes API对象的集群指标和CPU利用率等节点指标。下图为Prometheus的示例架构。

在前面介绍的Go API基础上,可以通过DCGM向Prometheus暴露GPU指标。NVIDIA为此构建了dcgm-exporter的项目。

dcgm-exporter 使用 Go 绑定从 DCGM 收集 GPU 遥测数据,然后通过 http 接口 (/metrics) 向 Prometheus 暴露指标。

dcgm-exporter可以通过使用csv格式的配置文件来定制DCGM收集的GPU指标。

1.4 Kubelet设备监控

dcgm-exporter收集了节点上所有可用GPU的指标。然而,在Kubernetes中,当一个节点请求GPU资源时,可能不能确定哪些GPU会被分配给pod。从v1.13开始,Kubelet增加了一个设备监控功能,可以通过pod-resources套接字了解分配给pod的设备,其中包括pod名称、pod命名空间和设备ID。

dcgm-exporter中的http服务连接到kubelet中的pod-resources服务(/var/lib/kubelet/pod-resources)来识别pod上运行的GPU设备,并将GPU设备的pod相关信息添加到收集的指标中。

二、GPU监控

2.1 部署说明

下面是一些设置dcgm-exporter的示例。如果使用NVIDIA GPU Operator,那么dcgm-exporter同样是部署组件之一。

文档中包含了设置Kubernetes集群的步骤。为了简洁起见,假定已经存在一个运行着NVIDIA软件组件的Kubernetes集群,例如,驱动程序、容器运行时和Kubernetes设备插件等。在使用Prometheus Operator部署Prometheus时,还可以方便地部署Grafana。在该篇文章中,为了简单起见,使用了单节点Kubernetes集群。

在设置社区提供的Prometheus Operator的Helm chart时,必须暴露Grafana供外部访问,并且prometheusSpec.serviceMonitorSelectorNilUsesHelmValues必须设置为false。

简单来说,设置监控包括运行以下命令。

代码语言:javascript
复制
$ helm repo add prometheus-community \https://prometheus-community.github.io/helm-charts
$ helm repo update$ helm inspect values prometheus-community/kube-prometheus-stack > /tmp/kube-prometheus-stack.values# Edit /tmp/kube-prometheus-stack.values in your favorite editor# according to the documentation# This exposes the service via NodePort so that Prometheus/Grafana# are accessible outside the cluster with a browser$ helm install prometheus-community/kube-prometheus-stack \--create-namespace --namespace prometheus \--generate-name \--set prometheus.service.type=NodePort \--set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false

此时,集群配置如下所示,其中所有的Prometheus pods和服务健康运行。

代码语言:javascript
复制
$ kubectl get pods -ANAMESPACE     NAME                                                              READY   STATUS    RESTARTS   AGEkube-system   calico-kube-controllers-8f59968d4-zrsdt                           1/1     Running   0          18mkube-system   calico-node-c257f                                                 1/1     Running   0          18mkube-system   coredns-f9fd979d6-c52hz                                           1/1     Running   0          19mkube-system   coredns-f9fd979d6-ncbdp                                           1/1     Running   0          19mkube-system   etcd-ip-172-31-27-93                                              1/1     Running   1          19mkube-system   kube-apiserver-ip-172-31-27-93                                    1/1     Running   1          19mkube-system   kube-controller-manager-ip-172-31-27-93                           1/1     Running   1          19mkube-system   kube-proxy-b9szp                                                  1/1     Running   1          19mkube-system   kube-scheduler-ip-172-31-27-93                                    1/1     Running   1          19mkube-system   nvidia-device-plugin-1602308324-jg842                             1/1     Running   0          17mprometheus    alertmanager-kube-prometheus-stack-1602-alertmanager-0            2/2     Running   0          92sprometheus    kube-prometheus-stack-1602-operator-c4bc5c4d5-f5vzc               2/2     Running   0          98sprometheus    kube-prometheus-stack-1602309230-grafana-6b4fc97f8f-66kdv         2/2     Running   0          98sprometheus    kube-prometheus-stack-1602309230-kube-state-metrics-76887bqzv2b   1/1     Running   0          98sprometheus    kube-prometheus-stack-1602309230-prometheus-node-exporter-rrk9l   1/1     Running   0          98sprometheus    prometheus-kube-prometheus-stack-1602-prometheus-0                3/3     Running   1          92s  $ kubectl get svc -ANAMESPACE     NAME                                                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                        AGEdefault       kubernetes                                                  ClusterIP   10.96.0.1        <none>        443/TCP                        20mkube-system   kube-dns                                                    ClusterIP   10.96.0.10       <none>        53/UDP,53/TCP,9153/TCP         20mkube-system   kube-prometheus-stack-1602-coredns                          ClusterIP   None             <none>        9153/TCP                       2m18skube-system   kube-prometheus-stack-1602-kube-controller-manager          ClusterIP   None             <none>        10252/TCP                      2m18skube-system   kube-prometheus-stack-1602-kube-etcd                        ClusterIP   None             <none>        2379/TCP                       2m18skube-system   kube-prometheus-stack-1602-kube-proxy                       ClusterIP   None             <none>        10249/TCP                      2m18skube-system   kube-prometheus-stack-1602-kube-scheduler                   ClusterIP   None             <none>        10251/TCP                      2m18skube-system   kube-prometheus-stack-1602-kubelet                          ClusterIP   None             <none>        10250/TCP,10255/TCP,4194/TCP   2m12sprometheus    alertmanager-operated                                       ClusterIP   None             <none>        9093/TCP,9094/TCP,9094/UDP     2m12sprometheus    kube-prometheus-stack-1602-alertmanager                     ClusterIP   10.104.106.174   <none>        9093/TCP                       2m18sprometheus    kube-prometheus-stack-1602-operator                         ClusterIP   10.98.165.148    <none>        8080/TCP,443/TCP               2m18sprometheus    kube-prometheus-stack-1602-prometheus                       NodePort    10.105.3.19      <none>        9090:30090/TCP                 2m18sprometheus    kube-prometheus-stack-1602309230-grafana                    ClusterIP   10.100.178.41    <none>        80/TCP                         2m18sprometheus    kube-prometheus-stack-1602309230-kube-state-metrics         ClusterIP   10.100.119.13    <none>        8080/TCP                       2m18sprometheus    kube-prometheus-stack-1602309230-prometheus-node-exporter   ClusterIP   10.100.56.74     <none>        9100/TCP                       2m18sprometheus    prometheus-operated                                         ClusterIP   None             <none>        9090/TCP                       2m12s
b. 部署dcgm-exporter
代码语言:javascript
复制
$ helm repo add gpu-helm-charts \https://nvidia.github.io/gpu-monitoring-tools/helm-charts$ helm repo update

使用helm安装

代码语言:javascript
复制
$ helm install \   --generate-name \   gpu-helm-charts/dcgm-exporter

结果验证

代码语言:javascript
复制
$ helm lsNAME                            NAMESPACE       REVISION        APP VERSIONdcgm-exporter-1-1601677302      default         1               dcgm-exporter-1.1.0             2.0.10nvidia-device-plugin-1601662841 default         1          nvidia-device-plugin-0.7.0      0.7.0

Prometheus和Grafana服务暴露如下:

代码语言:javascript
复制
$ kubectl get svc -ANAMESPACE     NAME                                                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                        AGEdefault       dcgm-exporter                                             ClusterIP   10.99.34.128     <none>        9400/TCP                       43ddefault       kubernetes                                                  ClusterIP   10.96.0.1        <none>        443/TCP                        20mkube-system   kube-dns                                                    ClusterIP   10.96.0.10       <none>        53/UDP,53/TCP,9153/TCP         20mkube-system   kube-prometheus-stack-1602-coredns                          ClusterIP   None             <none>        9153/TCP                       2m18skube-system   kube-prometheus-stack-1602-kube-controller-manager          ClusterIP   None             <none>        10252/TCP                      2m18skube-system   kube-prometheus-stack-1602-kube-etcd                        ClusterIP   None             <none>        2379/TCP                       2m18skube-system   kube-prometheus-stack-1602-kube-proxy                       ClusterIP   None             <none>        10249/TCP                      2m18skube-system   kube-prometheus-stack-1602-kube-scheduler                   ClusterIP   None             <none>        10251/TCP                      2m18skube-system   kube-prometheus-stack-1602-kubelet                          ClusterIP   None             <none>        10250/TCP,10255/TCP,4194/TCP   2m12sprometheus    alertmanager-operated                                       ClusterIP   None             <none>        9093/TCP,9094/TCP,9094/UDP     2m12sprometheus    kube-prometheus-stack-1602-alertmanager                     ClusterIP   10.104.106.174   <none>        9093/TCP                       2m18sprometheus    kube-prometheus-stack-1602-operator                         ClusterIP   10.98.165.148    <none>        8080/TCP,443/TCP               2m18sprometheus    kube-prometheus-stack-1602-prometheus                       NodePort    10.105.3.19      <none>        9090:30090/TCP                 2m18sprometheus    kube-prometheus-stack-1602309230-grafana                    ClusterIP   10.100.178.41    <none>        80:32032/TCP                   2m18sprometheus    kube-prometheus-stack-1602309230-kube-state-metrics         ClusterIP   10.100.119.13    <none>        8080/TCP                       2m18sprometheus    kube-prometheus-stack-1602309230-prometheus-node-exporter   ClusterIP   10.100.56.74     <none>        9100/TCP                       2m18sprometheus    prometheus-operated                                         ClusterIP   None             <none>        9090/TCP                       2m12s
‍‍‍‍使用32032端口暴露的Grafana服务,访问Grafana主页。使用Prometheus chart中设置的凭证登录到仪表板:prometheus.values中的adminPassword字段。
现在要启动一个用于GPU指标的Grafana仪表板,请从Grafana仪表板(https://grafana.com/grafana/dashboards/12239)导入NVIDIA仪表板。

查看DCGM指标

现在运行一些GPU工作负载,为此,DCGM社区提供了一个名为dcgmproftester的CUDA负载生成器,它可以用来生成确定性的CUDA工作负载,用于读取和验证GPU指标。

要生成一个Pod,首先必须下载DCGM并将制成镜像。以下脚本创建了一个可用于运行dcgmproftester的容器。这个容器可以在NVIDIA DockerHub仓库中找到。

代码语言:javascript
复制
#!/usr/bin/env bashset -exo pipefail mkdir -p /tmp/dcgm-dockerpushd /tmp/dcgm-docker cat > Dockerfile <<EOFARG BASE_DISTARG CUDA_VERFROM nvidia/cuda:\${CUDA_VER}-base-\${BASE_DIST}LABEL io.k8s.display-name="NVIDIA dcgmproftester" ARG DCGM_VERSION WORKDIR /dcgmRUN apt-get update && apt-get install -y --no-install-recommends \    libgomp1 \    wget && \    rm -rf /var/lib/apt/lists/* && \    wget --no-check-certificate https://developer.download.nvidia.com/compute/redist/dcgm/\${DCGM_VERSION}/DEBS/datacenter-gpu-manager_\${DCGM_VERSION}_amd64.deb && \    dpkg -i datacenter-gpu-manager_*.deb && \    rm -f datacenter-gpu-manager_*.deb ENTRYPOINT ["/usr/bin/dcgmproftester11"]EOF DIR=.DCGM_REL_VERSION=2.0.10BASE_DIST=ubuntu18.04CUDA_VER=11.0IMAGE_NAME=nvidia/samples:dcgmproftester-$DCGM_REL_VERSION-cuda$CUDA_VER-$BASE_DIST  docker build --pull \        -t "$IMAGE_NAME" \        --build-arg DCGM_VERSION=$DCGM_REL_VERSION \        --build-arg BASE_DIST=$BASE_DIST \        --build-arg CUDA_VER=$CUDA_VER \        --file Dockerfile \        "$DIR" popd

在Kubernetes集群上部署容器之前,尝试直接使用Docker运行它。在这个例子中,通过指定-t 1004来使用Tensor Cores触发FP16矩阵乘法,并以-d 45(45秒)的速度运行测试。您可以通过修改-t参数来尝试运行其他工作负载。

代码语言:javascript
复制
Skipping CreateDcgmGroups() since DCGM validation is disabledCU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_MULTIPROCESSOR: 1024CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT: 40CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_MULTIPROCESSOR: 65536CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR: 7CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR: 5CU_DEVICE_ATTRIBUTE_GLOBAL_MEMORY_BUS_WIDTH: 256CU_DEVICE_ATTRIBUTE_MEMORY_CLOCK_RATE: 5001000Max Memory bandwidth: 320064000000 bytes (320.06 GiB)CudaInit completed successfully. Skipping WatchFields() since DCGM validation is disabledTensorEngineActive: generated ???, dcgm 0.000 (27605.2 gflops)TensorEngineActive: generated ???, dcgm 0.000 (28697.6 gflops)

将其部署到Kubernetes集群上,可以通过Grafana仪表板观测相应的指标。下面的代码示例:

代码语言:javascript
复制
cat << EOF | kubectl create -f - apiVersion: v1 kind: Pod metadata:   name: dcgmproftester spec:   restartPolicy: OnFailure   containers:   - name: dcgmproftester11     image: nvidia/samples:dcgmproftester-2.0.10-cuda11.0-ubuntu18.04     args: ["--no-dcgm-validation", "-t 1004", "-d 120"]     resources:       limits:          nvidia.com/gpu: 1     securityContext:       capabilities:          add: ["SYS_ADMIN"] EOF

可以看到dcgmproftester pod健康运行,随后指标显示在Grafana仪表板上。GPU利用率(GrActive)已经达到了98%的利用率峰值,可能还会发现其他有趣的指标,比如功率或GPU内存。

代码语言:javascript
复制
$ kubectl get pods -ANAMESPACE     NAME                                                              READY   STATUS    RESTARTS   AGE...default       dcgmproftester                                                    1/1     Running   0          6s

DCGM最近增加了一些设备级指标。其中包括细粒度的GPU利用率指标,可以监控SM占用率和Tensor Core利用率。有关更多信息,可以查看DCGM用户指南中的Profiling Metrics。

下图显示了 Prometheus获取的由dcgm-exporter 提供的监控指标。

您可以自定义Grafana仪表板,以包含DCGM的其他指标。在这种情况下,通过编辑 repo 上提供的 Grafana JSON 文件将 Tensor Core 利用率添加到仪表板中,也可以使用Grafana的Web界面进行编辑。

下面的仪表板包括Tensor Core利用率。重新启动dcgmproftester容器后,你可以看到T4上的Tensor Core已经达到了约87%的利用率。

通过将GPU指标作为自定义指标和Prometheus Adapter,可以使用Horizontal Pod Autoscaler根据GPU利用率或其他指标来扩展Pod数量。

二、参考资料

1. https://developer.nvidia.com/blog/monitoring-gpus-in-kubernetes-with-dcgm/#

往期 · 精选

1、技术分享 | Kubelet从人门到放弃:识透CPU管理

2、干货分享 | OpenAI:Kubernetes集群近万节点的生产实践

3、干货分享 | Kubernetes将废弃PodSecurityPolicy

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DCOS 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • b. 部署dcgm-exporter
  • ‍‍‍‍使用32032端口暴露的Grafana服务,访问Grafana主页。使用Prometheus chart中设置的凭证登录到仪表板:prometheus.values中的adminPassword字段。
  • 现在要启动一个用于GPU指标的Grafana仪表板,请从Grafana仪表板(https://grafana.com/grafana/dashboards/12239)导入NVIDIA仪表板。
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档