DRA 기능
DRA 기능 (DRA Features)
이 페이지는 고급 사용 사례를 위한 선택적(optional) DRA 기능들을 다룹니다. 이 기능 중 일부는 DRA 드라이버의 지원이 필요해요. 각 기능은 성숙도(maturity)와 이를 활성화하는 기능 게이트(feature gate)를 함께 표시하고 있으니 참고하세요.
분할 가능한 디바이스 (Partitionable devices)
기능 상태: Kubernetes v1.36부터 Beta; 기본 활성화
DRA에서 표현되는 디바이스가 반드시 단일 머신에 연결된 단일 단위일 필요는 없어요. 여러 머신에 연결된 여러 디바이스로 구성된 논리적 디바이스일 수도 있습니다. 이런 디바이스는 하부 물리 디바이스의 리소스를 겹쳐서 소비할 수 있어요. 즉, 하나의 논리 디바이스가 할당되면 다른 디바이스는 더 이상 사용할 수 없게 됩니다.
ResourceSlice API에서는 이를 명명된 CounterSet 목록(각각은 명명된 카운터 집합을 포함)으로 표현해요. 카운터는 DRA를 통해 광고되는 논리 디바이스가 사용하는 물리 디바이스에서 사용 가능한 리소스를 나타냅니다.
논리 디바이스는 ConsumesCounters 목록을 지정할 수 있어요. 각 항목은 CounterSet에 대한 참조와, 소비할 양을 가진 명명된 카운터 집합을 포함합니다. 따라서 디바이스가 할당 가능하려면 참조된 CounterSet이 디바이스가 참조하는 카운터에 대해 충분한 수량을 가져야 해요.
CounterSet은 디바이스와 별도의 ResourceSlice에 지정해야 합니다. 디바이스는 디바이스와 같은 리소스 풀에 정의된 모든 CounterSet의 카운터를 소비할 수 있어요.
다음은 8Gi 메모리의 공유 카운터에서 각각 6Gi 메모리를 소비하는 두 디바이스의 예시예요. 따라서 어느 시점이든 두 디바이스 중 하나만 할당될 수 있어요. 스케줄러가 이를 처리하며, ResourceClaim API는 영향을 받지 않으므로 소비자에게는 투명합니다.
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: resourceslice-with-countersets
spec:
nodeName: worker-1
pool:
name: pool
generation: 1
resourceSliceCount: 2
driver: dra.example.com
sharedCounters:
- name: gpu-1-counters
counters:
memory:
value: 8Gi
---
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: resourceslice-with-devices
spec:
nodeName: worker-1
pool:
name: pool
generation: 1
resourceSliceCount: 2
driver: dra.example.com
devices:
- name: device-1
consumesCounters:
- counterSet: gpu-1-counters
counters:
memory:
value: 6Gi
- name: device-2
consumesCounters:
- counterSet: gpu-1-counters
counters:
memory:
value: 6Gi
분할 가능한 디바이스는 kube-apiserver와 kube-scheduler의 DRAPartitionableDevices 기능 게이트로 제어됩니다.
디바이스 호환성 그룹 (Device compatibility groups)
기능 상태: Kubernetes v1.37부터 Alpha; 기본 비활성화
디바이스 호환성 그룹은 DRA 드라이버가 어떤 분할 디바이스가 같은 물리 하드웨어에 함께 할당(co-allocate)될 수 있는지 선언하게 해 줍니다. 이 기능이 없으면 호환되지 않는 디바이스 조합은 kubelet이 노드에서 팟을 준비할 때에만 감지되어 준비가 실패해요. 호환성 그룹을 사용하면 스케줄러가 스케줄링 시점에 노드 측 작업이 시작되기 전에 호환되지 않는 조합을 거부합니다.
이 기능은 상호 배타적인 운영 모드를 지원하는 하드웨어에 가장 유용해요. 예를 들어 MIG 모드나 vGPU 모드 중 하나로 실행될 수 있는 GPU가 있어요: MIG 모드의 디바이스와 vGPU 모드의 디바이스는 겹치는 물리 리소스를 호환되지 않는 방식으로 소비하므로 함께 할당될 수 없습니다. 드라이버가 compatibilityGroups를 선언하면 이 제약이 스케줄러에 보이게 됩니다.
이 기능은 분할 가능한 디바이스 위에 구축됩니다: compatibilityGroups 필드는 분할 가능한 디바이스에만 존재하는 device.consumesCounters[] 항목에 있습니다. DRADeviceCompatibilityGroups와 DRAPartitionableDevices 기능 게이트가 모두 kube-apiserver와 kube-scheduler에서 활성화되어야 해요.
동작 방식 (How it works)
드라이버는 ResourceSlice의 각 device.consumesCounters[] 항목에 대해 compatibilityGroups 목록을 정의해요. 목록에는 해당 특정 카운터 세트에서 디바이스의 운영 모드 또는 파티션 유형을 나타내는 최대 2개의 불투명한 문자열 이름이 포함됩니다.
같은 카운터 세트에서 리소스를 가져오는 여러 디바이스를 스케줄러가 할당할 때, compatibilityGroups의 교집합을 계산해요. 교집합이 비어 있지 않아야만 할당이 성공합니다 — 즉, 함께 할당되는 모든 디바이스가 최소 하나의 공통 그룹 이름을 공유해야 합니다. 다른 카운터 세트에서 리소스를 가져오는 디바이스는 서로 비교되지 않아요.
그룹을 선언하지 않은 디바이스(unset, nil, 빈 목록)는 특수한 경우로 처리됩니다: 같은 카운터 세트에서 다른 그룹 없는 디바이스와만 함께 할당 가능합니다. 하나 이상의 그룹을 선언한 디바이스와는 절대 함께 할당될 수 없어요.
이 제약은 단일 스케줄링 주기에서 할당되는 모든 클레임에 적용됩니다: 두 클레임이 각각 같은 카운터 세트에서 디바이스를 할당한다면, 클레임 간 그룹 교집합도 적용됩니다.
예시 (Example)
MIG 모드 또는 vGPU 모드로 작동할 수 있는 GPU를 생각해 보세요. 드라이버가 8Gi 공유 메모리 카운터에서 각각 4GiB를 소비하는 두 디바이스를 공개합니다. 카운터 용량만으로는 두 디바이스를 함께 할당할 수 있어요. 각 디바이스는 운영 모드를 호환성 그룹으로 선언해 두 모드를 상호 배타적으로 만듭니다:
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: gpu-counters
spec:
nodeName: worker-1
pool:
name: gpu-pool
generation: 1
resourceSliceCount: 2
driver: gpu.example.com
sharedCounters:
- name: gpu-0-memory
counters:
memory:
value: 8Gi
---
apiVersion: resource.k8s.io/v1
kind: ResourceSlice
metadata:
name: gpu-devices
spec:
nodeName: worker-1
pool:
name: gpu-pool
generation: 1
resourceSliceCount: 2
driver: gpu.example.com
devices:
- name: gpu-0-mig
consumesCounters:
- counterSet: gpu-0-memory
counters:
memory:
value: 4Gi
compatibilityGroups:
- mig
- name: gpu-0-vgpu
consumesCounters:
- counterSet: gpu-0-memory
counters:
memory:
value: 4Gi
compatibilityGroups:
- vgpu
이 예시에서:
gpu-0-mig는mig그룹에 속해요.gpu-0-vgpu는vgpu그룹에 속합니다.
팟 또는 PodGroup이 이 풀에서 두 디바이스를 요청하면, 스케줄러는 gpu-0-memory 카운터 세트에서 선택된 두 디바이스가 공통 호환성 그룹을 공유하는지 확인해요. {"mig"} ∩ {"vgpu"} = ∅이므로, 카운터 세트에 두 디바이스를 위한 충분한 메모리가 있음에도 불구하고 그 조합은 거부됩니다. 두 요청 모두 그러한 조합이 존재하는 풀에서 두 MIG 디바이스(또는 두 vGPU 디바이스)로만 충족될 수 있어요.
제약 조건 (Constraints)
- 각
consumesCounters[]항목은 최대 2개의 그룹 이름을 선언할 수 있어요. - 그룹 이름은 단일 항목 내에서 고유해야 합니다.
- 그룹 이름은 쿠버네티스에 불투명하며, 게시 드라이버의 풀 내에서만 의미가 있어요.
- 그룹은 카운터 세트별로 비교됩니다: 한 카운터 세트의 그룹은 다른 카운터 세트의 공동 할당 결정에 영향을 주지 않습니다.
버전 차이 안전성 (Version-skew safety)
DRADeviceCompatibilityGroups 기능 게이트가 비활성화되면(alpha의 기본값), kube-apiserver는 기존 객체에 이미 필드가 설정된 경우를 제외하고 새로 생성되거나 갱신된 ResourceSlice에서 compatibilityGroups 필드를 제거해요. 그런 다음 스케줄러는 이전에 그룹 디바이스가 있었던 풀의 디바이스를 불완전한 풀에 속한 것으로 취급하고 완전히 건너뜁니다.
비어 있지 않은 목록만 필드가 설정된 것으로 간주합니다: compatibilityGroups: null과 compatibilityGroups: []는 필드를 생략한 것과 동일하게 처리돼요. 이를 가진 디바이스는 그룹이 없는 디바이스와 똑같이 동작하며, 스케줄러가 풀을 불완전한 것으로 취급하게 하지 않습니다.
디바이스 호환성 그룹은 kube-apiserver와 kube-scheduler의 DRADeviceCompatibilityGroups 기능 게이트로 제어됩니다. DRAPartitionableDevices 기능 게이트도 활성화되어야 해요.
소비 가능한 용량 (Consumable capacity)
기능 상태: Kubernetes v1.36부터 Beta; 기본 활성화
소비 가능한 용량 기능은 동일한 디바이스를 여러 독립적인 ResourceClaim이 소비하게 해 주며, 쿠버네티스 스케줄러가 각 클레임이 디바이스 용량을 얼마나 사용하는지 관리해요. 이는 팟이 노드의 리소스를 공유할 수 있는 것과 유사합니다; ResourceClaim도 디바이스의 리소스를 공유할 수 있어요.
디바이스 드라이버는 ResourceSlice의 .spec.devices에 추가된 allowMultipleAllocations 필드를 설정해 그 디바이스를 여러 독립적인 ResourceClaim 또는 하나의 ResourceClaim 내의 여러 요청에 할당하도록 허용할 수 있어요.
사용자는 ResourceClaim의 spec.devices.requests에 추가된 capacity 필드를 설정해 각 할당의 디바이스 리소스 요구 사항을 지정할 수 있어요.
여러 할당을 허용하는 디바이스의 경우, 요청된 용량은 총 용량에서 가져오거나(소비되며) — 이를 소비 가능한 용량(consumable capacity) 이라고 해요. 그런 다음 스케줄러는 모든 클레임에 걸친 총 소비 용량이 디바이스의 전체 용량을 초과하지 않도록 보장합니다. 또한 드라이버 작성자는 개별 디바이스 용량에 requestPolicy 제약을 사용해 그 용량이 어떻게 소비되는지 제어할 수 있어요. 예를 들어 드라이버 작성자는 특정 용량이 1Gi 단위로만 소비되도록 지정할 수 있습니다.
다음은 여러 할당을 허용하고 소비 가능한 대역폭 용량을 포함하는 네트워크 디바이스의 예시예요.
kind: ResourceSlice
apiVersion: resource.k8s.io/v1
metadata:
name: resourceslice
spec:
nodeName: worker-1
pool:
name: pool
generation: 1
resourceSliceCount: 1
driver: dra.example.com
devices:
- name: eth1
allowMultipleAllocations: true
attributes:
name:
string: "eth1"
capacity:
bandwidth:
requestPolicy:
default: "1M"
validRange:
min: "1M"
step: "8"
value: "10G"
소비 가능한 용량은 아래 예시처럼 요청할 수 있어요.
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: bandwidth-claim-template
spec:
spec:
devices:
requests:
- name: req-0
exactly:
deviceClassName: resource.example.com
capacity:
requests:
bandwidth: 1G
할당 결과에는 소비된 용량과 공유의 식별자가 포함됩니다.
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
...
status:
allocation:
devices:
results:
- consumedCapacity:
bandwidth: 1G
device: eth1
shareID: "a671734a-e8e5-11e4-8fde-42010af09327"