[Kubernetes] NVIDIA Device Plugin 동작 원리

2 분 소요

Kubernetes 환경에서 GPU를 사용하는 방법을 알아본 뒤, 그렇다면 NVIDIA Device Plugin이 어떻게 동작하여 컨테이너에서 GPU를 사용할 수 있는 것인지 공부한 내용을 작성한다.


개요

크게 두 가지의 관점에서 이해하면 좋다. NVIDIA Device Plugin이 쿠버네티스 환경에서 GPU를 인식할 수 있게 해 준다고 했기 때문에, 어떻게 인식할 수 있는 건지(이하 보고라고 하겠다), 인식한 GPU 노드에 어떻게 파드가 스케줄링되어 실행되는지(이하 스케줄링이라고 하겠다)이다.


큰 구조는 아래와 같다. GPU를 사용하기 위해, 아래와 같이 계층 별로 책임이 잘 분리되어 있다.

┌──────────────┐
│  Scheduler   │  "어느 노드에 배치할까?" (정책 결정)
└──────┬───────┘
       │ Pod.spec.nodeName = "worker-1"
       ↓
┌──────────────┐
│   Kubelet    │  "이 노드에서 어떻게 실행할까?" (실행 조율)
│  (worker-1)  │  - Device plugin에게 물어보기
└──────┬───────┘  - Container runtime에게 전달하기
       │
       ├─────→ ┌─────────────────┐
       │       │ Device Plugin   │  "어떤 GPU 줄까?" (리소스 할당)
       │       └─────────────────┘
       │
       └─────→ ┌─────────────────┐
               │Container Runtime│  "어떻게 격리할까?" (실행)
               └─────────────────┘
  • Scheduler (kube-scheduler): 어느 노드에 배치할지 결정
    • 모든 리소스를 동일하게 취급
    • 각각의 리소스를 고려했을 때, 파드를 어느 노드에 배치할지가 관심사
  • Kubelet: 파드 실행 관리
    • 노드별 에이전트
    • device plugin과 container runtime 사이 중개자 역할
    • device plugin에 물어봐서, container runtime에 실행 요청
  • NVIDIA Device Plugin: 어떤 장치를 할당할지 결정
    • 노드 GPU 세부사항 관리
    • Kubelet에게 파드 실행 시 어떤 GPU를 사용하라고 알려 줌
  • Container Runtime: 실제 컨테이너 실행


보고

NVIDIA Device Plugin daemonset이 배포되어 있는 클러스터라면, GPU 노드에 라벨링했을 때, 각 노드에 NVIDIA Device Plugin이 배포된다고 했다. 이후, 노드의 GPU 상태가 아래와 같이 관리된다.


kubernetes-gpu-report

  1. NVIDIA Device Plugin Pod 시작
    • 노드에 배포된 daemonset pod가 자동 시작
  2. Device Plugin → Kubelet 등록 (Register)
    • Device Plugin이 kubelet의 unix socket에 연결
    • Kubelet은 NVIDIA Device Plugin Pod를 인식하게 됨
    • nvidia.com/gpu 리소스를 관리하겠습니다 선언
  3. Device Plugin → Kubelet GPU 개수 보고 (ListAndWatch, 지속적)
    • Device Plugin이 구현해야 하는 메서드 중 하나인 ListAndWatch를 실행함
    • NVML(NVIDIA Management Library)로 GPU 스캔
    • 발견한 GPU 개수를 gRPC stream으로 지속 보고
  4. Kubelet은 노드 상태에 GPU 자원을 지속적으로 반영하여 업데이트함
    • GPU 상태 변경 시 즉시 업데이트


이렇게 보고된 GPU 자원을 노드 상태를 통해 확인할 수 있게 되는 것이다.

apiVersion: v1
kind: Node
metadata:
  name: worker-1
status:
  capacity:
    nvidia.com/gpu: "8"      # device plugin이 보고한 값
    cpu: "16"
    memory: "64Gi"
  allocatable:
    nvidia.com/gpu: "8"      


스케줄링

그렇다면 사용자가 GPU 파드 생성을 요청했을 때는 어떤 일이 발생할까.

kubernetes-gpu-scheduling-1

  1. 사용자: nvidia.com/gpu: 1 파드 생성 요청
  2. Scheduler: 노드 스케줄링
    • 위 보고 단계에서 노드 상태가 계속해서 보고되고 있음
    • 이렇게 보고된 노드 상태를 바탕으로, 가용 nvidia.com/gpu 자원을 확인해 적절한 노드에 배치
  3. Kubelet: 파드 배치 감지
    • 아, 내 노드에 파드가 배치되었구나. 컨테이너 생성을 시작해야지!
  4. Kubelet: NVIDIA GPU Device Plugin에게 GPU 할당 요청
    • 이 pod에 nvidia.com/gpu 자원이 1개 필요해. 어떤 GPU를 사용하면 돼?
  5. NVIDIA Device Plugin: GPU 할당 결과 응답 반환
    • GPU-<uuid>를 할당해줄게. /dev/nvidia0 경로에 있어. 환경 변수는 이렇게 설정해
    • GPU ID: GPU-abc123…
    • Device Path: /dev/nvidia0, /dev/nvidiactl, /dev/nvidia-uvm
    • 환경변수: NVIDIA_VISIBLE_DEVICES=GPU-abc123
    • 마운트: CUDA 라이브러리 경로들
  6. Kubelet: Container Runtime에 4에서 받은 응답과 함께 컨테이너 실행 요청
    • Kubelet은 NVIDIA Device Plugin의 응답을 신뢰. 받은 것을 그대로 전달
    • Container Runtime에, 예컨대 아래와 같은 정보를 주입
      {
        "Devices": [
          {
            "Path": "/dev/nvidia0", 
            "Type": "c",
            "Major": 195,
            "Minor": 0
          }
        ],
        "Mounts": [
          "/usr/local/nvidia/lib64",
          // CUDA 라이브러리들
        ],
        "Env": [
          "NVIDIA_VISIBLE_DEVICES=0",  
          "CUDA_VISIBLE_DEVICES=0"
        ]
      }
      
  7. Container Runtime: 컨테이너 실행


Container Runtime의 GPU 처리

NVIDIA Container Runtime에 대해 알아본 결과를 바탕으로, 위의 56 사이에 어떤 일이 일어나는지 조금 더 자세히 살펴보자.

kubernetes-gpu-scheduling-2

  1. Kubelet: High-Level Container Runtime에 컨테이너 생성 요청
  2. High-Level Container Runtime: NVIDIA Container Runtime 호출
  3. NVIDIA Container Runtime 동작
    • GPU 장치 파일 마운트
    • CUDA 라이브러리 마운트
    • NVIDIA driver 파일 마운트
    • 컨테이너 namespace 설정
  4. NVIDIA Container Runtime: Low-Level Container Runtime 호출
  5. Low-Level Container Runtime: 컨테이너 실행


결론

위와 같은 단계를 거쳐, 최종적으로 쿠버네티스 환경에서 컨테이너가 GPU를 사용할 수 있게 된다. 알고 보면, 그 속에 숨어 있는 추상화 레벨과 책임 분리가, 놀라운 수준이다.



hit count

댓글남기기