LabHub

블로그

NVIDIA GPU Operator 완전 정복 — 설치·배포부터 MIG 분할 설정까지

한국어English日本語中文

들어가며 — GPU 노드 셋업의 지옥에서 벗어나기

쿠버네티스 클러스터에 GPU 노드를 수동으로 붙여본 사람은 압니다. NVIDIA 드라이버를 커널 버전에 맞춰 설치하고, container toolkit을 깔고, 런타임 설정을 바꾸고, 디바이스 플러그인을 배포하고, 모니터링 익스포터를 붙이고 — 이 다섯 층의 버전 궁합이 하나라도 어긋나면 파드는 GPU를 못 봅니다. 노드가 10대면 이 작업이 10번, 커널 업데이트가 오면 또 처음부터입니다.

NVIDIA GPU Operator는 이 전체 스택을 쿠버네티스 오퍼레이터 패턴으로 자동화합니다. 관리자는 Helm 차트 하나를 설치하고, 원하는 상태를 선언하면, 오퍼레이터가 각 노드에 필요한 컴포넌트를 컨테이너로 배포하고 계속 조정(reconcile)합니다. 이 글은 설치부터 검증, 그리고 A100/H100급 GPU의 킬러 기능인 MIG(Multi-Instance GPU) 분할 설정까지를 실제 명령어와 함께 다룹니다. 쿠버네티스 기초가 필요하다면 이 사이트의 쿠버네티스 놀이터에서 먼저 감을 잡고 오셔도 좋습니다.

GPU Operator는 무엇을 배포하는가

오퍼레이터를 설치하면 gpu-operator 네임스페이스에 다음 오퍼랜드(operand)들이 데몬셋 형태로 깔립니다. 각각이 수동 셋업 시대에 손으로 하던 일 하나씩에 대응합니다.

설치 — Helm 차트 하나로

전제 조건은 세 가지입니다: NVIDIA GPU가 달린 노드, 지원되는 컨테이너 런타임(containerd 등), 그리고 Node Feature Discovery(오퍼레이터가 기본으로 함께 설치).

# 1) NVIDIA Helm 저장소 등록
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update

# 2) 설치 (버전은 문서에서 최신 확인 — 이 글 기준 v26.3.3)
helm install --wait gpu-operator \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator \
  --version=v26.3.3

환경에 따라 자주 쓰는 변형 두 가지:

# 노드에 드라이버가 이미 설치되어 있다면 (DGX OS, 직접 설치 등)
helm install --wait gpu-operator \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator \
  --version=v26.3.3 \
  --set driver.enabled=false

# container toolkit까지 이미 있다면
#   --set toolkit.enabled=false 를 추가

설치 상태 확인:

kubectl get pods -n gpu-operator
# driver-daemonset, container-toolkit, device-plugin, dcgm-exporter,
# gpu-feature-discovery, operator-validator 가 모두 Running/Completed 이면 정상

검증 — 파드에서 GPU가 보이는가

가장 확실한 검증은 GPU를 요청하는 테스트 파드입니다.

apiVersion: v1
kind: Pod
metadata:
  name: gpu-smoke-test
spec:
  restartPolicy: Never
  containers:
    - name: nvidia-smi
      image: nvidia/cuda:12.4.1-base-ubuntu22.04
      command: ['nvidia-smi']
      resources:
        limits:
          nvidia.com/gpu: 1
kubectl apply -f gpu-smoke-test.yaml
kubectl logs gpu-smoke-test
# nvidia-smi 출력에 GPU 모델이 보이면 성공

GFD가 붙여준 노드 라벨도 확인해 두면 노드 셀렉터를 짤 때 유용합니다.

kubectl get node <노드이름> -o jsonpath='{.metadata.labels}' | jq . | grep nvidia
# nvidia.com/gpu.product, nvidia.com/gpu.memory, nvidia.com/gpu.count 등

MIG — 한 장의 GPU를 하드웨어 수준에서 쪼개기

A100/H100 같은 데이터센터 GPU는 한 장이 너무 큽니다. 작은 추론 워크로드 하나가 80GB GPU를 통째로 점유하면 나머지 용량은 놀게 됩니다. MIG(Multi-Instance GPU)는 Ampere 세대부터 지원되는 기능으로, GPU 한 장을 최대 7개의 하드웨어 격리된 인스턴스로 분할합니다.

핵심은 "하드웨어 격리"입니다. 각 MIG 인스턴스는 자기 몫의 SM(연산 유닛), L2 캐시, 메모리 대역폭을 물리적으로 배정받습니다. 시분할(time-slicing)과의 결정적 차이가 여기 있습니다 — 시분할은 여러 파드가 GPU를 번갈아 쓰므로 한 파드의 폭주가 다른 파드의 지연으로 번지지만, MIG는 옆 인스턴스가 무엇을 하든 내 성능이 보장됩니다. 멀티테넌트 클러스터, 추론 서빙, 학생/팀별 GPU 할당에 MIG가 선호되는 이유입니다.

프로필 이름은 <GI 개수>g.<메모리>gb 형식입니다. 예를 들어 H100 80GB 한 장은 대표적으로 이렇게 쪼갤 수 있습니다:

프로필        인스턴스 수(최대)   용도 감각
1g.10gb   ×7                 소형 추론 7개
2g.20gb   ×3                 중형 추론/실험 3개
3g.40gb   ×2                 중대형 학습 2개
7g.80gb   ×1                 분할 없이 통째로
(혼합도 가능: 예 — 3g.40gb 1개 + 2g.20gb 1개 + 1g.10gb 2개)

A100 40GB라면 같은 원리로 1g.5gb×7, 2g.10gb×3, 3g.20gb×2 … 형태가 됩니다. 정확한 조합 규칙은 GPU 모델마다 다르므로 NVIDIA MIG 사용자 가이드의 프로필 표를 기준으로 삼으세요.

MIG 전략 — single vs mixed

GPU Operator에서 MIG를 쓰려면 설치 시 전략(strategy)부터 정합니다. 이 선택이 쿠버네티스에 리소스가 광고되는 방식을 바꿉니다.

# single 전략으로 설치
helm install --wait gpu-operator \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator \
  --version=v26.3.3 \
  --set mig.strategy=single

# 클라우드(GKE/EKS 등)처럼 재부팅이 필요한 환경이라면 추가:
#   --set migManager.env[0].name=WITH_REBOOT \
#   --set-string migManager.env[0].value=true

이미 설치된 클러스터에서 전략만 바꾸려면 ClusterPolicy를 패치합니다:

kubectl patch clusterpolicies.nvidia.com/cluster-policy \
  --type='json' \
  -p='[{"op":"replace", "path":"/spec/mig/strategy", "value":"mixed"}]'

MIG 적용 — 노드 라벨 하나로

MIG Manager의 동작 원리는 우아할 정도로 단순합니다. nvidia.com/mig.config 노드 라벨을 감시하다가, 라벨이 바뀌면 그 프로필을 하드웨어에 적용합니다.

# H100 노드를 1g.10gb 7개로 분할
kubectl label nodes <노드이름> nvidia.com/mig.config=all-1g.10gb --overwrite

기본 제공 프로필에는 all-disabled(MIG 끄기), all-1g.10gb, all-2g.20gb, all-3g.40gb, all-balanced(여러 크기를 균형 있게 혼합) 등이 있습니다. 적용 과정은 라벨로 추적합니다:

kubectl get node <노드이름> -o jsonpath='{.metadata.labels}' | jq . | grep mig
# nvidia.com/mig.config.state 가
#   pending → (필요시 rebooting) → success 로 바뀌면 완료

success 후 리소스를 확인하면 분할 결과가 보입니다:

kubectl describe node <노드이름> | grep -A5 'Allocatable'
# single 전략: nvidia.com/gpu: 7  (라벨의 gpu.product 에 MIG-1g.10gb 표기)
# mixed  전략: nvidia.com/mig-1g.10gb: 7 처럼 프로필별 리소스

mixed 전략에서 파드는 이렇게 특정 프로필을 요청합니다:

resources:
  limits:
    nvidia.com/mig-1g.10gb: 1

커스텀 프로필 — 한 장 안에서 크기 섞기

기본 프로필로 부족하면(예: "GPU 0번만 3g+1g+1g 혼합, 나머지는 MIG 끄기") ConfigMap으로 직접 정의합니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-mig-config
  namespace: gpu-operator
data:
  config.yaml: |
    version: v1
    mig-configs:
      all-disabled:
        - devices: all
          mig-enabled: false
      inference-mix:
        - devices: [0]
          mig-enabled: true
          mig-devices:
            "1g.10gb": 5
            "2g.20gb": 1
        - devices: [1, 2, 3]
          mig-enabled: false
# MIG Manager가 이 ConfigMap을 쓰도록 ClusterPolicy 패치
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
  --type='json' \
  -p='[{"op":"replace", "path":"/spec/migManager/config/name", "value":"custom-mig-config"}]'

# 노드에 커스텀 프로필 적용
kubectl label nodes <노드이름> nvidia.com/mig.config=inference-mix --overwrite

참고로 v26.3.0부터는 MIG Manager가 시작 시 NVML로 노드의 하드웨어를 조회해 가능한 프로필 목록을 런타임에 자동 생성해 노드별 ConfigMap으로 써 줍니다. 새 GPU 모델이 나와도 기본 프로필 목록을 기다릴 필요가 없어졌습니다.

운영 주의사항 — 미리 알면 장애가 아닌 것들

마치며

GPU Operator는 "GPU 노드 셋업"이라는 반복 노동을 선언형 리소스 하나로 바꿔 놓았고, MIG Manager는 그 위에서 값비싼 GPU의 활용률 문제를 라벨 한 줄로 다루게 해 줍니다. 요약하면: Helm으로 설치하고, 전략(single/mixed)을 정하고, nvidia.com/mig.config 라벨로 분할하고, mig.config.state로 확인하고, DCGM으로 관찰한다 — 이 다섯 문장이 전부입니다. 나머지는 여러분의 워크로드에 맞는 프로필을 찾는 일이고, 그것은 모니터링 데이터가 알려줄 것입니다.

리눅스·쿠버네티스 기본기를 함께 다지고 싶다면 리눅스 터미널쿠버스트로넛 퀴즈도 활용해 보세요.

참고 자료

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다