처음뵙겠습니다 (●’◡’●)

두다지에서 인턴으로 근무하고 있는 kade 입니다. 앞으로 종종 포스트 할 수 있으면 좋겠네요.

클러스터,클라우드 운영에 있어서 가장 중요한 것 중 하나는 가용자원 모니터링이 아닐까 생각합니다.
쿠버네티스 클러스터 내의 CPU,Memory의 사용량은 kubectl descirbe 명령어와 kubectl top 명령어를 이용하면 손쉽게 CPU와 Memory 사용량을 알 수 있습니다. 그렇다면 쿠버네티스 클러스터 내에서 GPU를 이용하고 있는 pod , container 의 정보는 어떻게 알 수 있을까요?

방법이 여러가지 있지만 오늘은 Nvidia에서 제공하는 dcgm exporter 에 대해 소개해 드리고자 합니다.

Nvidia DCGM

2020년 11월 4일 엔비디아 개발자 블로그에 이 하나 올라왔습니다.

그 주제는 바로 ‘Monitoring GPUs in Kubernetes with DCGM’ , DCGM 은 Data Center GPU Manager 의 약어로 Nvidia에서 제공하는 Tesla 시리즈의 그래픽 카드를 장착한 클러스터 또는 데이터센터 환경에서 비교적 가벼운 코스트로 GPU 를 모니터링하게 해주는 역할을 합니다.

여기서 주목할 점은 Tesla 시리즈에만 이 기능을 제공한다는 것인데, 두다지에서는 Tesla 그래픽 카드를 사용하지 않고 RTX 와 GTX 시리즈의 그래픽카드를 사용하고 있습니다. 그렇다면 저희는 DCGM 을 사용할 수 없을까요? ‘정답은 포스트 제목에서 알 수 있겠지만, 사용가능하다’ 입니다.

호환이 안되는걸 알았지만 공식 블로그를 보고 무작정 따라해 보았습니다.

DCGM Exporter 설치

  • 설치 환경
    • OS : Ubuntu Linux 18.04
    • kubernetes version : 1.15.11 (master) / 1.15.12(worker) , 1.16.15 (worker)
    • helm version : 3.3.1
    • Nvidia-driver version : 450.51.06
    • CUDA version : 11.0
    • GPU : RTX 3090, RTX 2080 Ti , GTX 1080, GTX 1080 Ti
  • 원래 공식 문서에 따라 DCGM Exporter를 사용하려면 kubernetes 버전이 1.16이상이어야 합니다.

1. helm repo 추가

$ helm repo add prometheus-community \
https://prometheus-community.github.io/helm-charts
$ helm repo update

2. helm 설치시 사용할 value 설정 ( 중요 )

$ 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

자세한 사항은 Nvidia datacenter 공식문서 에 나와 있습니다.

간단하게 요약하면 총 3가지 작업을 해야 합니다.

a. vi /tmp/kube-prometheus-stack.values 등의 편집기를 이용하여 values 파일을 열고 하단 부분을 찾아서 수정해주세요

# Port to expose on each node
# Only used if service.type is 'NodePort'
#
 nodePort: 30090 # <-- 다른 노드포트를 사용해도 괜찮습니다.

# Loadbalancer IP
# Only use if service.type is "loadbalancer"
 loadBalancerIP: ""
 loadBalancerSourceRanges: []
# Service type
#
 type: ClusterIP # <-- 이 부분을 NodePort 로 변경하세요 

b. 같은 파일에서 serviceMonitorSelectorNilUsesHelmValues: 필드를 false 로 설정해주세요

# If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the
# prometheus resource to be created with selectors based on values in the helm deployment,
# which will also match the servicemonitors created
#
serviceMonitorSelectorNilUsesHelmValues: false  # <-- 이부분 false 확인 

c. 같은 파일에서 exporter 로 사용할 ( scrape 할) config 정보를 추가해주세요

  • 만약 기존 프로메테우스가 설치되어 있다면, 프로메테우스의 configmap 에 하단부분을 넣어주세요
# AdditionalScrapeConfigs allows specifying additional Prometheus scrape configurations. Scrape configurations
# are appended to the configurations generated by the Prometheus Operator. Job configurations must have the form
# as specified in the official Prometheus documentation:
# https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config. As scrape configs are
# appended, the user is responsible to make sure it is valid. Note that using this feature may expose the possibility
# to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible
# scrape configs are going to break Prometheus after the upgrade.
#
# The scrape configuration example below will find master nodes, provided they have the name .*mst.*, relabel the
# port to 2379 and allow etcd scraping provided it is running on all Kubernetes master nodes
#
additionalScrapeConfigs: # <-- 이부분 추가 !
- job_name: gpu-metrics
  scrape_interval: 1s
  metrics_path: /metrics
  scheme: http
  kubernetes_sd_configs:
  - role: endpoints
    namespaces:
      names:
      - gpu-operator-resources
  relabel_configs:
  - source_labels: [__meta_kubernetes_pod_node_name]
    action: replace
    target_label: kubernetes_node

3. helm install

Tesla 시리즈가 아닌 다른 그래픽 카드를 쓰신다면 5번을 보고 와주세요!

+ 마지막 --version 9.4.10은 쿠버네티스 버전이 1.16 미만 일때만 해주세요.

helm install prometheus-community/kube-prometheus-stack \
   --create-namespace --namespace prometheus \
   --generate-name \
   --values /tmp/kube-prometheus-stack.values --version 9.4.10

sidecar istio inject 등의 문제로 custom 하게 helm install 을 하고 싶다면 helm charts 를 다운받아서 로컬 설치할 수 있습니다.

sudo helm pull gpu-helm-charts/dcgm-exporter

# 다운받은 charts directory 안에서
vi daemonset.yaml 

# spec.template.metadata.annotations 필드에
spec:
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/component: dcgm-exporter
      app.kubernetes.io/instance: dcgm-exporter-1604622934
      app.kubernetes.io/name: dcgm-exporter
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "false"  <-- 이부분 설정
      creationTimestamp: null

4. prometheus 에서 확인

  • Tesla 그래픽 카드에 Kubernetes 1.16 버전을 사용 하신다면 아래와 같이 문제없이 설치되었겠지만

prom-dcgm-1

  • GTX, RTX 를 사용하신다면..

prom-dcgm-error1 prom-dcgm-error2

위와 같은 에러와 함께 작동되지 않는 걸 보실 수 있습니다.

5. GTX, RTX에서 DCGM exporter 사용하기

  • 저는 두다지의 클러스터에 DCGM Exporter 을 적용해보고 싶었고,

    Nvidia Developer Forum에 글을 남겼습니다.

    글을 남기고 하루가 안되어 답글이 달렸고 , 그 방법은 간단했습니다.

    바로 --set arguments=null 을 붙여주는것.

    비록 프로파일링은 안되겠지만 ,다른 기능은 사용할 수 있다고 합니다.

blog-reply

  
  helm install prometheus-community/kube-prometheus-stack \
     --create-namespace --namespace prometheus \
     --generate-name \
     --values /tmp/kube-prometheus-stack.values --version 9.4.10 \
     --set arguments=null
    
  • 위와같이 설치하고나면 GPU ID 와 함께 Container , Pod, namespace 정보까지 알 수 있습니다.

    GPU 의 UUID 를 알고나면 이 그래픽카드가 어떤 그래픽카드인지 까지 알 수 있고, 또 얼마나 사용중인지 알 수 있습니다. 이를 위한 exporter도 있지만 이는 나중에 포스트 해보도록 하겠습니다.

주의사항

1. Helm

도중에 설정을 잘못하여 재설치를 해야한다면, 반드시 helm uninstall 로 깔끔하게 지워주세요

helm uninstall RELEASE_NAME [...] [flags]

만약 일부만 ( 특히 네임스페이스만 ) 삭제하셨다면 하단 것들을 차례로 확인하며 dcgm 과 관련된것들을 모두 삭제해주셔야 합니다.

  • podSecurityPolicy

  • Clusterrole

  • Clusterrolebinding

  • Service ( in kube-system)

  • MutatingWebhookConfiguration

  • ValidatingWebhookConfiguration

2. 자신의 kubernetes 버전과 그래픽카드 종류를 확인하고 잘 따라해보세요

  • 중간중간 설명이 있지만, 놓치기 쉽습니다

마치며

쿠버네티스를 이용한 클러스터를 운영하시며 GPU 모니터링에 관심이 많으신분들에게 도움이 되었으면 좋겠습니다 , 다음엔 nvidia-smi 를 exporter로 활용하는 nvidia-exporter 에 대해 포스팅 해보겠습니다.