확장 및 업그레이드¶
확장¶
목표: 복제본 수, P:D 비율, llm-d Endpoint Picker(EPP) 리소스를 조정합니다.
복제본 조정¶
prefill 복제본 수는 modelserver.replicas.prefill로, decode 복제본 수는 modelserver.replicas.decode로 설정하세요. 차트 기본값은 둘 다 4입니다. 다음 values 블록은 prefill 복제본을 4개, decode 복제본을 5개로 설정합니다.
prefill 전체가 사용하는 NPU 수는 devices.npu.count에 prefill 복제본 수를 곱한 값입니다. decode도 같습니다. 변경한 복제본 수는 업그레이드, 롤백 및 제거에 따라 helm upgrade로 적용하세요.
복제본을 늘리려면 추가하는 Pod마다 NPU와 RoCE NIC 여유 용량이 있어야 합니다. 노드별 하드웨어 수량은 하드웨어를, 디바이스 할당 방식은 디바이스 할당을 참고하세요.
복제본 수를 줄이면 Deployment가 새 복제본 수를 넘는 Pod를 삭제합니다. 삭제되는 Pod가 처리하던 요청은 5xx로 실패합니다.
모드 전환(replicas ↔ nodePlacement)과 노드 재지정은 helm upgrade로 적용할 수 없습니다. uninstall 후 install로 적용하세요(변경 규칙).
P:D 비율 선택¶
P:D 비율은 측정한 배치를 정리한 하드웨어 › P:D 비율을 보고 선택하세요. 기본 배치는 레퍼런스 4P4D이며, 노드마다 prefill Pod와 decode Pod를 하나씩 둡니다.
EPP 리소스¶
EPP 리소스는 llm-d-router-gateway.router.epp.resources로 조정하세요. 차트 기본값은 CPU 4코어와 메모리 8Gi를 요청하고, 메모리 제한은 16Gi입니다.
노드 예산에 EPP의 메모리 요청량(8Gi)을 포함하세요. 계산식은 Pod 명세 요구 사항 › 리소스 및 노드 예산을 참고하세요.
업그레이드, 롤백 및 제거¶
목표: 서빙 스택을 안전하게 변경, 롤백, 제거합니다.
helm upgrade를 실행할 때마다 설치 시 사용한 values 파일(-f values-env.yaml)을 다시 지정하세요.
레퍼런스 4P4D에는 여유 디바이스가 없습니다. Pod를 재생성하는 변경 전에 여유 디바이스가 없는 경우를 참고하세요.
변경 규칙¶
변경은 종류에 따라 다음 방법으로 적용하세요.
- 값 변경은
helm upgrade로 적용합니다. 재생성되는 Pod는 변경 유형별 영향을 참고하세요. - 토폴로지 모드 전환(
replicas↔nodePlacement)과 노드 재지정은 uninstall 후 install로 적용합니다.nodePlacement목록의 항목 순서를 바꾸는 것도 노드 재지정에 포함됩니다.helm upgrade로 적용하면 기존 Pod가 디바이스를 반환하기 전에 새 Pod가 같은 디바이스를 요청할 수 있습니다. - 롤백은 uninstall 후 이전 이미지 tag와 values로 install합니다.
helm rollback은 지원하지 않습니다.
변경 유형별 영향¶
다음 표는 값 변경마다 어느 Pod를 재생성하는지 정리합니다.
| 변경 | Pod 재생성 | 방법 |
|---|---|---|
modelserver.replicas.{prefill,decode}(같은 모드) | 없음. 남는 Pod는 재생성하지 않습니다. prefill 또는 decode의 복제본 수를 0으로 설정하면 차트가 복제본 수가 0인 P/D role의 Deployment를 제거하고, 컴파일 캐시 PersistentVolumeClaim(PVC)은 남습니다 | helm upgrade |
gateway 아래 전체 / monitoring.enabled | 없음. modelserver 이외의 객체인 Gateway와 모니터링 커스텀 리소스(CR)만 바뀝니다 | helm upgrade |
modelserver의 image · serveArgs · serveEnv · extraServeArgs · extraServeEnv · removeServeArgs · probes · resources · podOverrides, 다음 행의 PVC 명세 키를 제외한 모든 storage.* 볼륨 키, routing.proxy.*, tracing.*, imagePullSecrets, eppServiceName | 모든 Pod. 단, routing.proxy.*는 decode Pod만, extraServeEnv.<role>과 podOverrides.<role>은 <role>(prefill 또는 decode) Pod만 재생성합니다. 트레이스 수집을 비활성화한 상태에서는 tracing.collector.*가 영향을 주지 않습니다 | helm upgrade. 변경 열의 값은 Pod 명세나 serve ConfigMap을 바꾸므로 영향을 받는 modelserver가 다시 시작합니다 |
devices.claimTemplateName, devices.{npu,rdma}.mode, devices.rdma.enabled, devices.rdma.discoveryTimeoutSeconds, devices.rdma.sideChannel.host, 디바이스 플러그인 모드의 count와 resourceName | 모든 Pod | helm upgrade. 차트가 변경 열의 키를 Pod 명세의 resourceClaims, 리소스 요청, 컨테이너 환경 변수에 렌더링하므로 Deployment가 Pod를 재생성합니다 |
devices.rdma.sideChannel.basePort.<role> | <role>(prefill 또는 decode) Pod | helm upgrade |
storage.compileCache.{storageClass,accessModes}와 storage.model(kind: pvc)의 같은 키 | 없음. PVC 명세만 바뀝니다 | uninstall 후 PVC를 삭제(또는 kind: existingClaim으로 전환)하고 install. storageClass와 accessModes는 PVC를 생성한 뒤 바꿀 수 없습니다. 따라서 기존 PVC가 있으면 helm install과 helm upgrade가 렌더링 단계에서 현재 설치의 업그레이드를 거부합니다. 이 검사는 클러스터에서 PVC를 조회하므로 helm template과 GitOps 렌더링에서는 동작하지 않습니다(제거 › 남는 항목 참고) |
storage.compileCache.size와 storage.model.size(kind: pvc) | 없음. PVC 용량만 바뀝니다 | 볼륨 확장을 허용하는 StorageClass에서는 helm upgrade로 늘릴 수 있습니다. 남은 PVC보다 작은 값은 helm install과 helm upgrade가 렌더링 단계에서 거부합니다. helm template과 GitOps 렌더링에서는 이 검사가 동작하지 않습니다 |
replicas ↔ nodePlacement 모드 전환, 노드 재지정 | 모든 Pod | uninstall → install(변경 규칙) |
| AGG와 P/D 분리 간 전환 또는 모델 변경 | 모든 Pod | uninstall → install. P/D 설치에 AGG values를 적용해 업그레이드하면 prefill Deployment는 삭제되지만 컴파일 캐시 PVC는 남습니다 |
llm-d-router-gateway.router.epp.pluginsCustomConfig(EPP 플러그인 구성) | 없음. llm-d-router-gateway 하위 차트가 ConfigMap 체크섬 어노테이션을 생성하지 않으므로 pluginsCustomConfig를 바꿔도 EPP가 재시작하지 않습니다 | helm upgrade 후 EPP를 직접 재시작하세요: kubectl -n <ns> rollout restart deploy/<release-name>-epp |
llm-d-router-gateway.router.inferencePool.create 전환 | 모든 Pod | uninstall → install. inferencePool.create를 바꾸면 EPP Deployment의 셀렉터가 바뀝니다. 셀렉터는 변경할 수 없으므로 현재 설치를 업그레이드하면 적용 단계에서 실패합니다 |
레퍼런스 구성은 Dynamic Resource Allocation(DRA)으로 디바이스를 할당합니다. Pod가 받는 디바이스는 ResourceClaimTemplate(이하 RCT)에 정의합니다. 따라서 devices.rdma.count를 바꿔도 Pod가 받는 NIC 수는 바뀌지 않습니다.
Pod가 받는 디바이스를 바꾸려면 새 RCT를 만들어야 합니다. 기존 RCT의 명세는 수정할 수 없기 때문입니다. 새 RCT를 기존 RCT와 다른 이름으로 적용하세요. 그다음 devices.claimTemplateName을 새 RCT 이름으로 바꾸고 helm upgrade를 실행하세요.
변경을 적용한 뒤에는 모든 Pod가 Ready 상태인지 확인하세요. 그다음 서빙 스택 설치(Helm 차트) › 최초 추론에 따라 추론 요청을 보내세요.
롤링 업데이트¶
롤링 업데이트의 일반 동작은 Kubernetes의 Deployment strategy 문서를 참고하세요. 이 절은 이 차트에만 해당하는 내용을 다룹니다.
차트의 기본 업데이트 전략(maxSurge: 1, maxUnavailable: 0)에서는 Deployment가 새 Pod를 먼저 추가한 뒤 기존 Pod를 종료합니다. 따라서 prefill Pod를 재생성하는 변경에는 prefill Pod 하나분의 여유 디바이스가 필요합니다. decode Pod도 같습니다. 이미지 교체처럼 prefill Pod와 decode Pod를 모두 재생성하는 변경에는 Pod 두 개분의 여유 디바이스가 필요합니다.
여유 디바이스는 노드별 디바이스 목록과 현재 할당된 리소스를 비교해 확인하세요.
여유 디바이스가 없는 경우¶
레퍼런스 4P4D는 모든 디바이스를 사용하므로 여유 디바이스가 없습니다. 이 경우 modelserver.strategy를 다음과 같이 설정하세요. 기본 전략을 그대로 쓰면 새 Pod가 디바이스를 받지 못해 롤아웃이 진행되지 않습니다.
이 전략에서는 Deployment가 기존 Pod를 먼저 종료합니다. 따라서 교체 중에는 교체 중인 prefill 또는 decode의 복제본이 하나 줄어듭니다. 남은 Pod가 부하를 감당할 수 있는지 확인하세요.
nodePlacement 모드에서는 차트가 modelserver.strategy를 무시하고 항상 Recreate로 Pod를 교체합니다.
그 밖에 주의할 상황¶
다음 경우에는 롤링 업데이트가 느려지거나 진행되지 않습니다.
| 상황 | 결과 | 대응 |
|---|---|---|
maxSurge: 0으로 바꿨지만 기존 Pod의 NPU claim, RDMA queue pair, 포트 반환이 늦음 | 기존 Pod가 NPU claim, RDMA queue pair, 포트를 반환할 때까지 새 Pod가 기다립니다(Pending 상태이거나 시작을 재시도) | kubectl -n <ns> get resourceclaims로 기존 Pod의 claim 반환을 확인하세요. claim이 반환되면 새 Pod가 시작을 이어 갑니다 |
| 컴파일 캐시가 비어 있음 | 새 Pod가 먼저 컴파일합니다(컴파일 캐시 › 최초 시작 시간 참고). 그동안 기존 Pod는 계속 서빙하므로 롤아웃 시간만 길어집니다 | 컴파일 캐시 PVC를 유지한 채 진행하세요(컴파일 캐시 참고) |
| 토폴로지 모드도 동시에 변경 | Deployment 이름이 바뀌어 롤링 업데이트가 적용되지 않습니다 | 변경 규칙에 따라 uninstall → install을 수행하세요 |
컴파일 캐시의 accessModes가 ReadWriteOncePod | Pod 하나만 컴파일 캐시 PVC를 마운트할 수 있어 새 Pod를 먼저 시작하는 기본 조합을 사용할 수 없습니다. 차트는 렌더링할 때 ReadWriteOncePod와 기본 롤링 업데이트의 조합을 거부합니다 | maxSurge: 0, maxUnavailable: 1 또는 type: Recreate로 바꾸세요 |
컴파일 캐시가 ReadWriteOnce | prefill Pod나 decode Pod가 여러 노드에 걸치거나(nodePlacement 모드) prefill이나 decode의 복제본이 둘 이상이면(replicas 모드) 차트가 렌더링 단계에서 ReadWriteOnce를 거부합니다. 차트가 렌더링을 허용한 배치에서도 새 Pod가 다른 노드에 스케줄링되면 볼륨을 연결하지 못합니다 | Pod를 한 노드에 두거나 maxSurge: 0, maxUnavailable: 1로 교체하세요 |
모델 볼륨이 ReadWriteMany가 아님 | 다른 노드에 스케줄링된 새 Pod는 볼륨을 연결하지 못합니다. 차트가 생성하는 PVC(storage.model.kind: pvc)는 Pod가 둘 이상이면 차트가 렌더링 단계에서 ReadWriteOnce를 거부합니다. 차트 외부의 claim(existingClaim)은 차트가 accessModes를 확인할 수 없으므로 ReadWriteMany가 아닌 볼륨을 감지하지 못합니다 | Pod를 한 노드에 두거나 maxSurge: 0, maxUnavailable: 1로 교체하세요 |
차트는 각 Deployment의 progressDeadlineSeconds를 시작 예산에서 산출하며, 기본값은 2시간입니다(시작 및 준비 상태 프로브 › Deployment 진행 기한 참고). 따라서 Kubernetes는 롤아웃이 느려도 2시간 안에는 실패로 판정하지 않습니다. kubectl -n <ns> get deploy로 prefill과 decode의 Deployment 이름을 확인한 뒤 다음 명령으로 진행 상황을 확인하세요.
변경 작업 예제¶
다음 명령은 현재 Helm 릴리스를 확인한 뒤 이미지 교체와 uninstall → install 절차를 보여 줍니다.
버전 호환성¶
차트 버전의 MAJOR.MINOR는 RBLN SDK 릴리스 버전과 같습니다(이번 릴리스는 0.12). 차트만 수정한 버전은 PATCH 릴리스로 배포됩니다(예: 0.12.1). 기본 modelserver 이미지 안의 vllm-rbln 버전은 차트의 appVersion에 별도로 기록됩니다. 이미지를 교체하면 이미지 안의 SDK 구성 요소가 모두 함께 바뀝니다. 구성 요소 목록은 소프트웨어 스택과 버전 › 구성 요소를 참고하세요.
이미지 내부 SDK와 Kubernetes 및 RBLN NPU Operator의 검증된 조합은 지원 버전 문서의 RBLN Cloud Native Stack(RCNS) 표를 따릅니다. RCNS 표는 RCNS 버전별로 Kubernetes, 컨테이너 런타임, RBLN Driver, RBLN NPU Operator, DRA 드라이버 및 RBLN SDK 버전을 함께 고정합니다. RCNS 버전 하나는 Kubernetes 마이너 버전 하나에 대응합니다. 이 스택에서 검증한 조합은 소프트웨어 스택과 버전을 참고하세요.
SDK를 바꿀 때 컴파일 캐시 재사용 여부도 함께 판단하세요. RBLN Compiler의 major.minor 버전, 서빙 설정, NPU 종류가 모두 같아야 캐시가 재사용됩니다. 조건과 정리 방법은 컴파일 캐시 › 재사용 조건을 참고하세요.
RBLN Driver 및 RBLN NPU Operator 업그레이드¶
RBLN Driver와 RBLN NPU Operator는 서빙 스택 차트 외부에 있습니다. 절차는 RBLN NPU Operator 업그레이드와 RBLN NPU Operator 설치를 참고하세요.
RBLN NPU Operator를 업그레이드한 뒤에는 디바이스 할당 › 디바이스 할당 확인과 같은 명령으로 DeviceClass와 ResourceSlice가 다시 게시되었는지 확인하세요. 업그레이드 중에는 게시가 잠시 멈출 수 있습니다. 다시 게시될 때까지 새로 스케줄링하는 Pod는 Pending 상태로 남습니다. 이미 서빙 중인 Pod는 할당받은 claim을 유지하므로 영향을 받지 않습니다.
제거¶
서빙 스택은 다음 명령으로 제거하세요.
삭제되는 항목¶
helm uninstall은 차트가 생성한 객체를 삭제합니다. 주요 객체는 다음과 같습니다.
- prefill과 decode의 modelserver Deployment
- EPP Deployment와 InferencePool
- Gateway와 HTTPRoute
- 차트가 생성한 ConfigMap, ServiceAccount, RBAC 객체
남는 항목¶
다음 항목은 helm uninstall 후에도 남습니다.
| 남는 항목 | 이유 | 삭제 방법 |
|---|---|---|
| Pod를 배포했던 prefill 또는 decode의 컴파일 캐시 PVC | helm.sh/resource-policy: keep이 채워진 캐시를 보존합니다 | Pod를 배포했던 prefill과 decode 각각에 대해 kubectl -n <ns> delete pvc <release-name>-compile-cache-<role> |
사용자가 생성한 네임스페이스, Image Pull Secret, llm-d-hf-token, 모델 저장소 | 차트가 생성하지 않았습니다. 다만 storage.model.kind: pvc에서는 차트가 모델 PVC(<release-name>-model-cache)를 resource-policy: keep으로 생성하므로 모델 PVC도 제거 후 남습니다 | 직접 삭제 |
ResourceClaimTemplate npu-rdma | 사용자가 RCT를 적용했으므로 차트가 RCT를 관리하지 않습니다 | 직접 삭제 |
노드 레이블 rebellions.ai/rds.present | 사용자가 노드에 붙인 레이블(RDS 지원)이므로 차트가 이 레이블을 관리하지 않습니다 | kubectl label node <node> rebellions.ai/rds.present- |
| 실패한 설치의 Helm 릴리스 기록 | 실패한 설치의 Helm 릴리스 기록이 남아 있으면 Helm이 같은 이름의 다음 설치를 거부합니다 | helm uninstall <release-name> -n <ns> |
helm uninstall 후 다음 명령으로 남은 항목을 확인하세요.
오프로드 볼륨(storage.modelOffload)을 활성화했다면 오프로드 볼륨은 Pod와 함께 삭제됩니다. 다만 StorageClass의 reclaimPolicy가 Retain이면 PersistentVolume(PV)이 남으므로 직접 삭제하세요.
남은 컴파일 캐시 PVC는 다음 설치에서 다시 사용할 수 있습니다. 같은 Helm 릴리스 이름으로 다시 설치하면 차트가 남은 PVC를 사용하므로 새 Pod는 다시 컴파일하지 않습니다. Helm 릴리스 이름을 바꾸면 차트가 새 PVC를 생성하므로 새 Pod가 처음부터 다시 컴파일합니다.