Skip to content
Published on

Kubernetes DRA(Dynamic Resource Allocation)로 GPU 워크로드 스케줄링 최적화 가이드

Authors
  • Name
    Twitter
Kubernetes DRA GPU Scheduling

들어가며

Kubernetes에서 GPU 같은 하드웨어 가속기를 스케줄링하는 것은 오랫동안 운영자들에게 난제였습니다. 기존 Extended Resource 모델은 nvidia.com/gpu: 1처럼 단순한 정수 카운트 방식으로 GPU를 할당했기 때문에, GPU의 세부 속성(VRAM 용량, MIG 파티션, 특정 모델)을 기준으로 스케줄링하는 것이 근본적으로 불가능했습니다.

이 문제를 해결하기 위해 Kubernetes 1.26에서 알파로 도입되고, 1.31에서 대폭 재설계되어 1.32에서 베타로 승격된 **DRA(Dynamic Resource Allocation)**는 GPU/FPGA/네트워크 장치 등 복잡한 하드웨어 리소스를 구조화된 방식으로 요청하고 할당할 수 있는 프레임워크입니다.

기존 Extended Resource 모델의 한계

기존 모델에서 GPU 할당은 다음과 같이 이루어졌습니다:

apiVersion: v1
kind: Pod
metadata:
  name: gpu-training-legacy
spec:
  containers:
    - name: trainer
      image: nvcr.io/nvidia/pytorch:24.01-py3
      resources:
        limits:
          nvidia.com/gpu: 2

이 방식은 몇 가지 근본적인 한계가 있습니다:

  • 속성 기반 선택 불가: A100 80GB와 T4 16GB를 구분할 수 없습니다. 단순히 "GPU 2개"만 요청할 뿐, 어떤 종류의 GPU인지 명시할 방법이 없습니다.
  • 부분 할당 불가: NVIDIA MIG(Multi-Instance GPU) 기술로 A100을 7개의 독립 인스턴스로 분할할 수 있지만, Extended Resource 모델에서는 이를 세밀하게 표현하기 어렵습니다.
  • 디바이스 초기화 제어 부재: GPU를 컨테이너에 전달하기 전에 MPS(Multi-Process Service) 설정이나 특정 드라이버 모드를 적용하는 절차를 표준화할 수 없습니다.
  • 디바이스 간 토폴로지 무시: NVLink로 연결된 GPU 쌍을 함께 할당받는 것이 성능에 중요하지만, 기존 모델은 이를 고려하지 않습니다.

DRA는 이 모든 한계를 해소하여 GPU 워크로드의 스케줄링 품질을 근본적으로 개선합니다. 이 글에서는 DRA의 아키텍처부터 실전 배포, 운영 트러블슈팅까지 체계적으로 다룹니다.

DRA 아키텍처 개요

DRA는 Kubernetes의 resource.k8s.io/v1beta1 (1.32 기준) API 그룹에 속하며, 다음 네 가지 핵심 리소스로 구성됩니다.

핵심 리소스 구조

DeviceClass: 디바이스의 유형을 정의합니다. GPU 모델별로 DeviceClass를 생성하여 워크로드가 특정 GPU 타입을 요청할 수 있게 합니다. 스토리지의 StorageClass와 유사한 역할을 합니다.

ResourceClaim: 실제 디바이스 할당 요청을 나타냅니다. PersistentVolumeClaim이 스토리지를 요청하듯, ResourceClaim은 특정 DeviceClass의 디바이스를 요청합니다. Pod의 라이프사이클과 독립적으로 존재할 수 있어 디바이스를 여러 Pod 간에 공유하거나, Pod 재시작 시에도 동일 디바이스를 유지할 수 있습니다.

ResourceClaimTemplate: Pod 생성 시 자동으로 ResourceClaim을 생성하기 위한 템플릿입니다. Pod마다 전용 ResourceClaim이 필요한 경우에 사용합니다.

ResourceSlice: 노드에 설치된 DRA 드라이버가 API 서버에 보고하는 디바이스 목록입니다. 스케줄러는 ResourceSlice를 참조하여 어떤 노드에 어떤 디바이스가 사용 가능한지 파악합니다.

스케줄링 플로우

DRA 기반 스케줄링은 다음과 같은 단계로 진행됩니다:

  1. Pod 제출: 사용자가 ResourceClaim을 참조하는 Pod를 생성합니다.
  2. 스케줄러 필터링: kube-scheduler가 ResourceSlice 정보를 기반으로 요청된 DeviceClass의 디바이스가 사용 가능한 노드를 필터링합니다.
  3. 구조화된 파라미터 매칭: 스케줄러가 ResourceClaim의 요구 사항과 각 노드의 사용 가능한 디바이스를 직접 매칭합니다. 이것이 DRA의 "Structured Parameters" 모델의 핵심입니다.
  4. 할당 결정: 스케줄러가 특정 노드의 특정 디바이스를 ResourceClaim에 할당합니다.
  5. 디바이스 준비: 해당 노드의 DRA 드라이버(kubelet 플러그인)가 할당된 디바이스를 컨테이너가 사용할 수 있도록 준비합니다 (CDI 디바이스 설정 등).
  6. 컨테이너 시작: kubelet이 준비된 디바이스와 함께 컨테이너를 시작합니다.

기존 Device Plugin 방식과 달리, DRA에서는 스케줄러가 직접 디바이스 속성을 이해하고 최적의 배치를 결정합니다. 이는 Device Plugin이 단순히 "가용 개수"만 보고하던 것과 근본적으로 다른 접근입니다.

DRA 드라이버 설치와 설정

사전 요구사항

DRA를 사용하려면 Kubernetes 1.32 이상이 필요하며, DynamicResourceAllocation 피처 게이트가 활성화되어야 합니다. Kubernetes 1.32에서는 베타 상태이므로 기본적으로 활성화되어 있습니다.

# 클러스터 버전 확인
kubectl version --short

# DRA 피처 게이트 활성화 확인 (kube-apiserver, kube-scheduler, kubelet 모두 필요)
# kubeadm 기반 클러스터의 경우 ClusterConfiguration에서 설정
kubectl get configmap -n kube-system kubeadm-config -o yaml | grep -A 5 "featureGates"

# DRA 관련 API 리소스 확인
kubectl api-resources | grep resource.k8s.io
# 출력 예시:
# deviceclasses              resource.k8s.io/v1beta1   false   DeviceClass
# resourceclaims             resource.k8s.io/v1beta1   true    ResourceClaim
# resourceclaimtemplates     resource.k8s.io/v1beta1   true    ResourceClaimTemplate
# resourceslices             resource.k8s.io/v1beta1   false   ResourceSlice

NVIDIA DRA 드라이버 설치

NVIDIA는 공식 DRA 드라이버인 nvidia-dra-driver를 제공합니다. 기존 k8s-device-plugin과는 별도의 프로젝트이며, DRA의 구조화된 파라미터 모델을 완전히 지원합니다.

# NVIDIA DRA 드라이버 Helm 차트 저장소 추가
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update

# nvidia-dra-driver 설치
# 기존 NVIDIA GPU Operator가 설치되어 있다면 device-plugin은 비활성화해야 합니다
helm install nvidia-dra-driver nvidia/nvidia-dra-driver \
  --namespace nvidia-dra-driver \
  --create-namespace \
  --set controller.enabled=true \
  --set kubeletPlugin.enabled=true \
  --version v0.8.0

# 설치 확인
kubectl get pods -n nvidia-dra-driver
# NAME                                              READY   STATUS    RESTARTS   AGE
# nvidia-dra-driver-controller-7d8f9b6c4d-k2xvn    1/1     Running   0          2m
# nvidia-dra-driver-kubelet-plugin-node1-abcde      1/1     Running   0          2m
# nvidia-dra-driver-kubelet-plugin-node2-fghij      1/1     Running   0          2m

# ResourceSlice 생성 확인 - 드라이버가 노드의 GPU 정보를 보고
kubectl get resourceslices -o wide
# NAME                              DRIVER               NODE    POOL        DEVICES
# gpu-node1-nvidia-gpu-slice-0      gpu.nvidia.com       node1   nvidia-gpu  4
# gpu-node2-nvidia-gpu-slice-0      gpu.nvidia.com       node2   nvidia-gpu  8

ResourceSlice 상세 확인

드라이버가 정상적으로 설치되면, 각 GPU 노드의 디바이스 정보가 ResourceSlice로 보고됩니다. 이를 통해 스케줄러는 각 GPU의 세부 속성을 파악할 수 있습니다.

# 특정 노드의 ResourceSlice 상세 보기
kubectl get resourceslice gpu-node1-nvidia-gpu-slice-0 -o yaml

출력 예시를 보면 각 GPU에 대해 모델명, VRAM, UUID, 아키텍처, MIG 지원 여부 등 풍부한 속성이 보고되는 것을 확인할 수 있습니다. 이러한 속성들이 바로 DeviceClass와 ResourceClaim에서 필터링 조건으로 활용됩니다.

DeviceClass 정의와 GPU 티어 관리

GPU 모델별 DeviceClass 정의

DeviceClass는 StorageClass와 유사하게 디바이스의 "클래스"를 정의합니다. 클러스터 관리자가 미리 정의해두면, 워크로드 개발자는 단순히 DeviceClass 이름만 참조하여 원하는 GPU를 요청할 수 있습니다.

# gpu-deviceclasses.yaml
apiVersion: resource.k8s.io/v1beta1
kind: DeviceClass
metadata:
  name: gpu.nvidia.com-a100
spec:
  selectors:
    - cel:
        expression: "device.driver == 'gpu.nvidia.com' && device.attributes['gpu.nvidia.com'].productName == 'NVIDIA A100 80GB PCIe'"
  config:
    - opaque:
        driver: gpu.nvidia.com
        parameters:
          apiVersion: gpu.nvidia.com/v1alpha1
          kind: GpuConfig
          sharing:
            strategy: TimeSlicing
            timeSlicingConfig:
              interval: Long
---
apiVersion: resource.k8s.io/v1beta1
kind: DeviceClass
metadata:
  name: gpu.nvidia.com-h100
spec:
  selectors:
    - cel:
        expression: "device.driver == 'gpu.nvidia.com' && device.attributes['gpu.nvidia.com'].productName == 'NVIDIA H100 80GB HBM3'"
  config:
    - opaque:
        driver: gpu.nvidia.com
        parameters:
          apiVersion: gpu.nvidia.com/v1alpha1
          kind: GpuConfig
          sharing:
            strategy: TimeSlicing
            timeSlicingConfig:
              interval: Short
---
apiVersion: resource.k8s.io/v1beta1
kind: DeviceClass
metadata:
  name: gpu.nvidia.com-a100-mig-3g20gb
spec:
  selectors:
    - cel:
        expression: >-
          device.driver == 'gpu.nvidia.com' &&
          device.attributes['gpu.nvidia.com'].productName == 'NVIDIA A100 80GB PCIe' &&
          device.attributes['gpu.nvidia.com'].migProfile == '3g.20gb'

위 예시에서 세 가지 DeviceClass를 정의했습니다:

  • gpu.nvidia.com-a100: A100 80GB GPU 전체를 Time-Slicing 모드로 할당
  • gpu.nvidia.com-h100: H100 80GB GPU를 단기 Time-Slicing으로 할당
  • gpu.nvidia.com-a100-mig-3g20gb: A100의 MIG 3g.20gb 프로파일(20GB VRAM, 3개 컴퓨트 슬라이스)을 할당

MIG 파티셔닝 전략

NVIDIA A100/H100에서 MIG를 활용하면 하나의 물리 GPU를 여러 독립 인스턴스로 분할하여 활용도를 극대화할 수 있습니다. DRA에서는 MIG 프로파일별로 DeviceClass를 정의하여 세밀한 GPU 자원 관리가 가능합니다.

MIG 프로파일컴퓨트 슬라이스VRAM최대 인스턴스(A100 기준)주요 용도
1g.5gb1/75GB7개추론(소형 모델), 개발/테스트
1g.10gb1/710GB7개추론(중형 모델)
2g.10gb2/710GB3개소규모 학습, 배치 추론
3g.20gb3/720GB2개중규모 학습, 파인튜닝
4g.40gb4/740GB1개대규모 학습
7g.80gb7/780GB1개전체 GPU (MIG 미사용과 동일)

A100 vs H100 스펙 비교

DeviceClass를 설계할 때 GPU 모델의 특성을 정확히 이해하는 것이 중요합니다.

항목NVIDIA A100 80GBNVIDIA H100 80GB
아키텍처AmpereHopper
FP16 성능312 TFLOPS989 TFLOPS
FP8 성능지원 안 함1,979 TFLOPS
VRAM80GB HBM2e80GB HBM3
메모리 대역폭2 TB/s3.35 TB/s
NVLink 대역폭600 GB/s900 GB/s
MIG 최대 인스턴스7개7개
TDP300W700W
DRA 드라이버 지원nvidia-dra-driver v0.6+nvidia-dra-driver v0.7+

H100은 FP8 연산과 Transformer Engine을 통해 LLM 학습/추론 성능이 A100 대비 3배 이상 향상되므로, LLM 워크로드에는 H100 DeviceClass를 우선 할당하는 정책을 수립하는 것이 좋습니다.

ResourceClaim 기반 Pod 스케줄링

기본 ResourceClaim 사용

ResourceClaim을 직접 생성하고 Pod에서 참조하는 방식입니다. 디바이스를 Pod 라이프사이클과 독립적으로 관리하거나, 여러 Pod에서 공유해야 할 때 사용합니다.

# 독립적인 ResourceClaim 생성
apiVersion: resource.k8s.io/v1beta1
kind: ResourceClaim
metadata:
  name: training-gpu-claim
  namespace: ml-workloads
spec:
  devices:
    requests:
      - name: gpu
        deviceClassName: gpu.nvidia.com-a100
        count: 4
    constraints:
      - requests: ['gpu']
        matchAttribute: 'gpu.nvidia.com/nvlinkInterconnect'
---
# ResourceClaim을 참조하는 Pod
apiVersion: v1
kind: Pod
metadata:
  name: distributed-training
  namespace: ml-workloads
spec:
  containers:
    - name: trainer
      image: nvcr.io/nvidia/pytorch:24.01-py3
      command: ['torchrun', '--nproc_per_node=4', 'train.py']
      resources:
        claims:
          - name: training-gpus
  resourceClaims:
    - name: training-gpus
      resourceClaimName: training-gpu-claim
  restartPolicy: Never

위 예시에서 주목할 점은 constraints 필드입니다. matchAttribute를 사용하여 4개의 A100 GPU가 NVLink로 상호 연결된 상태로 할당되도록 제약 조건을 설정했습니다. 이는 분산 학습 시 GPU 간 통신 성능에 결정적인 영향을 미칩니다.

ResourceClaimTemplate 사용

Job이나 Deployment처럼 여러 Pod를 생성하는 워크로드에서는 ResourceClaimTemplate을 사용하여 각 Pod마다 전용 ResourceClaim이 자동 생성되도록 합니다.

# MIG 기반 추론 서비스 배포
apiVersion: apps/v1
kind: Deployment
metadata:
  name: llm-inference-service
  namespace: ml-workloads
spec:
  replicas: 6
  selector:
    matchLabels:
      app: llm-inference
  template:
    metadata:
      labels:
        app: llm-inference
    spec:
      containers:
        - name: inference-server
          image: nvcr.io/nvidia/tritonserver:24.01-py3
          ports:
            - containerPort: 8000
              name: http
            - containerPort: 8001
              name: grpc
          resources:
            claims:
              - name: inference-gpu
      resourceClaims:
        - name: inference-gpu
          resourceClaimTemplateName: mig-inference-template
---
apiVersion: resource.k8s.io/v1beta1
kind: ResourceClaimTemplate
metadata:
  name: mig-inference-template
  namespace: ml-workloads
spec:
  spec:
    devices:
      requests:
        - name: mig-gpu
          deviceClassName: gpu.nvidia.com-a100-mig-3g20gb
          count: 1

이 구성에서는 6개의 Triton Inference Server 레플리카가 각각 A100의 MIG 3g.20gb 슬라이스 1개를 할당받습니다. 물리 A100 2장으로 6개의 추론 인스턴스를 운영할 수 있어, 기존 Extended Resource 모델에서 GPU 2장을 통째로 할당해야 했던 것에 비해 자원 활용률이 크게 개선됩니다.

인라인 디바이스 요청

간단한 경우에는 별도의 ResourceClaim이나 ResourceClaimTemplate을 만들지 않고, Pod 스펙에서 직접 디바이스를 요청할 수도 있습니다.

apiVersion: v1
kind: Pod
metadata:
  name: quick-gpu-job
  namespace: ml-workloads
spec:
  containers:
    - name: compute
      image: nvcr.io/nvidia/cuda:12.3.1-runtime-ubuntu22.04
      command: ['python3', 'benchmark.py']
      resources:
        claims:
          - name: gpu-req
  resourceClaims:
    - name: gpu-req
      resourceClaimTemplateName: ''
      source:
        devices:
          requests:
            - name: gpu
              deviceClassName: gpu.nvidia.com-h100
              count: 1
  restartPolicy: Never

멀티 클라우드 DRA 비교 (AKS vs GKE vs EKS)

각 클라우드 프로바이더별 DRA 지원 현황과 GPU 인스턴스 옵션을 비교합니다.

항목AKS (Azure)GKE (Google)EKS (AWS)
Kubernetes 최소 버전1.31+ (Preview)1.32+ (Preview)1.32+ (Preview)
DRA 피처 게이트수동 활성화 필요GKE 채널별 자동 활성화EKS 애드온으로 관리
GPU 인스턴스 (A100)NC A100 v4a2-highgpu / a3-highgpup4d.24xlarge
GPU 인스턴스 (H100)ND H100 v5a3-ultragpu-8gp5.48xlarge
NVIDIA DRA 드라이버Helm 수동 설치GKE GPU Operator 통합EKS NVIDIA 애드온
MIG 지원지원 (수동 구성)지원 (GKE MIG 관리자)지원 (수동 구성)
노드 오토스케일링 연동Karpenter / Cluster AutoscalerNAP / KarpenterKarpenter
가격 (A100 80GB, 시간당)~$3.67~$3.67~$32.77 (8GPU 전체)
주요 제한사항Preview 기능, SLA 미보장Rapid 채널만 지원특정 리전만 가용

클라우드별 설정 차이점

GKE에서는 GPU 노드 풀 생성 시 DRA를 활성화할 수 있습니다:

# GKE에서 DRA 지원 GPU 노드 풀 생성
gcloud container node-pools create gpu-pool-h100 \
  --cluster=ml-cluster \
  --zone=us-central1-c \
  --machine-type=a3-highgpu-8g \
  --accelerator=type=nvidia-h100-80gb,count=8 \
  --num-nodes=2 \
  --enable-autoscaling \
  --min-nodes=0 \
  --max-nodes=4 \
  --node-labels="gpu-type=h100" \
  --metadata="install-nvidia-driver=True"

# DRA 피처 게이트 활성화 (GKE Rapid 채널)
gcloud container clusters update ml-cluster \
  --zone=us-central1-c \
  --release-channel=rapid \
  --enable-kubernetes-unstable-apis=resource.k8s.io/v1beta1

EKS에서는 EKS 매니지드 애드온을 통해 DRA 드라이버를 관리합니다:

# EKS 클러스터에 NVIDIA DRA 드라이버 애드온 설치
aws eks create-addon \
  --cluster-name ml-cluster \
  --addon-name nvidia-dra-driver \
  --addon-version v0.8.0-eksbuild.1 \
  --region us-east-1

# GPU 노드 그룹 생성 (Karpenter NodePool)
cat <<EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-h100-pool
spec:
  template:
    spec:
      requirements:
        - key: "node.kubernetes.io/instance-type"
          operator: In
          values: ["p5.48xlarge"]
        - key: "karpenter.sh/capacity-type"
          operator: In
          values: ["on-demand"]
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: gpu-nodes
  limits:
    cpu: "1000"
    memory: 4000Gi
    nvidia.com/gpu: "64"
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 30m
EOF

각 클라우드 프로바이더마다 DRA의 안정성 수준과 통합 깊이가 다르므로, 프로덕션 배포 전에 반드시 해당 프로바이더의 DRA 지원 문서를 확인하고, 가능하면 Preview/Beta 기능에 대한 별도의 지원 계약을 검토해야 합니다.

기존 Extended Resource 모델에서 DRA로 마이그레이션

기존 Extended Resource 기반 GPU 할당에서 DRA로 마이그레이션하는 것은 클러스터 전체에 영향을 미치는 작업이므로 단계적으로 진행해야 합니다.

마이그레이션 단계

1단계 - 평가와 인벤토리 (1~2주)

현재 클러스터의 GPU 사용 현황을 파악합니다.

# 현재 Extended Resource 방식으로 GPU를 사용하는 모든 Pod 조회
kubectl get pods --all-namespaces -o json | \
  jq -r '.items[] |
    select(.spec.containers[].resources.limits["nvidia.com/gpu"] != null) |
    [.metadata.namespace, .metadata.name,
     (.spec.containers[].resources.limits["nvidia.com/gpu"] // "0")] |
    @tsv' | \
  column -t -s $'\t'

# 노드별 GPU 할당 현황
kubectl get nodes -l nvidia.com/gpu.present=true -o json | \
  jq -r '.items[] |
    [.metadata.name,
     .status.capacity["nvidia.com/gpu"],
     .status.allocatable["nvidia.com/gpu"]] |
    @tsv' | \
  column -t -s $'\t' -N "NODE,CAPACITY,ALLOCATABLE"

2단계 - DRA 인프라 준비 (1주)

  1. Kubernetes 버전을 1.32 이상으로 업그레이드합니다.
  2. DRA 피처 게이트가 활성화되었는지 확인합니다.
  3. NVIDIA DRA 드라이버를 설치합니다.
  4. 기존 NVIDIA Device Plugin은 아직 제거하지 않습니다 (공존 가능).

3단계 - DeviceClass 정의 (1~2일)

클러스터에 존재하는 GPU 모델별로 DeviceClass를 생성합니다. 앞서 설명한 YAML 예시를 참고하여, 운영 환경의 GPU 인벤토리에 맞게 DeviceClass를 정의합니다.

4단계 - 파일럿 워크로드 전환 (2~4주)

비핵심 워크로드부터 DRA 방식으로 전환합니다. 개발/스테이징 환경에서 먼저 검증한 후, 프로덕션의 낮은 우선순위 워크로드로 확장합니다.

5단계 - 전면 전환 (2~4주)

모든 GPU 워크로드를 DRA로 전환하고, 기존 NVIDIA Device Plugin을 제거합니다. 이 단계에서는 롤백 계획을 반드시 준비해야 합니다.

마이그레이션 시 주의사항

  • 공존 기간: DRA 드라이버와 기존 Device Plugin은 동시에 운영할 수 있지만, 동일 Pod에서 두 방식을 혼용하면 안 됩니다. 하나의 Pod는 resources.limits의 Extended Resource 방식이나 resourceClaims의 DRA 방식 중 하나만 사용해야 합니다.
  • RBAC 업데이트: DRA 리소스(resourceclaims, resourceclaimtemplates, deviceclasses)에 대한 RBAC 권한을 관련 서비스 어카운트에 부여해야 합니다.
  • 모니터링 재구성: 기존에 nvidia.com/gpu 메트릭을 기반으로 한 대시보드와 알림을 DRA 기반 메트릭으로 업데이트해야 합니다.

운영 시 주의사항과 모니터링

용량 계획 (Capacity Planning)

DRA 환경에서의 GPU 용량 계획은 기존보다 세밀해집니다. MIG를 활용하는 경우 물리 GPU 수뿐만 아니라 MIG 프로파일 조합도 고려해야 합니다.

권장 용량 계획 원칙:

  • 물리 GPU당 MIG 프로파일 혼합 금지: 하나의 A100에서 1g.5gb와 3g.20gb를 동시에 구성하면 관리 복잡도가 급증합니다. 노드 단위로 동일한 MIG 프로파일을 적용하는 것을 권장합니다.
  • 오버프로비저닝 비율: 학습 워크로드는 1015%, 추론 워크로드는 2030%의 여유 용량을 확보하세요. DRA에서는 디바이스 속성 기반 스케줄링이므로 단순 GPU 개수가 아닌 DeviceClass별 가용량을 기준으로 계획합니다.
  • 노드 장애 대비: GPU 노드 장애 시 해당 노드의 모든 ResourceClaim이 영향을 받습니다. 최소 N+1 이상의 노드 여유를 확보하세요.

모니터링 구성

DRA 환경에서는 다음 메트릭들을 모니터링해야 합니다:

# ResourceClaim 상태 모니터링
kubectl get resourceclaims --all-namespaces -o custom-columns=\
  'NAMESPACE:.metadata.namespace,'\
  'NAME:.metadata.name,'\
  'DEVICECLASS:.spec.devices.requests[0].deviceClassName,'\
  'ALLOCATED:.status.allocation.devices.results[0].device'

# Pending 상태의 ResourceClaim 확인 (할당 실패 감지)
kubectl get resourceclaims --all-namespaces \
  --field-selector="status.allocation=" \
  -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,AGE:.metadata.creationTimestamp'

# DeviceClass별 사용률 확인
kubectl get resourceslices -o json | \
  jq -r '[.items[].spec.devices[] |
    {driver: .basic.attributes["gpu.nvidia.com"].productName.stringValue}] |
    group_by(.driver) |
    map({gpu_model: .[0].driver, total: length}) |
    .[] | [.gpu_model, .total] | @tsv'

Prometheus 메트릭 수집

NVIDIA DRA 드라이버는 Prometheus 메트릭을 노출합니다. 다음과 같은 주요 메트릭을 모니터링 대시보드에 포함하세요:

메트릭 이름설명알림 임계값
dra_resource_claims_total전체 ResourceClaim 수-
dra_resource_claims_pending대기 중인 ResourceClaim 수5분 이상 Pending 시 경고
dra_resource_claims_allocated할당 완료된 ResourceClaim 수-
dra_devices_availableDeviceClass별 가용 디바이스 수가용률 10% 미만 시 경고
dra_devices_allocated할당된 디바이스 수-
dra_allocation_duration_seconds할당 소요 시간p99가 30초 초과 시 경고
dra_plugin_errors_total드라이버 오류 횟수1분 내 5회 이상 시 긴급

실패 사례와 복구 절차

사례 1: ResourceClaim이 영구적으로 Pending 상태

증상: Pod가 Pending 상태에서 벗어나지 않고, kubectl describe pod에서 "waiting for ResourceClaim to be allocated" 메시지가 표시됩니다.

원인 분석:

  • 요청한 DeviceClass에 해당하는 가용 디바이스가 없음
  • DeviceClass의 CEL 표현식이 잘못되어 어떤 디바이스도 매칭되지 않음
  • DRA 드라이버의 kubelet 플러그인이 비정상 상태

복구 절차:

# 1. ResourceClaim 상태 확인
kubectl describe resourceclaim training-gpu-claim -n ml-workloads

# 2. 요청한 DeviceClass와 매칭되는 디바이스 존재 여부 확인
kubectl get resourceslices -o json | \
  jq '.items[].spec.devices[] |
    select(.basic.attributes["gpu.nvidia.com"].productName.stringValue == "NVIDIA A100 80GB PCIe")'

# 3. DRA 드라이버 상태 확인
kubectl get pods -n nvidia-dra-driver
kubectl logs -n nvidia-dra-driver -l app=nvidia-dra-driver-kubelet-plugin --tail=50

# 4. 스케줄러 로그에서 DRA 관련 오류 확인
kubectl logs -n kube-system -l component=kube-scheduler --tail=100 | grep -i "dra\|resourceclaim\|deviceclass"

# 5. 필요 시 ResourceClaim 삭제 후 재생성
kubectl delete resourceclaim training-gpu-claim -n ml-workloads
kubectl apply -f training-gpu-claim.yaml

사례 2: 노드 장애 시 GPU 디바이스 누수(Leak)

증상: 노드가 NotReady 상태가 된 후 복구되었지만, 해당 노드의 GPU가 ResourceSlice에서는 "할당됨"으로 표시되어 새로운 Pod에 할당되지 않습니다.

원인: 노드 장애로 DRA 드라이버의 kubelet 플러그인이 비정상 종료되면서 디바이스 해제 절차가 완료되지 않았습니다.

복구 절차:

  1. 해당 노드에서 실행 중이던 Pod의 ResourceClaim이 아직 존재하는지 확인합니다.
  2. 해당 Pod가 삭제되었다면 ResourceClaim도 함께 삭제되어야 하지만 (소유자 참조가 있는 경우), 그렇지 않으면 수동으로 삭제합니다.
  3. DRA 드라이버 kubelet 플러그인을 재시작합니다.
# 해당 노드의 DRA 드라이버 플러그인 Pod 재시작
kubectl delete pod -n nvidia-dra-driver -l app=nvidia-dra-driver-kubelet-plugin \
  --field-selector spec.nodeName=problematic-node

# ResourceSlice가 올바르게 업데이트되었는지 확인 (재시작 후 30초 대기)
sleep 30
kubectl get resourceslices --field-selector spec.nodeName=problematic-node -o yaml

사례 3: DRA 드라이버 업그레이드 중 기존 워크로드 중단

증상: DRA 드라이버를 Helm으로 업그레이드하는 과정에서 kubelet 플러그인 DaemonSet의 Pod가 재시작되면서, 해당 노드에서 실행 중이던 GPU 워크로드가 디바이스 접근 오류를 발생시킵니다.

예방 조치:

  • DRA 드라이버 업그레이드 전에 GPU 워크로드를 다른 노드로 이전(drain)합니다.
  • 롤링 업데이트 전략을 maxUnavailable: 1로 설정하여 한 번에 하나의 노드에서만 드라이버가 재시작되도록 합니다.
  • 학습 워크로드의 경우 체크포인팅을 활성화하여 드라이버 재시작 시에도 학습 진행 상황을 보존합니다.

사례 4: CEL 표현식 오류로 DeviceClass 매칭 실패

증상: DeviceClass를 생성했지만 ResourceClaim이 할당되지 않습니다. kubectl describe 결과 매칭되는 디바이스가 없다고 표시됩니다.

원인: DeviceClass의 selectors.cel.expression에서 속성 이름이 잘못되었거나, 비교 값이 실제 디바이스가 보고하는 값과 다릅니다.

디버깅 방법:

# 실제 디바이스가 보고하는 속성 이름과 값 확인
kubectl get resourceslices -o json | \
  jq '.items[0].spec.devices[0].basic.attributes'

# 출력 예시:
# {
#   "gpu.nvidia.com": {
#     "driverVersion": {"stringValue": "550.54.15"},
#     "productName": {"stringValue": "NVIDIA A100 80GB PCIe"},
#     "architecture": {"stringValue": "Ampere"},
#     "cudaComputeCapability": {"versionValue": "8.0"},
#     "memory": {"quantityValue": "80Gi"}
#   }
# }
# DeviceClass의 CEL 표현식에서 사용하는 속성 이름이 위 출력과 정확히 일치하는지 확인합니다.

사례 5: ResourceClaim 쿼터 초과

증상: 네임스페이스의 ResourceQuota에 의해 ResourceClaim 생성이 거부됩니다.

DRA 환경에서는 네임스페이스별 ResourceClaim 수 제한을 설정할 수 있습니다. 특히 ResourceClaimTemplate을 사용하는 Deployment의 레플리카가 많으면 예상보다 빠르게 쿼터에 도달할 수 있으므로 주의가 필요합니다.

프로덕션 배포 체크리스트

DRA 기반 GPU 워크로드를 프로덕션에 배포하기 전에 다음 체크리스트를 확인하세요.

인프라 준비

  • Kubernetes 1.32 이상으로 업그레이드 완료
  • DynamicResourceAllocation 피처 게이트가 kube-apiserver, kube-scheduler, kubelet에서 활성화됨
  • NVIDIA DRA 드라이버가 모든 GPU 노드에 설치되고 정상 동작함
  • ResourceSlice가 각 노드의 GPU 정보를 정확히 보고함

DeviceClass 설계

  • 클러스터의 모든 GPU 모델에 대해 DeviceClass가 정의됨
  • MIG 프로파일별 DeviceClass가 필요한 경우 정의됨
  • DeviceClass의 CEL 표현식이 실제 디바이스 속성과 정확히 매칭됨 (테스트 ResourceClaim으로 검증)

워크로드 구성

  • Pod 스펙에서 resourceClaims가 올바르게 참조됨
  • ResourceClaimTemplate이 Deployment/Job 워크로드에 맞게 구성됨
  • GPU 토폴로지 제약(NVLink 등)이 필요한 워크로드에 constraints가 설정됨

RBAC과 보안

  • 네임스페이스별 ResourceClaim 생성 권한이 적절히 설정됨
  • DeviceClass는 클러스터 범위 리소스이므로 관리자만 생성/수정할 수 있도록 제한됨
  • ResourceQuota로 네임스페이스별 ResourceClaim 수 제한이 설정됨

모니터링과 알림

  • DRA 관련 Prometheus 메트릭 수집이 구성됨
  • Pending ResourceClaim에 대한 알림이 설정됨 (5분 이상 Pending 시)
  • DRA 드라이버 오류에 대한 알림이 설정됨
  • GPU 사용률과 DeviceClass별 가용량 대시보드가 구성됨

장애 대응

  • 노드 장애 시 ResourceClaim 복구 절차가 문서화됨
  • DRA 드라이버 업그레이드 절차와 롤백 계획이 수립됨
  • GPU 워크로드 체크포인팅이 활성화됨 (학습 워크로드)
  • 기존 Extended Resource 모델로의 롤백 계획이 준비됨 (마이그레이션 기간 중)

성능 검증

  • 디바이스 할당 지연시간이 허용 범위 내인지 확인 (p99 기준 30초 이내)
  • 스케줄러의 DRA 관련 처리량이 워크로드 규모에 충분한지 확인
  • MIG 환경에서 각 슬라이스의 격리 성능이 검증됨

참고자료