본문 바로가기
삵
Cloud Computing & MSA

쿠버네티스 GPU를 여러 파드가 나눠 쓰기

아아주라·2026년 10월 31일·조회 0

GPU 노드는 비싸다. 그런데 막상 붙여 보면 추론 서비스 하나나 주피터 노트북 하나가 카드 한 장을 통째로 잡고 있으면서 실제 사용률은 한 자릿수에 머무는 경우가 흔하다. Azure의 NC/ND 계열이든 온프레미스 A100이든, 노는 GPU를 보고 있으면 아깝다는 생각이 든다. 전에 DRA로 GPU를 할당하는 글을 쓴 적이 있는데, 거기서 한 걸음 더 들어가 "한 장을 여러 파드가 어떻게 나눠 쓰는가"를 정리한다.

NVIDIA GPU Operator는 GPU 한 장을 여러 파드가 공유하도록 세 가지 방식을 제공한다. Time-Slicing은 순번을 나눠 돌리는 소프트웨어 방식이고, MPS는 메모리와 연산을 몫으로 잘라 동시에 실행하며, MIG는 하드웨어로 칸을 막아 격리한다. 격리가 강할수록 설정과 하드웨어 제약이 늘고, 느슨할수록 활용률을 쉽게 올리는 대신 파드끼리 서로 간섭할 여지가 커진다.

1. device plugin이 자원을 광고하는 구조

쿠버네티스는 GPU를 직접 모른다. 노드에서 도는 NVIDIA device plugin이 nvidia.com/gpu라는 이름으로 카드 개수를 kubelet에 광고하고, 스케줄러는 그 숫자만큼만 파드를 배치한다. 카드가 1장이면 기본 상태에서는 파드 하나만 그 GPU를 요청할 수 있다.

공유는 이 광고 숫자를 늘리는 데서 출발한다. 물리 카드 1장을 replicas: 4로 설정하면 플러그인은 같은 카드를 4개의 할당 가능한 자원으로 광고한다. 파드 입장에서는 GPU가 4장 있는 것처럼 보이지만 실제로는 한 장을 공유하는 것이다. 세 방식 모두 이 replicas 설정을 공유하되, 그 뒤에서 GPU 시간을 나누는 방법이 다르다.

2. Time-Slicing으로 순번 돌리기

Time-Slicing은 CUDA 컨텍스트 전환으로 파드들이 GPU를 번갈아 쓰게 한다. 메모리나 장애 격리는 없다. 모든 NVIDIA GPU에서 동작하고 설정이 가장 간단해서, dev/test 노트북이나 트래픽이 뜸한 저위험 워크로드에 맞는다.

GPU Operator 네임스페이스에 ConfigMap을 만든다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: time-slicing-config
  namespace: gpu-operator
data:
  any: |-
    version: v1
    flags:
      migStrategy: none
    sharing:
      timeSlicing:
        renameByDefault: true
        failRequestsGreaterThanOne: true
        resources:
          - name: nvidia.com/gpu
            replicas: 4

renameByDefault: true로 두면 공유 자원이 nvidia.com/gpu 대신 nvidia.com/gpu.shared라는 별도 이름으로 광고된다. 이렇게 하면 공유 GPU를 요구하는 파드와 전용 GPU를 요구하는 파드를 자원 이름만으로 구분할 수 있다. false로 두면 이름은 nvidia.com/gpu 그대로이고 대신 nvidia.com/gpu.product 노드 레이블에 -SHARED 접미사가 붙는다.

failRequestsGreaterThanOne: true는 파드가 nvidia.com/gpu.shared: 2처럼 공유 자원을 2개 이상 요청할 때 요청을 거부하게 한다. Time-Slicing에서 2개를 요청해도 메모리가 2배로 늘지 않고 그저 같은 카드의 타임슬라이스 두 개를 잡을 뿐이라, 오해를 막으려면 켜 두는 쪽이 맞다.

ClusterPolicy에 적용한다. 버전 번호는 저장소 상태에 따라 다를 수 있다.

kubectl patch clusterpolicies.nvidia.com/cluster-policy \
  -n gpu-operator --type merge \
  -p '{"spec": {"devicePlugin": {"config": {"name": "time-slicing-config", "default": "any"}}}}'

특정 노드에만 다른 설정을 걸고 싶으면 ConfigMap에 여러 키를 두고 노드 레이블로 고른다.

kubectl label node <node-name> nvidia.com/device-plugin.config=tesla-t4

적용됐는지는 노드 자원에서 확인한다. replicas가 4면 nvidia.com/gpu.shared가 4로 잡힌다.

$ kubectl describe node <node-name> | grep nvidia.com/gpu
  nvidia.com/gpu.shared:  4
  nvidia.com/gpu.shared:  4

파드는 이 이름으로 요청한다.

resources:
  limits:
    nvidia.com/gpu.shared: 1

여기서 자주 걸리는 지점은 메모리다. Time-Slicing은 메모리를 나눠 주지 않기 때문에, 한 파드가 카드 메모리를 전부 잡으면 같은 카드를 공유하던 다른 파드의 CUDA 할당이 OOM으로 실패할 수 있다. 신뢰할 수 있는 워크로드끼리, 메모리 여유가 넉넉할 때 쓰는 방식이라고 보면 된다.

3. MPS로 메모리와 연산을 몫으로 자르기

MPS는 Multi-Process Service의 약자로, NVIDIA가 제공하는 데몬이 여러 프로세스의 CUDA 작업을 하나의 GPU 컨텍스트에서 동시에 실행시키는 기능이다. Time-Slicing이 순번을 돌리는 것과 달리 MPS는 커널을 겹쳐 돌릴 수 있고, 각 클라이언트에 메모리와 연산 몫의 상한을 걸 수 있다.

설정은 sharing 아래 mps 섹션을 쓴다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: mps-config
  namespace: gpu-operator
data:
  any: |-
    version: v1
    flags:
      migStrategy: none
    sharing:
      mps:
        resources:
          - name: nvidia.com/gpu
            replicas: 4

replicas가 4면 카드는 nvidia.com/gpu.shared 4개로 광고되고, 각 replica는 전체 메모리와 연산의 1/4씩을 상한으로 받는다. 즉 한 파드가 자기 몫을 넘겨 다른 파드의 메모리를 잠식하는 상황이 Time-Slicing보다 통제된다. 40GB 카드를 replicas 4로 나누면 각 파드는 10GB까지 쓰는 식이다.

다만 MPS는 하드웨어 격리가 아니다. 공식 문서가 분명히 적어 둔 한계가 있는데, 한 클라이언트에서 치명적인 장애가 나면 같은 GPU를 쓰는 다른 클라이언트에 영향을 줄 수 있다. 그리고 현재 MPS는 전체 GPU에 대해서만 지원하고 MIG 인스턴스와는 함께 쓸 수 없다. 서로 믿을 수 있는, 같은 신뢰 경계 안의 추론 워크로드를 동시에 돌릴 때 적합하다.

4. MIG로 하드웨어 칸막이 세우기

MIG는 Multi-Instance GPU로, Ampere 세대 이후 카드를 하드웨어 수준에서 여러 개의 독립 인스턴스로 쪼개는 기능이다. 각 인스턴스는 전용 메모리와 연산 블록, 장애 경계를 갖는다. A100과 H100은 최대 7개, A30은 최대 4개까지 나뉜다. 멀티테넌트나 규제 대상 워크로드처럼 예측 가능한 경계와 강한 격리가 필요할 때 쓴다.

MIG는 GPU Operator의 MIG Manager가 관리한다. 전략은 두 가지다. single은 노드의 모든 GPU에 같은 MIG 프로필을 적용하고, mixed는 카드마다 다른 프로필이나 MIG를 끈 상태를 섞을 수 있다.

helm install --wait --generate-name \
  -n gpu-operator --create-namespace \
  nvidia/gpu-operator \
  --set mig.strategy=single

프로필은 노드 레이블로 지정한다. 아래는 각 카드를 1g.10gb 인스턴스들로 나누라는 뜻이다.

kubectl label nodes <node-name> \
  nvidia.com/mig.config=all-1g.10gb --overwrite

MIG 인스턴스는 nvidia.com/gpu.shared가 아니라 프로필별 이름으로 광고된다. 파드는 이렇게 요청한다.

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

MIG 모드를 켜거나 프로필을 바꿀 때는 GPU가 리셋되므로 해당 노드의 GPU 워크로드가 잠시 비워진다. 운영 중 프로필 변경은 노드를 드레인한 뒤 진행해야 한다. 그리고 프로필이 고정이라, 너무 크게 자르면 용량이 남고 너무 작게 자르면 큰 모델이 안 들어가는 낭비가 생긴다. 이 조각 크기를 워크로드에 맞추는 일이 MIG 운영의 핵심이다.

5. 격리가 먼저면 MIG, 활용률이 먼저면 Time-Slicing

세 방식의 차이를 한자리에 놓으면 선택이 분명해진다.

  • Time-Slicing: 격리 없음. 모든 NVIDIA GPU 지원. 설정 가장 단순. 메모리 경쟁과 지연 가능성. dev/test, 저위험 버스트 워크로드.
  • MPS: 메모리와 연산 몫 상한은 있으나 장애 격리 없음. 전체 GPU만, MIG 불가. 동시 실행으로 처리량 이득. 같은 신뢰 경계의 추론.
  • MIG: 하드웨어 격리. Ampere 이상(A100, A30, H100 등). 최대 7분할. 프로필 고정으로 유연성은 낮음. 멀티테넌트와 운영 워크로드.

비용 관점에서 보면 Time-Slicing과 MPS는 추가 하드웨어 요구 없이 기존 카드 활용률을 끌어올려 GPU 노드 수를 줄이는 쪽이다. MIG는 분할 자체는 공짜지만 Ampere 이상 카드를 요구하고, 프로필이 맞지 않으면 쪼갠 조각이 놀면서 오히려 낭비가 된다. 격리 요구가 없다면 Time-Slicing으로 시작해 메모리 간섭이 문제가 될 때 MPS로 올리고, 테넌트 경계를 넘나드는 워크로드라면 처음부터 MIG를 선택하는 순서가 무난하다.

다음으로 볼 만한 건 스케줄링 쪽이다. 공유 자원을 노드에 광고하는 것만으로는 어느 파드가 어느 조각에 갈지까지 제어되지 않으므로, 같은 GPU에 어떤 워크로드를 묶을지는 노드 어피니티나 전용 노드 풀로 따로 설계해야 한다.

자주 묻는 질문

nvidia.com/gpu와 nvidia.com/gpu.shared는 무엇이 다른가

nvidia.com/gpu는 전용 GPU 1장을 요청하는 자원 이름이다. 공유 설정에서 renameByDefault를 true로 두면 공유 자원이 nvidia.com/gpu.shared라는 별도 이름으로 광고되어, 공유 GPU를 요구하는 파드와 전용 GPU를 요구하는 파드를 자원 이름만으로 구분할 수 있다. false면 이름은 그대로 두고 노드의 nvidia.com/gpu.product 레이블에 -SHARED 접미사가 붙는다.

Time-Slicing에서 replicas를 늘리면 메모리도 나뉘나

아니다. Time-Slicing은 CUDA 컨텍스트를 순번으로 전환할 뿐 메모리를 나눠 주지 않는다. 한 파드가 카드 메모리를 전부 잡으면 같은 카드를 공유하던 다른 파드가 OOM으로 실패할 수 있다. replica당 메모리 상한이 필요하면 MPS나 MIG를 써야 한다.

MPS와 Time-Slicing 중 추론 서비스에는 무엇이 맞나

같은 신뢰 경계 안에서 여러 추론 프로세스를 동시에 돌린다면 MPS가 유리하다. 커널을 겹쳐 실행해 처리량을 올리고 클라이언트별 메모리와 연산 몫에 상한을 걸 수 있기 때문이다. 다만 MPS는 하드웨어 격리가 아니라 한 프로세스의 치명적 장애가 다른 프로세스에 영향을 줄 수 있으니, 테넌트가 다르면 MIG를 검토한다.

MIG는 어떤 GPU에서 쓸 수 있나

Ampere 세대 이후(A100, A30, H100 등)에서 지원한다. A100과 H100은 최대 7개, A30은 최대 4개 인스턴스로 나뉜다. T4나 그 이전 세대 카드는 MIG를 지원하지 않으므로 Time-Slicing이나 MPS를 쓴다.

MIG 프로필을 운영 중에 바꿔도 되나

프로필을 바꾸면 GPU가 리셋되므로 해당 노드의 GPU 워크로드가 비워진다. 운영 중에는 노드를 드레인한 뒤 nvidia.com/mig.config 레이블을 변경해야 하고, 변경이 완료될 때까지 그 노드에 새 GPU 파드가 배치되지 않는다.

관련 글

댓글 0

로그인 후 댓글을 남길 수 있습니다.

아직 댓글이 없습니다.