8.3. 디바이스 (GPU 공유)
어떨 때 보는가
- GPU 를 쓰는 애플리케이션을 배포할 때
- GPU 파드가
Pending에서 넘어가지 않을 때 - 남은 GPU 가 있는지 확인할 때
- 여러 팀이 GPU 를 나눠 쓰는지 확인할 때
GPU 를 나눠 쓰기 어려운 이유
CPU 와 메모 리는 소수점 단위로 쪼갤 수 있습니다. "CPU 0.5개" 를 요청하면 스케줄러가 알아서 나눠 줍니다.
GPU 는 그렇지 않습니다.
| CPU · 메모리 | GPU | |
|---|---|---|
| 나누기 | 소수점까지 쪼갤 수 있습니다 | 장치 단위가 기본입니다 |
| 종류 구분 | 없습니다 | 모델·메모리 크기가 제각각입니다 |
| 요청 방법 | 숫자로 적습니다 | "어떤 조건의 장치" 를 적어야 합니다 |
| 여럿이 함께 쓰기 | 당연합니다 | 드라이버가 지원해야 합니다 |
"GPU 1개" 라고만 적으면 어느 모델을 받을지 알 수 없습니다. 8GB 짜리로는 안 되는 작업이 있고, 특정 세대에서만 도는 라이브러리도 있습니다.
DRA 란
DRA(Dynamic Resource Allocation)는 이런 복잡한 장치를 다루기 위한 Kubernetes 할당 방식 입니다.
숫자로 요청하는 대신 별도의 요청 자원을 만들고 파드가 그것을 참조 합니다. 요청에는 "어떤 클래스의 장치가 필요하고, 어떤 조건을 만족해야 하는지" 를 적습니다.
이 방식이 주는 것은 이렇습니다.
| 할 수 있는 것 | 설명 |
|---|---|
| 조건으로 고르기 | "메모리 16GB 이상인 GPU" 처럼 요청합니다 |
| 여러 파드가 공유 | 드라이버가 지원하면 한 장치를 나눠 씁니다 |
| 네임스페이스를 넘는 공유 | 팀이 달라도 같은 장치를 함께 씁니다 |
| 장치별 상태 확인 | 어느 장치가 어디에 배정됐는지 화면에서 봅니다 |
드라이버가 있어야 동작합니다. DRA 는 Kubernetes 의 틀이고, 실제 장치를 발견하고 배정하는 것은 GPU 제조사가 제공하는 드라이버입니다. 드라이버가 없으면 목록이 전부 비어 있습니다.
자원 네 가지와 역할
| 자원 | 범위 | 누가 만드나 | 역할 |
|---|---|---|---|
| 디바이스 클래스 | 클러스터 | 드라이버·운영자 | 장치의 종류와 고르는 조건 |
| 리소스 슬라이스 | 클러스터 | 드라이버가 자동 | 노드별 실제 장치 목록 |
| 리소스 클레임 | 네임스페이스 | 사용자 | 장치를 쓰겠다는 요청 |
| 리소스 클레임 템플릿 | 네임스페이스 | 사용자 | 파드마다 요청을 자동 생성하는 틀 |
앞의 둘은 읽기만 합니다. 뒤의 둘을 사용자가 만듭니다.
디바이스 클래스
장치의 종류 를 정의합니다. 디바이스 > 디바이스 클래스 로 들어갑니다.

| 항목 | 설명 |
|---|---|
| 이름 | 요청할 때 쓰는 이름 |
| 선택 조건 | 이 클래스에 속하는 장치의 조건 |
| 기본 설정 | 이 클래스로 요청할 때 자동으로 붙는 설정 |
GPU 모델별로 클래스가 등록됩니다. 파드는 클래스 이름으로 "이런 종류의 장치가 필요하다" 고 요청하고, 어느 노드의 몇 번째 장치인지는 지정하지 않습니다.
리소스 슬라이스
노드에 실제로 장착된 장치 목록입니다. 디바이스 > 리소스 슬라이스 에서 봅니다.
드라이버가 노드를 검사해 자동으로 등록 합니다. 사용자가 만들거나 고치지 않습니다.
| 확인할 것 | 설명 |
|---|---|
| 드라이버 | 이 목록을 발행한 드라이버 |
| 노드 | 어느 노드에 장착되어 있는지 |
| 장치 목록 | 그 노드의 장치와 각각의 속성 |
요청한 장치가 배정되지 않으면 여기서 남은 장치가 있는지 먼저 확인하십시오.
공유 가능 장치 읽는 법
장치 상세에 다음 값이 있으면 여러 파드가 함께 쓸 수 있는 장치 입니다.
| 항목 | 뜻 |
|---|---|
| 공유 가능 | 이 장치를 여럿이 나눠 쓸 수 있는지 |
| 용량 | 나눠 쓸 수 있는 총량. 예: 메모리 16311Mi |
| 요청 범위 | 한 요청이 가져갈 수 있는 범위와 단위 |
공유가 켜져 있으면 네임스페이스가 달라도 같은 장치를 함께 씁니다. 팀 A 가 GPU 를 잡아도 팀 B 가 나머지를 쓸 수 있습니다.
공유가 꺼져 있으면 한 파드가 장치를 통째로 차지합니다. 이때는 먼저 잡은 쪽이 놓을 때까지 다른 요청이 기다립니다.
공유 지원 여부는 드라이버 버전에 달려 있습니다. 공유가 안 되는 것 같으면 운영 담당자에게 드라이버 버전을 확인하십시오.
리소스 클레임
장치를 쓰겠다는 요청 입니다. 디바이스 > 리소스 클레임 에서 봅니다.
| 상태 | 뜻 |
|---|---|
| Pending | 배정할 장치를 찾는 중 |
| Allocated | 장치가 배정됨 |
상세 화면에서 다음을 확인합니다.
| 항목 | 무엇을 알 수 있는가 |
|---|---|
| 요청 | 어떤 클래스의 장치를 몇 개, 어떤 조건으로 요청했는지 |
| 할당 결과 | 어느 노드의 어느 장치가 배정됐는지 |
| 사용 주체 | 어떤 파드가 이 요청을 쓰고 있는지 |
| 장치 상태 | 배정된 장치의 드라이버·풀·이름과 공유 식별자 |
사용 주체가 비어 있는데 상태가 Allocated 면 장치를 잡아 두고 쓰지 않는 것입니다. 다른
파드가 기다리고 있다면 정리 대상입니다.
리소스 클레임 템플릿
같은 요청을 여러 파드가 되풀이해서 쓴다면 디바이스 > 리소스 클레임 템플릿 으로 만들어 둡니다.
Deployment 가 파드를 3개 띄우면 템플릿에서 클레임이 3개 자동으로 만들어집니다. 파드마다 클레임을 손으로 만들 필요가 없습니다.
| 상황 | 쓸 것 |
|---|---|
| 파드 하나가 특정 장치를 오래 씀 | 리소스 클레임 |
| 복제본이 여럿이고 각각 장치가 필요함 | 리소스 클레임 템플릿 |
| 파드가 사라지면 요청도 사라져야 함 | 템플릿 |
템플릿으로 만들어진 클레임은 파드와 수명을 같이합니다. 파드가 지워지면 클레임도 함께 지워져 장치가 풀립니다. 손으로 만든 클레임은 파드가 사라져도 남으니 직접 정리해야 합니다.
GPU 를 쓰는 순서
- 디바이스 클래스 에서 쓸 수 있는 장치 종류를 확인합니다.
- 리소스 슬라이스 에서 남은 장치와 공유 가능 여부를 봅니다.
- 파드 정의에 리소스 클레임(또는 템플릿)을 넣어 배포합니다.
- 리소스 클레임 이
Allocated가 되는지 확인합니다. - 파드가
Running이 되는지 확인합니다(3.1 장).
파드에서 GPU 를 쓰는 방법 — YAML
요청 방식 두 가지를 먼저 고릅니다
파드에 장치를 붙이는 방법은 두 가지이고, 어느 쪽을 쓰느냐가 공유 여부를 가릅니다.
| 참조 방식 | 결과 | 언제 쓰는가 |
|---|---|---|
resourceClaimName — 미리 만든 클레임을 이름으로 가리킴 | 여러 파드가 같은 장치를 나눠 씁니다 | GPU 가 모자라고 여러 워크로드가 함께 써야 할 때 |
resourceClaimTemplateName — 템플릿을 가리킴 | 파드마다 클레임이 새로 생겨 장치를 하나씩 독점합니다 | 복제본마다 장치가 따로 필요할 때 |
이 둘을 혼동하면 증상이 헷갈립니다. 공유하려던 것을 템플릿으로 쓰면 GPU 가 1장인
노드에서 두 번째 파드부터 Pending 에 머뭅니다. 첫 파드는 정상이라 설정이 맞는 것처럼
보입니다.
방법 1 — 여러 파드가 GPU 한 장을 나눠 쓰기
먼저 클레임을 하나 만듭니다. 파드보다 먼저 있어야 합니다.
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
name: shared-gpu
namespace: my-app
spec:
devices:
requests:
- name: gpu
exactly:
deviceClassName: gpu.nvidia.com # 디바이스 클래스 화면의 이름
allocationMode: ExactCount
count: 1
| 항목 | 설명 |
|---|---|
deviceClassName | 디바이스 클래스 화면에 있는 이름을 그대로 씁니다. 없는 이름을 적으면 클레임이 Pending 에 머뭅니다 |
allocationMode | ExactCount 는 count 만큼, All 은 조건에 맞는 장치 전부 |
count | 몇 개를 요청할지 |
그 다음 파드가 이름으로 가리킵니다. 파드 스펙과 컨테이너 스펙 두 곳에 모두 적어야 합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-gpu-app
namespace: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-gpu-app
template:
metadata:
labels:
app: my-gpu-app
spec:
resourceClaims: # ① 파드가 어떤 클레임을 쓰는지
- name: gpu # 파드 안에서 부를 이름
resourceClaimName: shared-gpu # 실제 ResourceClaim 이름
containers:
- name: app
image: registry.example.com/my-gpu-app:1.0
resources:
claims: # ② 이 컨테이너가 그중 무엇을 쓰는지
- name: gpu # ①의 name 과 같아야 합니다
limits:
cpu: "2"
memory: 4Gi
| 위치 | 하는 일 |
|---|---|
spec.resourceClaims | 파드가 쓸 클레임 목록. 여기 이름은 파드 안에서만 통합니다 |
containers[].resources.claims | 파드가 받은 것 중 이 컨테이너에 붙일 것 |
두 곳 중 하나만 적으면 장치가 연결되지 않습니다. 파드에만 적으면 컨테이너에서 GPU 가 보이지 않고, 컨테이 너에만 적으면 파드 생성이 거부됩니다.
이 예에서는 복제본 3개가 모두 같은 GPU 한 장 을 씁니다. 리소스 클레임 상세의 사용 주체에 파드 3개가 함께 표시됩니다.
방법 2 — 복제본마다 GPU 를 따로 잡기
템플릿을 만들고 파드가 그것을 가리킵니다.
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: dedicated-gpu
namespace: my-app
spec:
spec:
devices:
requests:
- name: gpu
exactly:
deviceClassName: gpu.nvidia.com
allocationMode: ExactCount
count: 1
spec 이 두 번 나오는 것이 맞습니다. 바깥은 템플릿의 명세, 안쪽은 템플릿이 찍어 낼
클레임의 명세 입니다.
spec:
resourceClaims:
- name: gpu
resourceClaimTemplateName: dedicated-gpu # 템플릿 이름
containers:
- name: app
image: registry.example.com/my-gpu-app:1.0
resources:
claims:
- name: gpu
복제본 수만큼 장치가 필요합니다. 복제본 3개면 GPU 3장이 있어야 하고, 모자라면 남은
파드는 Pending 에 머뭅니다.
옛 방식과 무엇이 다른가
예전에는 컨테이너의 자원 상한에 GPU 개수를 적었습니다.
resources:
limits:
nvidia.com/gpu: "1" # 옛 방식
DRA 로 바꿀 때는 이 줄을 지웁니다. 두 방식을 함께 쓰면 장치를 두 번 요청하게 됩니다. CPU·메모리 상한은 그대로 둡니다(3.1 장).
| 옛 방식 | DRA | |
|---|---|---|
| 요청하는 곳 | 컨테이너의 자원 상한 | ResourceClaim |
| 요청할 수 있는 것 | 개수만 | 개수 + 조건(모델·메모리·분할 여부) |
| 공유 | 노드 단위 설정이라 그 노드 전체에 적용 | 클레임 단위라 필요한 워크로드끼리만 |
| 확인 화면 | 노드 상세의 할당 가능 자원 | 디바이스 메뉴 |
적용한 뒤 확인할 것
| 순 서 | 어디에서 | 정상이면 |
|---|---|---|
| 1 | 디바이스 > 리소스 클레임 | 상태가 Allocated |
| 2 | 같은 화면 상세 | 할당 결과에 노드와 장치 이름이 있음 |
| 3 | 같은 화면 상세 | 사용 주체에 내 파드가 있음 |
| 4 | 워크로드 > Pod | Running(3.1 장) |
1번에서 Pending 이면 파드는 뜨지 않습니다. 아래 "배정되지 않을 때" 를 보십시오.
자주 틀리는 것
| 증상 | 원인 |
|---|---|
두 번째 파드부터 Pending | 공유하려 했는데 resourceClaimTemplateName 을 썼습니다 |
| 컨테이너에서 GPU 가 안 보임 | containers[].resources.claims 를 빠뜨렸습니다 |
| 파드 생성이 거부됨 | spec.resourceClaims 를 빠뜨렸거나 두 곳의 name 이 다릅니다 |
클레임이 계속 Pending | deviceClassName 이 실제 디바이스 클래스 이름과 다릅니다 |
| 장치를 두 배로 잡음 | 옛 방식(limits.nvidia.com/gpu)을 함께 남겨 두었습니다 |
| 다른 네임스페이스 파드와 공유가 안 됨 | 클레임은 네임스페이스 단위입니다. 드라이버 버전에 따라 가능 여부가 다르니 운영 담당자에게 확인하십시오 |
노드를 직접 지정할 수 없습니다. DRA 는 스케줄러가 장치를 배정해야 하므로 파드에 노드 이름을 박아 두면 배정이 되지 않습니다. 특정 노드로 보내야 하면 노드 선택 조건 (
nodeSelector)을 쓰십시오.
장치 목록이 비어 있을 때
디바이스 클래스와 리소스 슬라이스가 모두 비어 있으면 드라이버가 없거나 동작하지 않는 것입니다.
| 확인 | 설명 |
|---|---|
| GPU 노드가 있는가 | 노드 목록에서 GPU 노드를 확인합니다 (2.1 장) |
| 드라이버 파드가 떠 있는가 | 드라이버는 GPU 노드마다 파드로 돕니다 |
| 클러스터가 DRA 를 지원하는가 | 운영 담당자에게 확인 |
이 화면은 조회 전용입니다. 드라이버 설치와 설정은 운영 담당자가 수행합니다.
배정되지 않을 때
| 증상 | 원인 | 확인할 것 |
|---|---|---|
클레임이 Pending | 남은 장치가 없음 | 리소스 슬라이스에서 사용 중인 장치 확인 |
클레임이 Pending | 조건에 맞는 장치가 없음 | 요청한 클래스·속성이 실제 장치와 맞는지 |
클레임이 Pending | 공유가 꺼져 있고 먼저 잡은 파드가 있음 | 그 장치의 공유 가능 여부 |
파드가 Pending | 클레임은 배정됐으나 노드 자원 부족 | 그 노드의 CPU·메모리 여유 |
| 여러 팀이 동시에 못 씀 | 드라이버가 공유를 지원하지 않음 | 드라이버 버전 |
GPU 는 대개 노드 수보다 적어 경쟁이 심합니다. 쓰지 않는 파드가 장치를 잡고 있는지 리소스 클레임 목록에서 확인하십시오. 개발·시험용 파드를 정리하면 자리가 납니다.
MIG 와 DRA 의 관계
두 가지를 혼동하기 쉬운데 층이 다릅니다.
| MIG | DRA | |
|---|---|---|
| 무엇인가 | GPU 하드웨어를 여러 조각으로 나누는 기능 | Kubernetes 의 장치 할당 방식 |
| 어디에 있나 | GPU 안 | Kubernetes 안 |
| 제공하는 것 | 조각마다 전용 연산 자원과 메모리, 장애 격리 | 조건에 맞는 장치를 찾아 배정 |
| 쓸 수 있는 GPU | 데이터센터용 일부 모델만 | 드라이버가 지원하는 모든 GPU |
"DRA 를 쓰면 MIG 가 필요 없다" 는 것은 아닙니다. MIG 가 GPU 를 조각으로 나누고, DRA 가 그 조각을 파드에 배정합니다. 두 가지를 함께 쓸 수 있습니다.
하드웨어 수준의 격리(한 작업이 다른 작업의 성능이나 안정성에 영향을 주지 않는 것)는 MIG 만 제공합니다. DRA 의 공유는 소프트웨어 수준이라 서로 영향을 줄 수 있습니다.
어떤 방식을 쓰는지는 클러스터 구성에 달려 있습니다. 리소스 슬라이스의 장치 목록에 조각으로 나뉜 장치가 보이면 MIG 가 적용된 것입니다.