NPU 드라이버 업그레이드 워크플로우¶
이 문서는 컨테이너 드라이버 방식을 다룹니다. 호스트에 커널 드라이버를 직접 설치하는 호스트 드라이버 모드를 사용하는 경우에는 NPU 드라이버 설치를 참고하세요.
이 문서는 다음 내용을 다룹니다.
- RBLNDriver 정의: CRD 구조, Driver Manager가 설치하는 항목, 노드별로 드라이버 이미지가 선택되는 방식
- 아키텍처 및 흐름: 업그레이드를 조율하는 두 컴포넌트(operator, driver-manager)와 드라이버 Pod 시작 시 각 노드에서 수행되는 작업
- 업그레이드 모드 및 정책: 드라이버 자동 업그레이드와 수동 롤아웃, 그리고
upgradePolicy설정 방법(cordon, drain, reboot 등) - 여러 드라이버 버전 운영:
driver.instances로 특정 노드 그룹에 별도의 드라이버 버전을 고정하는 방법 - 운영 옵션: 특정 노드를 업그레이드에서 제외하는 방법
RBLNDriver 정의¶
오퍼레이터는 NPU 드라이버 설치를 관리하기 위해 RBLNDriver CRD를 정의합니다. 원하는 드라이버 버전으로 RBLNDriver 커스텀 리소스를 생성하면 Driver Manager가 해당 버전을 클러스터 전체에 설치하고 유지합니다.
RBLNDriver 예시¶
spec.image에는 NPU 제품군을 넣지 마세요. 오퍼레이터가 노드 풀마다 이미지 경로에 제품군 세그먼트를 자동으로 삽입합니다. 자세한 내용은 드라이버 이미지 선택을 참고하세요.
Driver Manager가 설치하는 항목¶
RBLNDriver 리소스가 적용되면 Driver Manager는 다음을 설치합니다.
- 커널 드라이버
- UMD 라이브러리
rbln-smi등의 도구
RBLNDriver마다 <CR_NAME>-smd라는 RSMD DaemonSet도 함께 배포됩니다. rbln-smd 이미지 태그는 spec.version을 따르므로 업그레이드 중에도 노드 데몬과 드라이버 버전이 일치합니다. spec.smd로는 레지스트리와 리포지토리만 지정합니다. Pod는 해당 노드의 드라이버 설치가 끝난 뒤에 시작하고, 노드의 드라이버 Pod가 교체될 때 함께 교체됩니다. 준비 상태는 .status.smd에 따로 표시됩니다.
Driver Manager v0.2.2 이상 필요
RSMD DaemonSet을 제어하는 rebellions.ai/npu.deploy.rbln-smd 노드 레이블을 갱신하려면 Driver Manager v0.2.2 이상이 필요합니다. 차트의 driver.manager.image.tag가 호환 버전을 고정하므로 특별한 이유가 없다면 그대로 사용하세요.
드라이버 이미지 선택¶
커널 드라이버 빌드는 NPU 제품군 하나와 OS·커널 조합 하나만 지원합니다. 한 클러스터에서 여러 NPU 제품을 운영할 수 있도록 오퍼레이터는 제품군, OS, 커널을 기준으로 NPU 노드를 노드 풀로 묶고 풀마다 드라이버 DaemonSet을 하나씩 생성합니다. 오퍼레이터는 다음 레이블을 사용해 각 노드가 속할 풀을 결정합니다.
| 레이블 | 부여 주체 | 값 예시 |
|---|---|---|
rebellions.ai/npu.family |
오퍼레이터가 직접 관리하는 rbln-npu-family라는 NodeFeatureRule |
atom |
feature.node.kubernetes.io/system-os_release.ID |
Node Feature Discovery | ubuntu |
feature.node.kubernetes.io/system-os_release.VERSION_ID |
Node Feature Discovery | 22.04 |
feature.node.kubernetes.io/kernel-version.full |
Node Feature Discovery | 6.8.0-90-generic |
풀 이름은 <family>-<os><version>-<kernel>이고, DaemonSet 이름은 <CR_NAME>-<POOL_NAME>입니다. 이미지 경로에는 spec.image의 마지막 세그먼트 앞에 제품군이 삽입됩니다.
따라서 커널 6.8.0-90-generic의 Ubuntu 22.04에서 동작하는 ATOM 노드는 atom-ubuntu22.04-6.8.0-90-generic 풀에 속하며 다음 이미지를 사용합니다.
rebellions.ai/npu.family 레이블이 없거나 값이 올바르지 않은 노드는 풀에 할당되지 않습니다. 오퍼레이터는 이를 DriverFamilyLabelMissing으로 보고하고 기존 DaemonSet은 그대로 두므로, 레이블이 누락되어도 동작 중인 드라이버는 제거되지 않습니다.
롤아웃 전 레지스트리 확인¶
오퍼레이터는 풀의 DaemonSet을 생성하기 전에 조합된 이미지가 레지스트리에 존재하는지 확인합니다. 404 응답만 풀 생성 실패로 처리합니다. 이 경우 커스텀 리소스는 Ready=False와 DriverImageNotFound 사유를 보고하면서 누락된 이미지 경로를 표시합니다. 따라서 Pod가 ImagePullBackOff에 머무르지 않습니다. 확인은 약 5분마다 반복되므로 이미지를 게시하면 별도 조치 없이 해소됩니다.
404 이외의 응답이나 오류(인증 실패, 타임아웃, TLS 또는 DNS 오류 등)가 발생하면 오퍼레이터는 경고를 기록하고 롤아웃을 계속합니다. 이후 kubelet이 이미지 풀 성공 여부를 판단합니다.
operator.driverImageCheck=false로 확인 자체를 건너뛸 수 있습니다. 폐쇄망이나 미러 전용 클러스터처럼 오퍼레이터가 노드용 레지스트리에 접근할 수 없는 경우, 또는 ServiceAccount 풀 시크릿이나 클라우드 인스턴스 자격 증명처럼 오퍼레이터가 볼 수 없는 노드 수준 자격 증명으로 이미지를 받는 경우에 사용하세요.
아키텍처 및 흐름¶
아키텍처 개요¶
NPU 드라이버 업그레이드는 두 컴포넌트가 함께 수행합니다.
| 컴포넌트 | 역할 |
|---|---|
rbln-npu-operator |
클러스터 수준 오케스트레이션 및 업그레이드 정책 집행 |
rbln-k8s-driver-manager |
노드 로컬 드라이버 상태 조정(reconciliation) |
설정에 따라 업그레이드는 다음 모드 중 하나로 동작합니다.
| 모드 | 설정 | 설명 |
|---|---|---|
| 드라이버 자동 업그레이드 | autoUpgrade: true |
오퍼레이터가 노드 전반의 드라이버 업그레이드 롤아웃을 조율 |
| 수동 롤아웃 | autoUpgrade: false |
관리자가 업그레이드를 명시적으로 트리거 |
드라이버 업그레이드는 두 계층으로 나뉘어 관리됩니다.
1. rbln-npu-operator (클러스터 오케스트레이션)¶
오퍼레이터는 클러스터 전체의 업그레이드 오케스트레이션을 관리합니다.
주요 책임은 다음과 같습니다.
- 드라이버 업그레이드가 필요한 노드 탐지
- 업그레이드 정책(
upgradePolicy) 집행 - 롤아웃 병렬도 제어(
maxParallelUpgrades) - 다음과 같은 노드 유지보수 작업 조율:
cordondrainreboot
- 노드 전반의 업그레이드 롤아웃 진행
오퍼레이터는 노드의 드라이버 상태를 직접 관리하지 않습니다. 대신 드라이버 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 정리¶
풀은 노드의 NPU 제품군, OS, 커널로 구분되므로 노드의 커널이 변경되면(예: apt upgrade 후 재부팅) 해당 노드는 다른 풀로 이동하고 새로운 드라이버 DaemonSet이 생성됩니다. 오퍼레이터는 노드 셀렉터가 어떤 노드와도 매칭되지 않는 드라이버 DaemonSet을 자동으로 감지해 삭제하므로, 커널 업그레이드 이후 사용하지 않는 드라이버 Pod가 누적되지 않습니다.
어느 한 풀이라도 생성에 실패하면 오퍼레이터는 오래된 DaemonSet 정리와 새 풀의 DaemonSet 생성을 모두 보류합니다. 정리를 보류하지 않으면 기존 DaemonSet이 다른 풀의 노드에 스케줄링되어 한 호스트에서 드라이버 설치가 중복 실행될 수 있기 때문입니다.
드라이버 준비 상태 신호¶
오퍼레이터는 드라이버 컨테이너가 드라이버 설치를 마친 뒤 생성하는 파일을 확인하여 준비 완료 여부를 판단합니다. 펌웨어 업데이트나 모듈 재로드가 진행 중일 때는 readiness probe가 Pod를 ready로 표시하지 않습니다.
.status.nodePools는 드라이버 Pod만 집계합니다. 노드 데몬은 별도로 보고되며, 아직 준비되지 않았다면 커스텀 리소스는 SmdNotReady 사유와 함께 Ready=False 상태를 유지합니다.
업그레이드 모드 및 정책¶
드라이버 자동 업그레이드 모드 (autoUpgrade: true)¶
드라이버 자동 업그레이드가 활성화되면, 오퍼레이터가 정책에 따라 노드 전반의 롤아웃을 수행합니다.
업그레이드 동작은 upgradePolicy로 제어됩니다.
업그레이드 흐름¶
오퍼레이터가 선택한 각 노드에 대해 다음 작업을 수행합니다.
| 단계 | 동작 |
|---|---|
| 1 | 새 워크로드가 스케줄링되지 않도록 노드 cordon |
| 2 | 정책에 따라 기존 NPU 워크로드 처리: waitForCompletion, npuPodDeletion, drain |
| 3 | 드라이버 Pod 재시작을 통해 노드 로컬 동기화 트리거 |
| 4 | 필요한 경우 노드 재부팅 수행 |
| 5 | 노드 검증 완료 |
| 6 | 노드 uncordon |
이후 오퍼레이터는 maxParallelUpgrades에 따라 다음 노드 배치로 진행합니다.
오퍼레이터는 각 단계를 노드에 Kubernetes 이벤트(DriverUpgradeStarted → NodeDrained → DriverUpgradeCompleted)로 기록합니다. 자세한 내용은 오퍼레이터 관찰가능성을 참고하세요.
노드 업그레이드 대상 선정¶
다음 조건에서 업그레이드가 필요한 노드가 감지됩니다.
- 드라이버 DaemonSet 리비전 변경
- 명시적인 업그레이드 요청 발생
오퍼레이터는 maxParallelUpgrades 값을 기준으로 업그레이드 노드를 선택합니다.
| 값 | 동작 |
|---|---|
1 |
한 번에 노드 1개씩 업그레이드(순차) |
0 |
병렬 업그레이드 제한 없음 |
재부팅 워크플로우¶
GRUB 설정이 변경된 경우에 재부팅을 활성화하면 노드가 재시작되어 변경 사항이 적용됩니다. drain.enable: true와 npuPodDeletion을 함께 설정하면 오퍼레이터가 재부팅 전에 워커 노드를 cordon하고 drain합니다. 이 설정들을 함께 활성화하는 예시는 다음과 같습니다.
drain.enable과 reboot.enable은 차트 기본값에서 모두 false입니다.
활성화하면 다음과 같이 동작합니다.
| 단계 | 동작 |
|---|---|
| 1 | 오퍼레이터가 reboot helper Pod를 통해 재부팅 트리거 |
| 2 | 노드가 일시적으로 NotReady 상태가 됨 |
| 3 | 재부팅 검증 후 노드가 Ready 상태로 복귀 |
수동 모드 (autoUpgrade: false)¶
AutoUpgrade가 비활성화되면 드라이버 DaemonSet은 OnDelete 전략을 사용합니다.
DaemonSet 템플릿이 변경되더라도 드라이버 Pod는 자동으로 재시작되지 않습니다.
대신 관리자가 명시적으로 작업해야 업그레이드가 진행됩니다.
수동 업그레이드 절차¶
- 관리자가 노드 선택
- 노드 유지보수 작업 수행(일반적으로 cordon 및 drain)
- 관리자가 드라이버 Pod 삭제:
- 새로운 드라이버 Pod 생성
- 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 등)을 활성화하세요.
설정 예시:
업그레이드 정책 참조¶
| 설정 | 설명 |
|---|---|
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(기본값) = 타임아웃 없음 |
여러 드라이버 버전 운영¶
한 클러스터에서 여러 드라이버 버전을 동시에 운영할 수 있습니다. 예를 들어 레이블로 지정한 일부 노드에만 카나리 버전을 적용하거나 NPU 제품군별로 다른 버전을 사용할 수 있습니다. driver.instances의 각 항목은 rbln-driver-<key> 이름의 RBLNDriver 커스텀 리소스로 렌더링됩니다.
인스턴스 키는 40자 이하의 소문자 DNS-1123 레이블이어야 합니다. 생성된 리소스 이름이 노드에 레이블 값으로 기록되기 때문입니다.
노드 라우팅¶
드라이버 DaemonSet은 사용자가 지정한 nodeSelector를 직접 사용하지 않습니다. 오퍼레이터는 조정할 때마다 각 NPU 노드의 소유 리소스를 다시 계산해 그 이름을 rebellions.ai/npu.driver.owner 노드 레이블에 기록하고, DaemonSet은 이 레이블을 셀렉터로 사용합니다. 따라서 셀렉터가 서로 겹쳐도 스케줄링 단계에서 노드당 하나의 드라이버만 배치됩니다.
매칭되는 셀렉터 중 가장 구체적인 셀렉터가 노드의 소유권을 가집니다. 가장 구체적인 셀렉터란 매칭되는 다른 모든 셀렉터의 키-값을 전부 포함하면서 키가 더 많은 셀렉터입니다. 최상위 driver.nodeSelector는 기본적으로 비어 있으므로 기본 리소스가 모든 노드에 매칭되며, 더 구체적인 인스턴스가 맡지 않은 노드를 자동으로 담당합니다.
셀렉터가 서로 같거나 포함 관계를 판단할 수 없는 두 인스턴스는 양쪽 모두에 매칭되는 노드에서 충돌합니다. 이때 해당 노드는 기존 드라이버를 그대로 유지하고 나머지 노드는 정상적으로 라우팅되며, 두 리소스 모두 ConflictingNodeSelector 사유와 함께 Ready=False를 보고하고 영향받은 노드 일부를 함께 표시합니다. 둘 중 한쪽 셀렉터를 수정하면 다음 조정 과정에서 해소됩니다.
rebellions.ai/npu.driver.owner와 rebellions.ai/npu.deploy.driver는 예약 키입니다. nodeSelector에 이 키를 사용한 리소스는 InvalidSpec으로 거부되고 라우팅에서 제외되며, 다른 리소스에는 영향을 주지 않습니다.
값 상속¶
인스턴스에 지정하지 않은 필드는 최상위 driver 블록에서 상속됩니다.
| 필드 종류 | 예시 | 동작 |
|---|---|---|
| 맵 | image, resources, annotations, manager, smd |
키 단위로 병합됩니다. 상속된 키를 제거하려면 인스턴스에서 맵 전체를 재정의하세요. |
| 리스트 | tolerations, env, imagePullSecrets |
병합하지 않고 전체를 대체합니다. []는 상속값을 비웁니다. |
| 스칼라 | priorityClassName |
재정의합니다. ""는 상속값을 비웁니다. |
nodeSelector |
— | 상속되지 않습니다. 모든 인스턴스에 필수이며 비워 둘 수 없습니다. 셀렉터를 비워 둘 수 있는 것은 기본 리소스뿐입니다. |
driver.upgradePolicy는 RBLNClusterPolicy에 한 번만 렌더링되어 모든 인스턴스에 동일하게 적용됩니다. 인스턴스별 업그레이드 주기는 지원하지 않습니다.
deployDefault: false는 기본 드라이버를 제거합니다
driver.deployDefault=false로 설정하면 기본 리소스가 제거되므로, 더 구체적인 인스턴스가 맡지 않은 노드는 드라이버를 잃습니다. 변경하기 전에 해당 노드를 확인하세요.
인스턴스 라우팅 확인¶
인스턴스 키 오타로 인한 자동 상속
인스턴스 키에 오타가 있으면 버전을 포함한 모든 필드를 기본값에서 상속한 채 오류 없이 렌더링됩니다.
적용 전에 각 인스턴스가 실제로 어떤 버전을 사용하는지 확인하세요.
helm uninstall은 커스텀 리소스를 제거하지만 노드의 rebellions.ai/npu.driver.owner 레이블은 남겨 둡니다. 재설치 시 오퍼레이터가 첫 조정 과정에서 덮어쓰므로 문제가 되지는 않지만, 완전히 제거할 때는 함께 정리하세요.
운영 옵션¶
드라이버 업그레이드 건너뛰기¶
특정 노드를 드라이버 업그레이드 대상에서 제외하려면 다음 레이블을 설정합니다.
업그레이드를 다시 활성화하려면 레이블을 제거합니다.
오퍼레이터는 업그레이드를 시도할 때마다 이 레이블을 다시 확인하므로 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의 전체 동작은 노드별 워크로드 레이블링을 참고하세요.
상태 확인¶
어떤 노드가 제외되었는지, 나머지 노드가 업그레이드 상태 머신의 어느 단계에 있는지 확인하려면 다음을 실행합니다.
동작 중인 드라이버 확인¶
드라이버 Pod가 커널 모듈을 로드했고 예상한 KMD 버전이 사용 중인지 확인하려면 대상 노드의 드라이버 컨테이너 안에서 rbln-smi를 실행합니다.
먼저 노드의 드라이버 Pod를 찾습니다. 드라이버 Pod 이름은 rbln-driver-<family>-<os>-<kernel>-<hash> 패턴을 따릅니다(드라이버 이미지 선택 참고).
그런 다음 rbln-driver-container에 exec하여 rbln-smi를 실행합니다.
헤더에는 동작 중인 KMD 버전이 표시되며, 디바이스 표에는 해당 노드에서 드라이버가 바인딩한 NPU가 나열됩니다.
업그레이드 후에는 KMD ver 줄이 RBLNDriver의 spec.version과 일치해야 합니다.