Prometheus를 사용해서 NVIDIA GPU 모니터링 하기

Node의 GPU 모니터링 하기

prometheus를 사용해서 노드들의 매트틱을 수집하고 있다면, 아마 node-exporter를 사용하고 있을 것이다. NVIDIA에서는 dcgm-exporter라는 GPU 매트릭 출력용 이미지를 제공하고 있다. 이 dcgm-exporter과 node-exporter를 결합하여 사용하면, GPU 매트릭을 수집할 수 있다.

dcgm-exporter

dcgm(Data Center GPU Manager) exporter는 nv-hostenging을 시작해서, 매초마다 GPU 매트릭을 읽어서 prometheus 형식으로 출력해주는 간단한 쉘 스크립트이다.

Node 설정하기

우선 일반 노드와 GPU 노드를 분리하기 위해서 taint와 label을 설정해주었다. 대부분 node-exporter를 실행하기 위해서 DaemonSet을 사용했을 것이다.

일반 노드에서는 node-exporter만을 실행하기 위해서 taint nvidia.com/gpu=:NoSchedule를 사용하였고, GPU 노드에서는 node-exporter + dcgm-exporter를 실행하기 위해서 label hardware-type=NVIDIAGPU를 사용하였다.

nvidia.com/brand는 현재로는 별의미가 없지만 붙여주었다.

kubectl taint nodes ${node} nvidia.com/gpu=:NoSchedule

kubectl label nodes ${node} "nvidia.com/brand=${label}"
kubectl label nodes ${node} hardware-type=NVIDIAGPU

기존 node-exporter에 dcgm-exporter 추가하기

dcgm-exporter가 GPU 매트릭을 파일로 남기고, prometheus는 그 파일을 읽어서 GPU 매트릭을 같이 출력한다.

GPU 노드용

apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app.kubernetes.io/name: node-exporter
    app.kubernetes.io/instance: gpu-node-exporter
    app.kubernetes.io/part-of: prometheus
    app.kubernetes.io/managed-by: argo-system
  name: prometheus-gpu-node-exporter
  namespace: argo-system
spec:
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/name: node-exporter
      app.kubernetes.io/instance: gpu-node-exporter
      app.kubernetes.io/part-of: prometheus
      app.kubernetes.io/managed-by: argo-system
  template:
    metadata:
      labels:
        app.kubernetes.io/name: node-exporter
        app.kubernetes.io/instance: gpu-node-exporter
        app.kubernetes.io/part-of: prometheus
        app.kubernetes.io/managed-by: argo-system
    spec:
      nodeSelector:
        hardware-type: NVIDIAGPU
      containers:
      - args:
        - --path.procfs=/host/proc
        - --path.sysfs=/host/sys
        - "--collector.textfile.directory=/run/prometheus"
        image: prom/node-exporter:v0.18.1
        imagePullPolicy: IfNotPresent
        name: prometheus-node-exporter
        ports:
        - containerPort: 9100
          hostPort: 9100
          name: metrics
          protocol: TCP
        resources:
          limits:
            cpu: 500m
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 100Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /host/proc
          name: proc
          readOnly: true
        - mountPath: /host/sys
          name: sys
          readOnly: true
        - name: collector-textfiles
          readOnly: true
          mountPath: /run/prometheus
      - image: nvidia/dcgm-exporter:1.4.6
        name: nvidia-dcgm-exporter
        securityContext:
          runAsNonRoot: false
          runAsUser: 0
        volumeMounts:
          - name: collector-textfiles
            mountPath: /run/prometheus
      dnsPolicy: ClusterFirst
      hostNetwork: true
      hostPID: true
      restartPolicy: Always
      serviceAccount: prometheus-node-exporter
      serviceAccountName: prometheus-node-exporter
      terminationGracePeriodSeconds: 30
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
      - effect: NoSchedule
        key: node-role.kubernetes.io/ingress
        operator: Exists
      - effect: NoSchedule
        key: nvidia.com/gpu
        operator: Exists
      volumes:
      - hostPath:
          path: /proc
          type: ""
        name: proc
      - hostPath:
          path: /sys
          type: ""
        name: sys
      - name: collector-textfiles
        emptyDir:
          medium: Memory
      - name: pod-gpu-resources
        hostPath:
          path: /var/lib/kubelet/pod-resources
  updateStrategy:
    type: OnDelete

일반 노드용

apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app.kubernetes.io/name: node-exporter
    app.kubernetes.io/instance: node-exporter
    app.kubernetes.io/part-of: prometheus
    app.kubernetes.io/managed-by: argo-system
  name: prometheus-node-exporter
  namespace: argo-system
spec:
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/name: node-exporter
      app.kubernetes.io/instance: node-exporter
      app.kubernetes.io/part-of: prometheus
      app.kubernetes.io/managed-by: argo-system
  template:
    metadata:
      labels:
        app.kubernetes.io/name: node-exporter
        app.kubernetes.io/instance: node-exporter
        app.kubernetes.io/part-of: prometheus
        app.kubernetes.io/managed-by: argo-system
    spec:
      containers:
      - args:
        - --path.procfs=/host/proc
        - --path.sysfs=/host/sys
        image: prom/node-exporter:v0.18.1
        imagePullPolicy: IfNotPresent
        name: prometheus-node-exporter
        ports:
        - containerPort: 9100
          hostPort: 9100
          name: metrics
          protocol: TCP
        resources:
          limits:
            cpu: 500m
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 100Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /host/proc
          name: proc
          readOnly: true
        - mountPath: /host/sys
          name: sys
          readOnly: true
      dnsPolicy: ClusterFirst
      hostNetwork: true
      hostPID: true
      restartPolicy: Always
      serviceAccount: prometheus-node-exporter
      serviceAccountName: prometheus-node-exporter
      terminationGracePeriodSeconds: 30
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
      - effect: NoSchedule
        key: node-role.kubernetes.io/ingress
        operator: Exists
      volumes:
      - hostPath:
          path: /proc
          type: ""
        name: proc
      - hostPath:
          path: /sys
          type: ""
        name: sys
  updateStrategy:
    type: OnDelete

프로메테우스 시계열 데이터 삭제하기

프로메테우스(Prometheus)에서 시계열(Time series) 데이터를 삭제하는 방법에 대해서 알아보겠습니다.

디스크 용량이 부족하거나 필요없는 시계열 데이터가 있을 경우, 데이터를 삭제할 필요가 있습니다. 프로메테우스의 시계열 데이터를 삭제하려면 관리 API를 사용해야합니다. 이 관리 API는 기본적으로 비활성화 되어 있습니다.

관리 API 활성화 하기

이 기능을 활성화 하기 위해서는, 프로메테우스를 기동할때 --web.enable-admin-api 파라메터를 추가해줘야합니다.

시계열 데이터 삭제하기

시계열 데이터를 삭제하는 API는 delete_series 입니다. 아래 명령어를 실행하면, 레이블과 일치하는 시계열 데이터를 모두 삭제할 수 있습니다.

curl -X POST \
	-g 'http://localhost:9090/api/v1/admin/tsdb/delete_series?match[]={foo="bar"}'

예를 들어 잡(job)이나 인스턴스(instance)에 해당하는 데이터를 삭제하려면, 다음과 같이 실행하면 됩니다.

curl -X POST \
	-g 'http://localhost:9090/api/v1/admin/tsdb/delete_series?match[]={job="node_exporter"}'

curl -X POST \
	-g 'http://localhost:9090/api/v1/admin/tsdb/delete_series?match[]={instance="172.22.0.1:9100"}'

전체 시계열 데이터를 모두 삭제하려면, 다음과 같이 실행하면 됩니다.

curl -X POST \
	-g 'http://localhost:9090/api/v1/admin/tsdb/delete_series?match[]={__name__=~".+"}'

참고로 delete_series API를 호출해도, 데이터가 즉시 삭제되지는 않는다. 실제 데이터는 디스크에 남아있고, 다음번 컴팩션(compaction)이 실행될때 정리된다. 바로 정리 하고 싶다면, 다음과 같이 clean_tombstones API를 호출하면 된다.

curl -X POST -g 'http://localhost:9090/api/v1/admin/tsdb/clean_tombstones'