콘텐츠로 이동

NPU 드라이버 업그레이드 워크플로우

이 문서는 컨테이너 드라이버 방식을 다룹니다. 호스트에 커널 드라이버를 직접 설치하는 호스트 드라이버 모드를 사용하는 경우에는 NPU 드라이버 설치를 참고하세요.

이 문서는 다음 내용을 다룹니다.

  • RBLNDriver 정의: CRD 구조, Driver Manager가 설치하는 항목, 노드별로 드라이버 이미지가 선택되는 방식
  • 아키텍처 및 흐름: 업그레이드를 조율하는 두 컴포넌트(operator, driver-manager)와 드라이버 Pod 시작 시 각 노드에서 수행되는 작업
  • 업그레이드 모드 및 정책: 드라이버 자동 업그레이드와 수동 롤아웃, 그리고 upgradePolicy 설정 방법(cordon, drain, reboot 등)
  • 운영 옵션: 특정 노드를 업그레이드에서 제외하는 방법

RBLNDriver 정의

오퍼레이터는 NPU 드라이버 설치를 관리하기 위해 RBLNDriver CRD를 정의합니다. 원하는 드라이버 버전으로 RBLNDriver 커스텀 리소스를 생성하면 Driver Manager가 해당 버전을 클러스터 전체에 설치하고 유지합니다.

RBLNDriver 예시

apiVersion: rebellions.ai/v1alpha1
kind: RBLNDriver
metadata:
  labels:
    app.kubernetes.io/name: rbln-driver
  name: rblndriver-sample
spec:
  registry: repo.rebellions.ai
  image: rebellions/rbln-driver
  version: "3.0.0"
  imagePullPolicy: IfNotPresent
  imagePullSecrets:
    - drivercred
  resources:
    requests:
      cpu: 250m
      memory: 64Mi
    limits:
      cpu: 500m
      memory: 128Mi
  manager:
    registry: docker.io
    image: rebellions/rbln-k8s-driver-manager
    version: v0.1.3
    imagePullPolicy: IfNotPresent

Driver Manager가 설치하는 항목

RBLNDriver 리소스가 적용되면 Driver Manager는 다음을 설치합니다.

  • 커널 드라이버
  • UMD 라이브러리
  • rbln-smi 등의 도구

드라이버 이미지 선택

Driver Manager는 각 노드의 Node Feature Discovery 라벨을 조합해 드라이버 컨테이너 이미지를 선택합니다.

  • feature.node.kubernetes.io/system-os_release.ID
  • feature.node.kubernetes.io/system-os_release.VERSION_ID
  • feature.node.kubernetes.io/kernel-version.full

예를 들어 Ubuntu 22.04에서 커널 6.8.0-90-generic을 사용하는 노드라면 다음 이미지가 선택될 수 있습니다. docker.io/rebellions/rbln-driver:3.0.0-6.8.0-90-generic-ubuntu22.04.


아키텍처 및 흐름

아키텍처 개요

NPU 드라이버 업그레이드는 두 컴포넌트가 함께 수행합니다.

컴포넌트 역할
rbln-npu-operator 클러스터 수준 오케스트레이션 및 업그레이드 정책 집행
rbln-k8s-driver-manager 노드 로컬 드라이버 상태 조정(reconciliation)

설정에 따라 업그레이드는 다음 모드 중 하나로 동작합니다.

모드 설정 설명
드라이버 자동 업그레이드 autoUpgrade: true 오퍼레이터가 노드 전반의 드라이버 업그레이드 롤아웃을 조율
수동 롤아웃 autoUpgrade: false 관리자가 업그레이드를 명시적으로 트리거

드라이버 업그레이드는 두 계층으로 나뉘어 관리됩니다.

1. rbln-npu-operator (클러스터 오케스트레이션)

오퍼레이터는 클러스터 전체의 업그레이드 오케스트레이션을 관리합니다.

주요 책임은 다음과 같습니다.

  • 드라이버 업그레이드가 필요한 노드 탐지
  • 업그레이드 정책(upgradePolicy) 집행
  • 롤아웃 병렬도 제어(maxParallelUpgrades)
  • 다음과 같은 노드 유지보수 작업 조율:
    • cordon
    • drain
    • reboot
  • 노드 전반의 업그레이드 롤아웃 진행

오퍼레이터는 노드의 드라이버 상태를 직접 관리하지 않습니다. 대신 드라이버 Pod 재시작을 트리거하며, 이 과정에서 노드 로컬 동기화가 시작됩니다.

2. rbln-k8s-driver-manager (노드 드라이버 동기화)

rbln-k8s-driver-manager는 드라이버 DaemonSet 내부에서 실행되며 각 노드의 드라이버 상태를 동기화합니다.

주요 책임은 다음과 같습니다.

  • 노드의 현재 드라이버 상태 탐지
  • 드라이버 업그레이드 동안 노드에 함께 배포된 컴포넌트 일시 중지
  • 필요 시 드라이버 제거/설치 수행
  • 워크로드 재개를 위한 노드 라벨 복원

동기화는 노드에서 드라이버 Pod가 시작될 때마다 실행됩니다.

드라이버 동기화 흐름

노드에서 드라이버 Pod가 시작되면 initContainer가 rbln-k8s-driver-manager에 구현된 reconcile-driver-state 로직을 실행합니다.

단계 동작
1. 노드 라벨 읽기 rebellions.ai/npu.deploy.* 라벨을 읽어 관련 컴포넌트 Pod 실행 여부 결정
2. 관련 컴포넌트 일시 중지 라벨을 paused-for-driver-upgrade로 교체하여 DaemonSet을 중지하고 기존 Pod 종료
3. Pod 종료 대기 NPU Operator 관련 컴포넌트 Pod가 모두 종료될 때까지 대기
4. 드라이버 상태 동기화 드라이버 이미지 다이제스트가 원하는 상태와 일치하면 기존 드라이버 제거를 건너뜁니다. 일치하지 않으면 커널 모듈 언로드, 이전 아티팩트 제거, 새 드라이버 설치를 수행합니다.
5. 노드 라벨 복원 원래 라벨을 복원하여 관련 컴포넌트 Pod가 다시 스케줄링될 수 있도록 함

결과적으로 노드의 모든 컴포넌트가 업그레이드된 드라이버를 사용해 다시 시작됩니다.

오래된 드라이버 DaemonSet 정리

드라이버 이미지는 NFD 라벨(OS, 커널 버전)을 기준으로 선택되므로, 노드의 커널이 변경되면(예: apt upgrade 후 재부팅) 다른 이미지 태그가 선택되고 새로운 드라이버 DaemonSet이 생성됩니다. 오퍼레이터는 노드 셀렉터가 어떤 노드와도 매칭되지 않는 드라이버 DaemonSet을 자동으로 감지해 삭제하므로, 커널 업그레이드 이후 사용하지 않는 드라이버 Pod가 누적되지 않습니다.


업그레이드 모드 및 정책

드라이버 자동 업그레이드 모드 (autoUpgrade: true)

드라이버 자동 업그레이드가 활성화되면, 오퍼레이터가 정책에 따라 노드 전반의 롤아웃을 수행합니다.

업그레이드 동작은 upgradePolicy로 제어됩니다.

업그레이드 흐름

오퍼레이터가 선택한 각 노드에 대해 다음 작업을 수행합니다.

단계 동작
1 새 워크로드가 스케줄링되지 않도록 노드 cordon
2 정책에 따라 기존 NPU 워크로드 처리: waitForCompletion, npuPodDeletion, drain
3 드라이버 Pod 재시작을 통해 노드 로컬 동기화 트리거
4 필요한 경우 노드 재부팅 수행
5 노드 검증 완료
6 노드 uncordon

이후 오퍼레이터는 maxParallelUpgrades에 따라 다음 노드 배치로 진행합니다.

노드 업그레이드 대상 선정

다음 조건에서 업그레이드가 필요한 노드가 감지됩니다.

  • 드라이버 DaemonSet 리비전 변경
  • 명시적인 업그레이드 요청 발생

오퍼레이터는 maxParallelUpgrades 값을 기준으로 업그레이드 노드를 선택합니다.

동작
1 한 번에 노드 1개씩 업그레이드(순차)
0 병렬 업그레이드 제한 없음

재부팅 워크플로우

선택적 재부팅은 다음과 같이 활성화할 수 있습니다.

1
2
3
4
5
6
7
8
9
driver:
  upgradePolicy:
    reboot:
      enable: true
      rebootTimeoutSeconds: 600
      image:
        registry: docker.io
        image: rebellions/rbln-node-reboot
        version: latest

이 블록은 차트 기본값에서 비활성화되어 있습니다(reboot.enable: false).

활성화하면 다음과 같이 동작합니다.

단계 동작
1 오퍼레이터가 reboot helper Pod를 통해 재부팅 트리거
2 노드가 일시적으로 NotReady 상태가 됨
3 재부팅 검증 후 노드가 Ready 상태로 복귀

수동 모드 (autoUpgrade: false)

AutoUpgrade가 비활성화되면 드라이버 DaemonSet은 OnDelete 전략을 사용합니다.

DaemonSet 템플릿이 변경되더라도 드라이버 Pod는 자동으로 재시작되지 않습니다.

대신 관리자가 명시적으로 작업해야 업그레이드가 진행됩니다.

수동 업그레이드 절차

  1. 관리자가 노드 선택
  2. 노드 유지보수 작업 수행(일반적으로 cordon 및 drain)
  3. 관리자가 드라이버 Pod 삭제:
    $ kubectl delete pod <driver-pod>
    
  4. 새로운 드라이버 Pod 생성
  5. initContainer가 드라이버 동기화 흐름을 트리거

동기화 중 rbln-k8s-driver-manager는 다음을 수행합니다.

  • 관련 컴포넌트 Pod 일시 중지
  • 노드 드라이버 상태 업데이트
  • 완료 후 노드 라벨 복원

동기화가 끝나면 관련 컴포넌트 Pod가 자동으로 다시 스케줄링됩니다.

Helm 설정

차트 수준에서 driver.enabled: false이면 RBLNDriver 리소스가 생성되지 않으며, 이 페이지에서 설명하는 업그레이드 동작은 적용되지 않습니다. 이 절의 나머지 내용은 driver.enabled: true를 가정합니다.

모든 업그레이드 동작은 명시적으로 활성화해야 합니다. 차트는 기본적으로 autoUpgrade, drain.enable, reboot.enable을 모두 false로 설정한 상태로 배포됩니다.

드라이버 자동 업그레이드를 사용하려면 autoUpgrade: true로 설정한 뒤, 오퍼레이터가 수행할 유지보수 작업에 해당하는 하위 블록(drain.enable, reboot.enable 등)을 활성화하세요.

설정 예시:

driver:
  upgradePolicy:
    autoUpgrade: true
    maxParallelUpgrades: 1
    waitForCompletion:
      timeoutSeconds: 0
      podSelector: ""
    npuPodDeletion:
      force: false
      timeoutSeconds: 300
    drain:
      enable: true
      force: false
      deleteEmptyDirData: false
      podSelector: ""
      timeoutSeconds: 300
    reboot:
      enable: true
      rebootTimeoutSeconds: 0
      image:
        registry: docker.io
        image: rebellions/rbln-node-reboot
        version: latest

업그레이드 정책 참조

설정 설명
autoUpgrade 드라이버 자동 업그레이드. false(기본값) = 오퍼레이터가 롤아웃을 조율하지 않음. true = 오퍼레이터가 롤아웃을 수행
maxParallelUpgrades 동시에 업그레이드할 수 있는 최대 노드 수. 1 = 순차 진행(기본값). 0 = 제한 없음
waitForCompletion.timeoutSeconds 제거 전에 선택된 Pod의 완료를 기다리는 최대 시간(초). 0(기본값) = 무한 대기
waitForCompletion.podSelector 대기할 Pod의 라벨 셀렉터. 빈 문자열(기본값) = 대기 단계 자체를 건너뜀
npuPodDeletion.force false(기본값) = 보수적 제거(컨트롤러가 없는 Pod에서 차단됨). true = 강제 제거
npuPodDeletion.timeoutSeconds 남은 Pod를 강제 삭제하기 전까지의 최대 시간(초). 0 = 무한 대기(기본값 300)
drain.enable false(기본값) = drain 건너뜀. true = Pod 재시작 전에 오퍼레이터가 노드를 drain
drain.force false(기본값) = 차단 Pod가 있으면 drain 실패. true = 차단 Pod가 있어도 drain 진행
drain.deleteEmptyDirData false(기본값) = emptyDir 스토리지를 사용하는 Pod가 drain을 차단함. true = 해당 Pod도 제거(데이터 손실 발생)
drain.podSelector drain 대상을 매칭되는 Pod로 제한하는 라벨 셀렉터. 빈 문자열(기본값) = 노드의 모든 Pod를 drain
drain.timeoutSeconds drain이 완료되기까지 기다리는 최대 시간(초). 0 = 무한 대기(기본값 300)
reboot.enable false(기본값) = 재부팅하지 않음. true = 업그레이드 과정에서 노드를 재부팅
reboot.rebootTimeoutSeconds 재부팅된 노드가 다시 Ready가 되기까지 기다리는 최대 시간(초). reboot.enable: true인 경우에만 의미가 있습니다. 0(기본값) = 타임아웃 없음

운영 옵션

드라이버 업그레이드 건너뛰기

특정 노드를 드라이버 업그레이드 대상에서 제외하려면 다음 라벨을 설정합니다.

$ kubectl label node <node-name> rebellions.ai/npu-driver-upgrade.skip=true

업그레이드를 다시 활성화하려면 라벨을 제거합니다.

$ kubectl label node <node-name> rebellions.ai/npu-driver-upgrade.skip-

오퍼레이터는 업그레이드를 시도할 때마다 이 라벨을 다시 확인하므로 autoUpgrade: true 모드와 수동 롤아웃 모두에 적용됩니다.

rebellions.ai/npu.deploy.skip과 혼동하지 마세요

라벨 효과
rebellions.ai/npu-driver-upgrade.skip=true 드라이버 업그레이드만 일시 중지합니다. 현재 드라이버는 계속 동작하고, 다른 NPU 컴포넌트는 영향을 받지 않습니다.
rebellions.ai/npu.deploy.skip=true 드라이버 자체를 포함해 노드의 모든 RBLN NPU 컴포넌트를 제거합니다. 해당 노드의 NPU 워크로드는 동작하지 않게 됩니다.

업그레이드만 보류하려면 npu-driver-upgrade.skip을 사용하고, 노드를 NPU 워크로드 대상에서 완전히 제외하려는 경우에만 npu.deploy.skip을 사용하세요. npu.deploy.skip의 전체 동작은 노드별 워크로드 라벨링을 참고하세요.

상태 확인

어떤 노드가 제외되었는지, 나머지 노드가 업그레이드 상태 머신의 어느 단계에 있는지 확인하려면 다음을 실행합니다.

1
2
3
4
$ kubectl get nodes \
  -L rebellions.ai/npu.present \
  -L rebellions.ai/npu-driver-upgrade-state \
  -L rebellions.ai/npu-driver-upgrade.skip

동작 중인 드라이버 확인

드라이버 Pod가 커널 모듈을 로드했고 예상한 KMD 버전이 사용 중인지 확인하려면 대상 노드의 드라이버 컨테이너 안에서 rbln-smi를 실행합니다.

먼저 노드의 드라이버 Pod를 찾습니다. 드라이버 Pod 이름은 rbln-driver-<os>-<kernel>-<hash> 패턴을 따릅니다(드라이버 이미지 선택 참고).

$ kubectl get pods -n rbln-system -o wide | grep rbln-driver

그런 다음 rbln-driver-container에 exec하여 rbln-smi를 실행합니다.

$ kubectl exec -n rbln-system <driver-pod> -c rbln-driver-container -- rbln-smi

헤더에는 동작 중인 KMD 버전이 표시되며, 디바이스 표에는 해당 노드에서 드라이버가 바인딩한 NPU가 나열됩니다.

1
2
3
4
5
6
7
8
+-------------------------------------------------------------------------------------------------+
|                                Device Information KMD ver: 3.0.0                                |
+-----+-----------+---------+---------------+------+---------+------+---------------------+-------+
| NPU |    Name   | Device  |   PCI BUS ID  | Temp |  Power  | Perf |  Memory(used/total) |  Util |
+=====+===========+=========+===============+======+=========+======+=====================+=======+
| 0   | RBLN-CA25 | rbln0   |  0000:05:00.0 |  37C |  58.7W  | P14  |    0.0B / 15.7GiB   |   0.0 |
| 1   |           | rbln1   |  0000:06:00.0 |  39C |         | P14  |    0.0B / 15.7GiB   |   0.0 |
+-----+-----------+---------+---------------+------+---------+------+---------------------+-------+

업그레이드 후에는 KMD ver 줄이 RBLNDriverspec.version과 일치해야 합니다.