글 목록

쿠버네티스 GPU 공유 2026: MIG·타임슬라이싱·MPS·DRA로 추론 비용 절반 만들기

GPU 1장을 여러 LLM 추론 워크로드가 안전하게 나눠 쓰는 4가지 방식(MIG·타임슬라이싱·MPS·DRA)을 격리 수준·하드웨어 요건·NVIDIA GPU Operator 매니페스트와 함께 비교하고 선택 기준을 정리합니다.

IntentCode··11 min read

왜 지금 GPU 공유가 추론 원가의 핵심인가

LLM 추론을 쿠버네티스에 올려본 팀이라면 청구서를 보고 한 번쯤 멈칫합니다. H100 한 장이 시간당 수 달러인데, 정작 nvidia-smi를 찍어 보면 GPU 사용률이 20~30%에서 머무는 경우가 흔합니다. 작은 임베딩 모델이나 7B급 모델을 GPU 한 장에 통째로 점유시켜 두기 때문입니다. 즉 비용 문제의 본질은 "GPU가 비싸다"가 아니라 **"비싼 GPU를 한 워크로드가 독점하고도 다 못 쓴다"**입니다.

2026년 현재 이 문제의 해법은 GPU를 여러 워크로드가 나눠 쓰는 **GPU 공유(GPU sharing)**로 수렴했습니다. 그런데 공유 방식이 하나가 아니라 네 가지(MIG, 타임슬라이싱, MPS, DRA)이고, 각각 격리 수준과 하드웨어 요건이 전혀 다릅니다. 잘못 고르면 한 모델의 OOM이 옆 모델까지 죽이거나, 멀티테넌트 환경에서 보안 격리가 깨집니다.

이 글에서는 네 가지 GPU 공유 방식을 격리 수준·지원 하드웨어·운영 난이도 관점에서 비교하고, NVIDIA GPU Operator와 실제 매니페스트로 적용하는 방법, 그리고 흔한 함정과 해결책까지 정리합니다.

배경: GPU 공유 4가지 방식과 2026년 선택지

먼저 네 가지 방식의 핵심 특성을 비교합니다. 같은 "GPU 나눠 쓰기"라도 메모리 격리·장애 격리·동시 실행 여부가 다르다는 점이 선택의 출발점입니다.

방식격리 수준VRAM 격리장애 격리동시 커널 실행지원 GPU주 용도
MIG하드웨어 파티셔닝✅ 전용✅ 완전A100/H100+멀티테넌트, SLA 보장
타임슬라이싱시분할(소프트웨어)❌ 공유 풀❌ (순차)모든 CUDA GPU개발/저부하 다중 워크로드
MPS공간 분할(소프트웨어)❌ 공유 풀Volta+신뢰된 워크로드 동시 처리
DRA스케줄러 레이어방식에 따름방식에 따름방식에 따름K8s 1.34+이기종 하드웨어 선언적 할당

핵심을 한 줄로 요약하면 이렇습니다. MIG는 하드웨어가 칼같이 갈라 주는 유일한 방식이고, 타임슬라이싱·MPS는 격리를 포기하는 대신 모든 GPU에서 쓸 수 있는 소프트웨어 방식이며, DRA는 이 셋을 어떻게 할당할지를 쿠버네티스가 선언적으로 다루게 해 주는 상위 프레임워크입니다.

세부 차이를 짚으면 다음과 같습니다.

  • MIG는 지원 GPU(A100/H100급 이상)를 최대 7개의 독립 인스턴스로 물리 분할합니다. 각 인스턴스는 전용 SM·L2 캐시·메모리 채널·장애 도메인을 가져, 한 인스턴스가 죽어도 나머지는 멀쩡합니다. 단, 프로파일이 정적이라 재구성하려면 해당 GPU의 워크로드를 모두 드레인해야 합니다.
  • 타임슬라이싱은 GPU 1장을 N개 복제본으로 광고하지만, 실제로는 워크로드가 시간을 번갈아 차지합니다. VRAM을 공유 풀로 함께 쓰기 때문에 한 프로세스가 메모리를 다 먹으면 옆 프로세스가 OOM으로 죽습니다.
  • MPS는 여러 CUDA 프로세스를 공간적으로 동시에 실행해 처리량을 높입니다. 다만 한 클라이언트의 결함이 같은 GPU를 쓰는 다른 클라이언트에 영향을 줄 수 있어, 신뢰된 워크로드 사이에서만 권장됩니다.
  • **DRA(Dynamic Resource Allocation)**는 쿠버네티스 v1.34(2025년 8월 27일 릴리스)에서 GA로 승격된 프레임워크로, GPU 종류·메모리 계층·토폴로지 제약 같은 이기종 하드웨어를 컨트롤 플레인이 이해하고 선언적으로 할당하게 해 줍니다.

심층 분석: 매니페스트로 보는 4가지 방식

1) 타임슬라이싱 — 가장 빠른 시작

타임슬라이싱은 NVIDIA GPU Operator에 ConfigMap 하나만 적용하면 켜집니다. GPU 1장을 4개 복제본으로 광고하는 예시입니다.

# time-slicing-config.yaml — GPU 1장을 4개 replica로 광고
apiVersion: v1
kind: ConfigMap
metadata:
  name: time-slicing-config
  namespace: gpu-operator
data:
  any: |-
    version: v1
    flags:
      migStrategy: none
    sharing:
      timeSlicing:
        # ⚠️ 주의: replicas는 VRAM을 격리하지 않습니다. 한 Pod가 메모리를 다 쓰면 OOM 전파
        resources:
          - name: nvidia.com/gpu
            replicas: 4   # GPU 1장 → 논리 4장처럼 노출

적용 후 Pod는 평소처럼 GPU 1개를 요청하지만, 실제로는 물리 GPU를 최대 4개 Pod가 나눠 갖게 됩니다.

# embedding-deploy.yaml — 작은 임베딩 서버 4개를 GPU 1장에 배치
apiVersion: apps/v1
kind: Deployment
metadata:
  name: embedding-server
spec:
  replicas: 4
  selector: { matchLabels: { app: embedding } }
  template:
    metadata: { labels: { app: embedding } }
    spec:
      containers:
        - name: embedder
          image: ghcr.io/intentcode/bge-m3-server:1.2
          resources:
            limits:
              nvidia.com/gpu: 1   # 타임슬라이싱이라 실제로는 1/4장
          env:
            # ⚠️ VRAM 상한을 직접 제약해 오버서브스크립션 방지 (타임슬라이싱 필수)
            - name: PYTORCH_CUDA_ALLOC_CONF
              value: "max_split_size_mb:512"

2) MIG — 멀티테넌트와 SLA가 필요할 때

MIG는 물리 분할이라 격리가 가장 강합니다. GPU Operator에 MIG 전략과 프로파일을 지정합니다.

# mig-config.yaml — H100 1장을 1g.10gb 인스턴스 7개로 분할
apiVersion: v1
kind: ConfigMap
metadata:
  name: mig-parted-config
  namespace: gpu-operator
data:
  config.yaml: |-
    version: v1
    mig-configs:
      seven-small:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.10gb": 7   # SM·VRAM·L2가 인스턴스별로 전용 할당

Pod는 일반 nvidia.com/gpu 대신 분할된 프로파일 리소스를 요청합니다.

# mig-pod.yaml — 7B 모델을 전용 MIG 인스턴스에 격리 배치
apiVersion: v1
kind: Pod
metadata:
  name: llm-7b-tenant-a
spec:
  containers:
    - name: vllm
      image: vllm/vllm-openai:v0.8.5
      args: ["--model", "Qwen/Qwen2.5-7B-Instruct", "--gpu-memory-utilization", "0.9"]
      resources:
        limits:
          nvidia.com/mig-1g.10gb: 1   # 전용 파티션 1개 — 옆 테넌트와 완전 격리

3) DRA — 선언적으로 "원하는 GPU 모양" 요청

DRA에서는 리소스를 카운트가 아니라 ResourceClaim으로 선언합니다. "MIG 1g.10gb 한 조각이 필요하다"를 의도 그대로 표현하는 방식입니다.

# dra-claim.yaml — Kubernetes 1.34 GA DRA 기준 ResourceClaim 예시
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
  name: mig-slice-claim
spec:
  devices:
    requests:
      - name: gpu-slice
        deviceClassName: mig.nvidia.com   # 드라이버가 광고한 디바이스 클래스
        selectors:
          - cel:
              expression: "device.attributes['nvidia.com'].profile == '1g.10gb'"
---
apiVersion: v1
kind: Pod
metadata:
  name: llm-dra
spec:
  resourceClaims:
    - name: gpu
      resourceClaimName: mig-slice-claim
  containers:
    - name: vllm
      image: vllm/vllm-openai:v0.8.5
      resources:
        claims:
          - name: gpu

DRA는 토폴로지 인식 스케줄링을 통해 텐서 병렬 작업에서 의미 있는 실측 시간 단축을 얻을 수 있는 것으로 보고됩니다. 다만 GA 직후인 만큼, 운영 도입 전 클러스터 버전과 드라이버 호환성을 반드시 확인합니다.

실전 가이드: GPU Operator로 단계별 적용

NVIDIA GPU Operator(2026년 5월 기준 v25.10.x 계열)는 GPU 발견·MIG 파티셔닝·타임슬라이싱을 Helm 한 번으로 설치해 줍니다.

# 1) GPU Operator 설치
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia && helm repo update
helm install --wait --generate-name \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator

# 2) 타임슬라이싱 ConfigMap 적용 후 기본 정책으로 지정
kubectl create -f time-slicing-config.yaml
kubectl patch clusterpolicy/cluster-policy \
  -n gpu-operator --type merge \
  -p '{"spec":{"devicePlugin":{"config":{"name":"time-slicing-config","default":"any"}}}}'

# 3) 노드가 GPU를 N배로 광고하는지 확인
kubectl get nodes -o json | jq '.items[].status.capacity["nvidia.com/gpu"]'

# 4) (MIG 전환 시) 라벨로 노드별 MIG 전략 지정
kubectl label nodes <node> nvidia.com/mig.config=seven-small --overwrite

선택 기준은 단순합니다. 멀티테넌트이거나 테넌트별 SLA·보안 격리가 필요하면 MIG, 같은 팀의 신뢰된 저부하 모델 여러 개를 한 장에 욱여넣는 개발/내부 환경이면 타임슬라이싱, 처리량을 끌어올려야 하는 신뢰된 동시 워크로드면 MPS, 그리고 이 셋을 버전·토폴로지까지 고려해 선언적으로 다루고 싶고 클러스터가 1.34+면 DRA입니다.

트러블슈팅: 흔한 함정 3가지

문제 1 — 타임슬라이싱인데 두 번째 Pod가 계속 OOM으로 죽습니다. 타임슬라이싱은 VRAM을 격리하지 않고 공유 풀을 그대로 씁니다. replica 수만 늘렸을 뿐 메모리 총량은 그대로이므로, 각 Pod의 VRAM 사용량 합이 물리 GPU 용량을 넘으면 OOM이 납니다. vLLM이라면 --gpu-memory-utilization0.4 이하로, PyTorch라면 PYTORCH_CUDA_ALLOC_CONF로 프로세스별 상한을 명시해 합이 물리 용량을 넘지 않게 맞춥니다.

문제 2 — MIG를 켰는데 nvidia.com/mig-1g.10gb 리소스가 노드에 안 보입니다. MIG 프로파일 재구성은 해당 GPU의 모든 워크로드를 드레인한 뒤에야 적용됩니다. GPU를 점유한 Pod가 남아 있으면 파티셔닝이 보류됩니다. kubectl drain 후 GPU Operator의 mig-manager Pod 로그에서 재구성 완료를 확인하고, T4·V100·소비자 GPU는 MIG를 지원하지 않는다는 점도 함께 점검합니다.

문제 3 — DRA ResourceClaim이 Pending에서 진행되지 않습니다. DRA는 v1.34 GA지만 DynamicResourceAllocation 피처 게이트와 드라이버(예: NVIDIA DRA driver)가 모두 활성화돼 있어야 합니다. API 그룹이 resource.k8s.io/v1로 노출되는지(kubectl api-resources | grep resource.k8s.io), 드라이버 DaemonSet이 디바이스 클래스를 정상 광고하는지부터 확인합니다.

결론 + IntentCode 관점

GPU 공유는 단일 정답이 없습니다. 격리가 필요하면 MIG, 단순함이 필요하면 타임슬라이싱, 동시성이 필요하면 MPS, 선언성과 토폴로지 인식이 필요하면 DRA라는 축으로 워크로드 성격에 맞춰 고르는 것이 핵심입니다. 단, 멀티테넌트 추론에서는 VRAM·장애 격리가 깨지는 소프트웨어 공유 방식의 한계를 반드시 염두에 둬야 합니다.

IntentCode는 클라우드 네이티브 AI 인프라와 MLOps 라인에서, 고객의 모델 포트폴리오와 SLA 요건을 분석해 MIG·DRA 기반의 GPU 효율화 설계를 제공합니다. "GPU는 늘렸는데 비용만 늘었다"는 단계에서 "같은 GPU로 두 배의 모델을 안전하게 돌린다"로 넘어가는 구간을 함께 설계합니다.