요청서가 장치를 고른다
한 줄 요약
장치 플러그인은 「GPU 몇 개」 만 말할 수 있습니다. DRA(Dynamic Resource Allocation)는 드라이버가 장치 하나하나를 속성과 함께 「ResourceSlice」 로 공개하고, 사용자가 「이런 장치를 몇 개」 라는 「요청서(ResourceClaim)」 를 쓰면 스케줄러가 직접 장치를 골라 그 요청서에 적어 줍니다. 개수 대신 장치를 다루게 되면서 고르기·나눠 쓰기·여러 장치 함께 받기가 API 안으로 들어왔습니다.
왜 이게 필요했나
장치 플러그인 시대의 우회로를 떠올리면 이유가 보입니다.
- 「고르기」: 「메모리 80GiB 짜리 카드」 를 원하면 노드에 모델 라벨을 붙이고 nodeSelector 로 노드를 골랐습니다. 노드 하나에 서로 다른 카드가 섞이면 이 방법은 무너집니다. 라벨은 노드의 속성이지 카드의 속성이 아니기 때문입니다.
- 「나눠 쓰기」: 한 카드를 두 파드가 쓰게 하려고 타임슬라이싱이 광고 수를 부풀렸습니다. 스케줄러는 「4장」 이라고 믿지만 실제로는 한 장입니다. 숫자가 거짓말을 시작하면 장부를 믿을 수 없습니다.
- 「함께 받기」: GPU 와 같은 PCIe 스위치 아래의 NIC 를 함께 받고 싶어도, 서로 다른 장치 플러그인은 서로를 모릅니다.
- 「설정 전달」: 파드마다 장치 설정을 다르게 주려면 주석에 문자열을 넣고 드라이버가 그것을 읽는 식의 약속이 필요했습니다.
DRA 는 이 넷을 API 객체로 옮깁니다. 공식 문서는 핵심 기능을 v1.35 부터 안정(Stable)으로 적고, 우리 실험 VM(k3s v1.36.5)에서는 resource.k8s.io/v1 이 기본으로 켜져 있었습니다.
어떻게 동작하나
등장인물은 넷입니다.
ResourceSlice 드라이버가 노드(또는 풀)마다 공개하는 장치 목록. 장치마다 속성(attributes)과 용량(capacity)
DeviceClass 관리자가 정하는 「장치의 종류」. CEL 선택식과 공통 설정을 담는다
ResourceClaim 사용자의 요청서. 「이 DeviceClass 에서, 이 CEL 조건으로, 몇 개」
ResourceClaimTemplate 파드마다 새 요청서를 찍어 내는 틀. 파드가 지워지면 찍어 낸 요청서도 지워진다
흐름은 이렇습니다. 스케줄러가 파드를 볼 때 요청서를 함께 읽고, 각 노드의 ResourceSlice 에서 조건에 맞는 장치를 찾아 「할당 결과를 요청서의 status 에 적습니다.」 그 노드의 kubelet 은 드라이버에게 「이 요청서를 준비하라」 고 부르고, 드라이버는 CDI 이름으로 컨테이너에 장치를 넣습니다. 장치 플러그인과 달리 결정은 스케줄러 안에서 끝나고, 결과는 누구나 읽을 수 있는 객체로 남습니다.
이 실습에 쓰는 dra-example-driver(판 0.5.0)는 노드마다 가짜 장치 gpu-0 부터 gpu-7 까지 8개를 공개합니다. 실측한 장치 하나는 이렇게 생겼습니다.
name: gpu-0
attributes: driverVersion=1.0.0, index=0, model=LATEST-GPU-MODEL, uuid=gpu-5739…
capacity: compute=100, memory=80Gi
CEL 로는 device.attributes['gpu.example.com'].index == 7 처럼 장치 하나를 정확히 고를 수 있습니다. 같은 요청서를 두 파드가 가리키면 두 파드는 「같은 장치를 함께」 씁니다(공유가 숫자 부풀리기가 아니라 명시적인 선언이 됩니다). count: 2 는 장치 둘을 한 요청서로 받습니다.
판에 따라 켜진 기능이 다릅니다. 실험 VM 의 API 서버 지표 kubernetes_feature_enabled 로 확인한 v1.36.5 의 상태입니다.
켜져 있음(안정) DynamicResourceAllocation · DRAPrioritizedList · DRAAdminAccess
켜져 있음(베타) DRAExtendedResource · DRAPartitionableDevices · DRAConsumableCapacity · DRADeviceTaints
꺼져 있음(알파) DRAListTypeAttributes · DRANodeAllocatableResources · DRAWorkloadResourceClaims
DRAExtendedResource 덕분에 예전처럼 resources.limits 에 적어도 DRA 장치를 받을 수 있습니다. 실측에서 deviceclass.resource.kubernetes.io/gpu.example.com: 1 로 요청한 파드는 이름이 …-extended-resources-… 인 요청서가 자동으로 만들어져 장치 하나를 받았습니다. MIG 처럼 카드를 쪼개는 일은 DRAPartitionableDevices 가 공유 카운터로 표현합니다.
현장에서 만나는 모습
- NVIDIA 의 DRA 드라이버는
kubernetes-sigs/dra-driver-nvidia-gpu로 옮겨 갔습니다. DeviceClass 이름은gpu.nvidia.com이고, 여러 노드의 NVLink 도메인을 묶는 ComputeDomain 도 같은 틀로 다룹니다. fake-gpu-operator 도draPlugin.enabled=true로 같은 이름의 가짜 장치를 공개합니다. - 장치 플러그인과 DRA 는 한동안 함께 삽니다. Kueue 는 DRA 요청서의 장치 수를 쿼터로 셀 수 있고, KAI-Scheduler 도 DRA 를 지원합니다. 다만 KAI 의 GPU 쪼개기는 장치 플러그인 경로에서만 된다는 것이 fake-gpu-operator 시험 문서의 설명입니다(미실측).
- GPU 공유의 세 방식(타임슬라이싱·MPS·MIG)은 GPU Operator 와 타임슬라이싱 코스의 「한 장을 여럿이 쓴다는 말의 뜻」 모듈에 정리되어 있습니다. 여기서는 그 공유를 「요청서를 함께 가리킨다」 는 API 로 표현하는 쪽을 봅니다.
- 이 드라이버의 다음 판에서는 드라이버 이름이 바뀌는 변경(PR 289)이 열려 있습니다. 실습은 판을 0.5.0 로 고정했습니다.
English corner
With DRA you no longer ask how many; you describe which one.
claim(요청서), slice(조각), allocation(할당) 세 단어로 이 API 를 읽을 수 있습니다.
다음 실습에서 할 것
ResourceSlice 와 DeviceClass 를 읽고, 틀로 요청서를 찍어 파드에 장치를 줍니다. CEL 로 장치를 하나 고르고, 요청서 하나를 두 파드가 함께 쓰고, 장치 둘을 한 번에 받은 뒤, 남은 장치보다 많이 요청해 Pending 을 만들고 장부를 계산합니다.