배경
최근 원격에 NVIDIA GPU가 장착된 LLM 서버를 운영하기 시작했다. Ollama를 통해 여러 LLM 모델을 서빙하고 있는데, GPU 리소스가 얼마나 사용되고 있는지 실시간으로 확인할 방법이 없었다.
SSH로 접속해서 nvidia-smi를 매번 실행하는 것은 번거롭고, 과거 데이터를 추적할 수도 없었다. 운영 중인 Prometheus + Grafana 모니터링 스택에 GPU 메트릭을 추가하기로 결정했다.
목표
- 실시간 모니터링: GPU 사용률과 온도를 실시간으로 확인
- 히스토리 추적: 과거 GPU 사용 패턴 분석
- 통합 대시보드: 기존 모니터링 시스템에 통합
- 낮은 오버헤드: 모니터링 자체가 부담이 되면 안 됨
시스템 구성
아키텍처
┌─────────────────────────────────────────┐
│ 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를 설치했다.
| |
2단계: GPU Metrics Exporter 구현
NVIDIA DCGM Exporter는 ARM64 아키텍처를 지원하지 않아서, nvidia-smi를 래핑하는 간단한 Prometheus Exporter를 직접 구현했다.
| |
백그라운드 실행:
| |
3단계: Prometheus 설정
Prometheus에 원격 서버 타겟을 추가했다.
| |
Prometheus 리로드:
| |
4단계: Grafana 대시보드 생성
Grafana에서 GPU 모니터링 대시보드를 생성했다.
패널 구성:
GPU 사용률 (실시간) - Gauge 타입
- Query:
nvidia_smi_gpu_utilization{job="gpu-metrics"} - Threshold: 0% (green) → 70% (yellow) → 90% (red)
- Query:
GPU 온도 (실시간) - Gauge 타입
- Query:
nvidia_smi_gpu_temperature_celsius{job="gpu-metrics"} - Threshold: 0°C (green) → 60°C (yellow) → 80°C (red)
- Query:
GPU 사용률 추이 - Time series 타입
- Query:
nvidia_smi_gpu_utilization{job="gpu-metrics"} - Legend:
GPU {{gpu}} - Calcs: mean, max
- Query:
GPU 온도 추이 - Time series 타입
- Query:
nvidia_smi_gpu_temperature_celsius{job="gpu-metrics"} - Legend:
GPU {{gpu}} - Calcs: mean, max
- Query:
결과
대시보드 화면
┌───────────────────────────────────────────────────────────┐
│ 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 파일이 여러 개 존재
해결: 이전 파일들을 삭제하고 최종 버전만 유지
| |
배운 점
간단한 게 최고다: DCGM 같은 복잡한 도구보다 bash 스크립트가 더 안정적일 수 있다.
포트포워딩 필수: 원격 서버의 메트릭을 수집하려면 포트포워딩 설정이 선행되어야 한다.
Prometheus는 관대하다: 15초마다 스크래핑하지만 실패해도 계속 재시도한다. 네트워크가 불안정해도 괜찮다.
Grafana 프로비저닝의 함정: 같은 UID를 가진 대시보드가 여러 개 있으면 충돌한다. 파일 관리가 중요하다.
실시간 + 추이 = 완벽: Gauge로 현재 상태를 보고, Time series로 과거 패턴을 분석할 수 있다.
다음 단계
- GPU 메모리 사용량 메트릭 추가 (다른 GPU에서 테스트)
- Alert 설정 (GPU 온도 80°C 이상, 사용률 95% 이상)
- 여러 GPU 지원 (현재는 단일 GPU만)
- Ollama 모델별 GPU 사용량 매핑
참고 자료
결론: 간단한 bash 스크립트와 기존 모니터링 스택을 활용해서 원격 GPU 서버의 실시간 모니터링을 구축했다. 이제 GPU 사용 패턴을 분석하고 리소스를 효율적으로 관리할 수 있게 되었다. 🎉