배경

최근 원격에 NVIDIA GPU가 장착된 LLM 서버를 운영하기 시작했다. Ollama를 통해 여러 LLM 모델을 서빙하고 있는데, GPU 리소스가 얼마나 사용되고 있는지 실시간으로 확인할 방법이 없었다.

SSH로 접속해서 nvidia-smi를 매번 실행하는 것은 번거롭고, 과거 데이터를 추적할 수도 없었다. 운영 중인 Prometheus + Grafana 모니터링 스택에 GPU 메트릭을 추가하기로 결정했다.

목표

  1. 실시간 모니터링: GPU 사용률과 온도를 실시간으로 확인
  2. 히스토리 추적: 과거 GPU 사용 패턴 분석
  3. 통합 대시보드: 기존 모니터링 시스템에 통합
  4. 낮은 오버헤드: 모니터링 자체가 부담이 되면 안 됨

시스템 구성

아키텍처

┌─────────────────────────────────────────┐
│ Main 서버 (main-server)                 │
│                                         │
│ ┌─────────────┐      ┌──────────────┐  │
│ │ Prometheus  │ ───▶ │   Grafana    │  │
│ │  (9090)     │      │   (3000)     │  │
│ └─────────────┘      └──────────────┘  │
│        │                                │
│        │ 포트포워딩 (59100, 59400)       │
└────────┼─────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────┐
│ 원격 LLM 서버 (gpu-server.example.com)  │
│                                         │
│ ┌──────────────┐   ┌──────────────┐    │
│ │ Node         │   │ GPU Metrics  │    │
│ │ Exporter     │   │ Exporter     │    │
│ │  (9100)      │   │  (9400)      │    │
│ └──────────────┘   └──────────────┘    │
│                           │             │
│                    ┌──────▼───────┐     │
│                    │  nvidia-smi  │     │
│                    │  (NVIDIA GB10)│    │
│                    └──────────────┘     │
└─────────────────────────────────────────┘

구성 요소

  • Main 서버: Prometheus, Grafana가 이미 운영 중
  • 원격 서버: NVIDIA GB10 GPU 장착
  • Node Exporter: 시스템 리소스 메트릭 수집
  • GPU Metrics Exporter: GPU 메트릭 수집 (직접 구현)

구현 과정

1단계: Node Exporter 설치

시스템 메트릭 수집을 위해 Docker로 Node Exporter를 설치했다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 원격 서버에서
docker run -d \\
  --name node-exporter \\
  --net host \\
  --pid host \\
  --userns host \\
  -v /proc:/host/proc:ro \\
  -v /sys:/host/sys:ro \\
  -v /:/rootfs:ro \\
  prom/node-exporter:latest \\
  --path.procfs=/host/proc \\
  --path.rootfs=/rootfs \\
  --path.sysfs=/host/sys

2단계: GPU Metrics Exporter 구현

NVIDIA DCGM Exporter는 ARM64 아키텍처를 지원하지 않아서, nvidia-smi를 래핑하는 간단한 Prometheus Exporter를 직접 구현했다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
# gpu_metrics_simple.sh
while true; do
  {
    echo "HTTP/1.1 200 OK"
    echo "Content-Type: text/plain"
    echo ""
    nvidia-smi --query-gpu=index,name,utilization.gpu,temperature.gpu \\
      --format=csv,noheader,nounits 2>/dev/null | awk -F',' '
    {
      gsub(/^[ \\t]+|[ \\t]+$/, "")
      gpu=$1; name=$2; util=$3; temp=$4
      
      if (gpu != "") {
        gsub(/ /, "_", name)
        print "nvidia_smi_gpu_utilization{gpu=\\"" gpu "\\",name=\\"" name "\\"} " (util=="" || util=="N/A" ? "0" : util)
        print "nvidia_smi_gpu_temperature_celsius{gpu=\\"" gpu "\\"} " (temp=="" || temp=="N/A" ? "0" : temp)
      }
    }'
  } | nc -w1 -l -p 9400
done

백그라운드 실행:

1
nohup bash gpu_metrics_simple.sh > /dev/null 2>&1 &

3단계: Prometheus 설정

Prometheus에 원격 서버 타겟을 추가했다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# prometheus.yml
scrape_configs:
  - job_name: 'remote-ollama-server'
    scrape_interval: 15s
    scrape_timeout: 10s
    static_configs:
      - targets: ['gpu-server.example.com:59100']
        labels:
          instance: 'ollama-server'
          region: 'remote'

  - job_name: 'gpu-metrics'
    scrape_interval: 15s
    scrape_timeout: 10s
    static_configs:
      - targets: ['gpu-server.example.com:59400']
        labels:
          instance: 'ollama-gpu'
          region: 'remote'

Prometheus 리로드:

1
curl -X POST http://localhost:9090/-/reload

4단계: Grafana 대시보드 생성

Grafana에서 GPU 모니터링 대시보드를 생성했다.

패널 구성:

  1. GPU 사용률 (실시간) - Gauge 타입

    • Query: nvidia_smi_gpu_utilization{job="gpu-metrics"}
    • Threshold: 0% (green) → 70% (yellow) → 90% (red)
  2. GPU 온도 (실시간) - Gauge 타입

    • Query: nvidia_smi_gpu_temperature_celsius{job="gpu-metrics"}
    • Threshold: 0°C (green) → 60°C (yellow) → 80°C (red)
  3. GPU 사용률 추이 - Time series 타입

    • Query: nvidia_smi_gpu_utilization{job="gpu-metrics"}
    • Legend: GPU {{gpu}}
    • Calcs: mean, max
  4. GPU 온도 추이 - Time series 타입

    • Query: nvidia_smi_gpu_temperature_celsius{job="gpu-metrics"}
    • Legend: GPU {{gpu}}
    • Calcs: mean, max

결과

대시보드 화면

┌───────────────────────────────────────────────────────────┐
│  GPU 모니터링                                              │
├───────────────┬───────────────────────────────────────────┤
│ GPU 사용률    │  GPU 사용률 추이 (지난 6시간)               │
│  (실시간)     │                                           │
│               │  [그래프: 시간별 GPU 사용률 변화]           │
│   0%          │  평균: 2%  최대: 15%                       │
│               │                                           │
├───────────────┼───────────────────────────────────────────┤
│ GPU 온도      │  GPU 온도 추이 (지난 6시간)                 │
│  (실시간)     │                                           │
│               │  [그래프: 시간별 GPU 온도 변화]             │
│   34°C        │  평균: 35°C  최대: 39°C                    │
│               │                                           │
└───────────────┴───────────────────────────────────────────┘

수집되는 메트릭

  • nvidia_smi_gpu_utilization: GPU 사용률 (%)
  • nvidia_smi_gpu_temperature_celsius: GPU 온도 (°C)

추후 필요 시 메모리 사용량, 전력 소비 등의 메트릭도 추가할 수 있다.

트러블슈팅

문제 1: DCGM Exporter ARM64 미지원

증상: ARM64 아키텍처에서 DCGM Exporter 이미지를 찾을 수 없음

해결: nvidia-smi를 래핑하는 간단한 bash 스크립트로 대체

문제 2: 메모리 값 N/A

증상: GB10 GPU의 메모리 정보가 “Not Supported"로 표시됨

해결: 메모리 메트릭 수집을 제외하고, 사용률과 온도만 수집

문제 3: Grafana 대시보드 프로비저닝 충돌

증상: 같은 UID를 가진 대시보드 JSON 파일이 여러 개 존재

해결: 이전 파일들을 삭제하고 최종 버전만 유지

1
2
3
4
5
# 중복 파일 삭제
rm gpu-monitoring.json gpu-monitoring-updated.json

# Grafana 재시작
docker restart grafana

배운 점

  1. 간단한 게 최고다: DCGM 같은 복잡한 도구보다 bash 스크립트가 더 안정적일 수 있다.

  2. 포트포워딩 필수: 원격 서버의 메트릭을 수집하려면 포트포워딩 설정이 선행되어야 한다.

  3. Prometheus는 관대하다: 15초마다 스크래핑하지만 실패해도 계속 재시도한다. 네트워크가 불안정해도 괜찮다.

  4. Grafana 프로비저닝의 함정: 같은 UID를 가진 대시보드가 여러 개 있으면 충돌한다. 파일 관리가 중요하다.

  5. 실시간 + 추이 = 완벽: Gauge로 현재 상태를 보고, Time series로 과거 패턴을 분석할 수 있다.

다음 단계

  • GPU 메모리 사용량 메트릭 추가 (다른 GPU에서 테스트)
  • Alert 설정 (GPU 온도 80°C 이상, 사용률 95% 이상)
  • 여러 GPU 지원 (현재는 단일 GPU만)
  • Ollama 모델별 GPU 사용량 매핑

참고 자료


결론: 간단한 bash 스크립트와 기존 모니터링 스택을 활용해서 원격 GPU 서버의 실시간 모니터링을 구축했다. 이제 GPU 사용 패턴을 분석하고 리소스를 효율적으로 관리할 수 있게 되었다. 🎉