콘텐츠로 이동

RBLN 쿠버네티스 디바이스 플러그인

RBLN SDK는 Kubernetes 클러스터에서 RBLN NPU를 사용하기 위한 쿠버네티스 디바이스 플러그인(Device Plugin)을 제공합니다.

설치는 NPU Operator 설치와 Device Plugin 구성을 따릅니다. 기본 요청과 할당 결과 확인은 NPU Pod 실행하기에서, 제품군 선택과 다중 NPU 할당은 NPU 제품군 선택하기와 NPU 2개 요청하기에서 확인할 수 있습니다.

CDI 설정(필수)

디바이스 플러그인은 컨테이너 런타임에서 CDI가 활성화되어 있어야 동작합니다. containerd를 직접 설정하고 재시작하거나 Container Toolkit으로 CDI를 설정해야 합니다.

containerd v1.7.x (/etc/containerd/config.toml)

1
2
3
4
[plugins]
  [plugins."io.containerd.grpc.v1.cri"]
    enable_cdi = true
    cdi_spec_dirs = ["/etc/cdi", "/var/run/cdi"]

containerd v2.x.x (/etc/containerd/config.toml)

1
2
3
4
[plugins]
  [plugins."io.containerd.cri.v1.runtime"]
    enable_cdi = true
    cdi_spec_dirs = ["/etc/cdi", "/var/run/cdi"]

디바이스 플러그인은 컨테이너를 할당할 때마다 rebellions.ai/npu=runtime CDI 어노테이션을 추가합니다. 플러그인 자체에는 CDI를 켜고 끄는 설정이 없습니다. 어노테이션은 항상 내보내며, 런타임이 이를 처리할지는 위의 CDI 설정과 Container Toolkit이 호스트에 생성한 CDI 스펙에 달려 있습니다. 두 가지가 갖춰지면 런타임은 워크로드가 NPU 리소스(예: rebellions.ai/npu)를 요청할 때 필요한 라이브러리와 rbln-smi 같은 도구를 컨테이너에 마운트합니다.

노드에 RDS(Rebellions Direct Storage) 디바이스 노드(/dev/rblnfs*)가 있으면 플러그인은 rebellions.ai/rds=all 어노테이션도 추가해 같은 CDI 경로로 RDS 디바이스를 마운트합니다. 플러그인은 NPU를 할당할 때마다 RDS 디바이스 노드를 확인하며, 없으면 RDS 어노테이션을 추가하지 않습니다. 대상 노드와 NVMe 설정은 RDS 지원에서 확인할 수 있습니다.

스케줄링과 할당

설정 또는 값 의미
rebellions.ai/npu.product 노드 레이블 nodeSelector에서 사용하는 하드웨어 정보입니다.
status.allocatable["rebellions.ai/npu"] Kubernetes에서 사용할 수 있는 정상 디바이스의 총 개수입니다. 이미 Pod가 요청한 디바이스도 포함합니다.
resources.limits.rebellions.ai/npu 컨테이너 하나가 요청하는 NPU 수입니다. 정수로 지정해야 합니다. requests를 생략하면 Kubernetes가 이 제한값을 requests에도 적용합니다. 둘 다 설정하면 값이 같아야 합니다.

컨테이너 두 개가 각각 NPU 1개를 요청하면 각 컨테이너에 서로 다른 디바이스가 할당됩니다. 컨테이너 하나가 NPU 2개를 요청하면 두 디바이스 모두 해당 컨테이너에 할당됩니다.

남은 NPU 수를 확인하려면 kubectl describe node <NODE_NAME>의 Allocatable과 기존 요청량을 비교합니다. 스케줄러는 selector와 taint를 비롯해 CPU와 메모리 요구량 등 다른 조건도 확인합니다. 하드웨어 레이블만으로는 드라이버나 디바이스 플러그인이 준비되었는지 알 수 없습니다.

같은 제품군의 여러 제품을 허용하려면 NPU limits를 유지한 채 Pod의 spec 아래에 다음을 추가합니다.

1
2
3
4
5
6
7
8
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: rebellions.ai/npu.family
          operator: In
          values: [atom]

제품군을 선택하기 전 kubectl get nodes -L rebellions.ai/npu.family로 노드의 제품군 레이블을 확인합니다.

여러 NPU의 RSD 그룹

디바이스 플러그인은 NPU를 할당할 때 선택한 PCI 버스 ID로 RSD 그룹을 만듭니다. 이 그룹의 호스트 디바이스를 컨테이너의 /dev/rsd0에 매핑합니다. rbln-smi -j -g에서 컨테이너에 할당된 모든 디바이스의 group_id가 동일하고 비어 있지 않아야 합니다. Kubernetes 워크로드가 디바이스를 사용하는 동안 호스트 RSD 그룹을 직접 생성·삭제해서는 안 됩니다.

디바이스 상태 기반 격리

디바이스 플러그인은 디바이스 검색 주기마다 커널 드라이버를 통해 각 NPU의 상태를 확인하여 kubelet에 Healthy/Unhealthy 상태를 보고합니다. 워크로드가 실행될 수 없는 디바이스는 스케줄링 대상에서 자동으로 제외되고, 드라이버가 다시 READY 상태를 보고하면 자동으로 스케줄링 가능한 상태로 복귀합니다.

NPU 할당 트레이스

디바이스 플러그인은 NPU 할당 경로를 OpenTelemetry 트레이스로 계측합니다. 할당 요청마다 어떤 디바이스와 Rebellions Scalable Design(RSD) 그룹이 컨테이너에 전달되었는지 스팬(span)에 기록되므로, OpenTelemetry Protocol(OTLP) 백엔드에서 노드별 NPU 할당 이력을 트레이스할 수 있습니다.

트레이스는 기본적으로 비활성화되어 있으며, 다음 Helm 값으로 OTLP gRPC 엔드포인트를 지정하여 활성화할 수 있습니다.

devicePlugin:
  otlpEndpoint: <OTLP_ENDPOINT>

host:port 형식의 엔드포인트는 평문 gRPC 연결을 사용합니다. TLS를 사용하려면 https://collector:4317처럼 스킴을 포함한 전체 URL을 지정해야 합니다.

트레이스는 부가적인 관찰가능성 기능이므로, 엔드포인트 형식이 잘못되었거나 OTLP 익스포터 초기화에 실패하더라도 플러그인은 트레이스 없이 계속 동작하며, 노드의 NPU 스케줄링에는 영향을 주지 않습니다.

할당 요청 단위의 Allocate 스팬과 컨테이너 단위의 allocateContainer 스팬이 생성되며, 다음 속성을 포함합니다. 할당이 실패하면 오류 내용이 스팬에 기록됩니다.

속성 설명
rbln.resource_name 할당이 요청된 리소스 이름(예: rebellions.ai/npu)
rbln.device.ids 컨테이너에 할당된 NPU 디바이스 ID 목록
rbln.device.count 할당된 디바이스 수
rbln.device.bus_ids 할당된 디바이스의 PCI 버스 ID 목록
rbln.rsd.host_path 할당에 사용된 RSD 그룹의 호스트 경로

모든 스팬에는 리소스 속성으로 service.name=rbln-device-plugin과 service.version이 포함됩니다. 또한 NODE_NAME 환경 변수가 설정된 경우(Helm DaemonSet은 spec.nodeName을 항상 주입) k8s.node.name 속성이 추가되어 노드별로 구분할 수 있습니다.