Như bạn có thể đã biết, NVIDIA GPU Operator giúp đơn giản hóa việc deploy và quản lý GPU node trong Kubernetes. Phần thiết lập ban đầu đã được đề cập trong tài liệu VKS GPU Node Groups — nhưng khi bạn bước vào môi trường production, một vấn đề mới xuất hiện: không phải GPU card nào cũng chạy được cùng một driver version.
Đây là tình huống điển hình mà bạn sẽ gặp:
- GPU card đời cũ bị “kẹt” ở driver cũ, ví dụ RTX 2080 Ti trên 550.
- Một nhóm node hiện tại đang dùng driver “default” đang hoạt động.
- GPU card mới yêu cầu driver mới hơn so với phần còn lại của cluster.
Nguyên tắc cốt lõi: các node đang có driver chạy ổn không bao giờ bị đụng vào nếu không có chủ ý.
Việc cài driver trực tiếp trên OS mà không dùng GPU Operator không được đề cập ở đây, vì cách đó làm tăng đáng kể chi phí vận hành vòng đời driver.
Hai cách quản lý GPU driver trên VKS
Trong production, bạn thường sẽ phải sống chung với nhiều GPU driver version cùng lúc, và tài liệu này tập trung vào hai cách tiếp cận thực tế để quản lý chúng với GPU Operator. Một approach dựa trên ClusterPolicy như một cấu hình global, còn approach còn lại dùng NVIDIADriver CRD để kiểm soát rõ ràng theo từng node.
Trong phần còn lại của hướng dẫn này, tôi sẽ giới thiệu cách mỗi approach hoạt động, ưu/nhược điểm của chúng, và cách bạn có thể migrate từ pattern cũ sang mô hình per-node mới một cách an toàn.
Approach A: Dựa vào ClusterPolicy và skip label
Với Approach A, ClusterPolicy định nghĩa một GPU driver version global cho toàn cluster, còn các node có thể “opt out” khỏi việc upgrade thông qua một label.
- Node mới join sẽ tự động nhận driver version từ ClusterPolicy.
- Muốn freeze một node, bạn thêm skip label như bên dưới.
- Muốn promote một default mới, bạn freeze các node hiện tại rồi cập nhật ClusterPolicy.
kubectl label node <node> nvidia.com/gpu-driver-upgrade.skip=true
Good for: các cluster đang chạy sẵn ClusterPolicy và không thể chịu downtime để migrate.
Limitation: bạn không thể cài một legacy driver lên một node mới dùng card cũ nếu ClusterPolicy đã được nâng sang một version mới không tương thích. Operator sẽ cố cài sai driver và fail ngay từ đầu.
Recommendation: Approach A là một legacy pattern. Nếu bạn có thể chấp nhận khoảng ~3 phút GPU downtime mỗi node trong maintenance window, hãy migrate sang Approach B.
Reference: https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-driver-upgrades.html
Approach B: Dùng NVIDIADriver CRD để kiểm soát từng node
Với Approach B, mỗi driver version là một NVIDIADriver CR riêng. Mỗi node được gán một label để khai báo chính xác driver version mà nó muốn chạy. Không còn global config, và cũng không cần skip label.
apiVersion: nvidia.com/v1alpha1
kind: NVIDIADriver
metadata:
name: driver-550
namespace: gpu-operator
spec:
driverType: gpu
repository: vcr.hitechcloud.vn/108942-aiplatform-public
image: driver
version: "550.54.15"
nodeSelector:
nvidia.com/driver-version: "550"
repoConfig:
name: "custom-repo"
---
apiVersion: nvidia.com/v1alpha1
kind: NVIDIADriver
metadata:
name: driver-570
namespace: gpu-operator
spec:
driverType: gpu
repository: vcr.hitechcloud.vn/108942-aiplatform-public
image: driver
version: "570.148.08"
nodeSelector:
nvidia.com/driver-version: "570"
repoConfig:
name: "custom-repo"
Node mới join sẽ chưa có driver cho đến khi bạn gán label phù hợp.
kubectl label node <node> nvidia.com/driver-version=570
Good for: cluster mới, cần quyền kiểm soát per-node rõ ràng, tránh upgrade ngoài ý muốn.
Tradeoff: node mới sẽ chưa có driver cho đến khi được label, nên bạn cần config/code ở bước tạo node.
Khi nào nên chọn Approach A, khi nào nên chọn Approach B
Cả hai approach đều hoạt động, nhưng chúng phục vụ hai kiểu vận hành khác nhau: một bên thiên về sự tiện lợi cho cluster đang tồn tại, một bên thiên về tính kiểm soát và dự đoán được trong dài hạn.
| Tình huống | Approach A — Skip Label | Approach B — NVIDIADriver CRD |
|---|---|---|
| New cluster | Works | Works, cleaner |
| Migrate existing cluster | Zero downtime | ~3 min downtime (daemonset restart) |
| New node auto-gets driver | Yes | No — pending until labeled |
| Freeze a node | Add skip label | Don’t change its version label |
| Promote new version | Freeze all nodes + update ClusterPolicy | Create new CR, label new nodes |
| Skip labels needed | Yes | No |
Playbook thực chiến: các lệnh bạn có thể copy và chạy ngay
Phần này là các bước thao tác thực tế mà bạn có thể copy và chạy để promote driver version mới hoặc migrate giữa hai approach.
Approach A — Promote new driver version
Step 1 — Freeze toàn bộ GPU node hiện tại:
kubectl get nodes -l nvidia.com/gpu.present=true -o name | \
xargs -I{} kubectl label {} nvidia.com/gpu-driver-upgrade.skip=true --overwrite
Step 2 — Update ClusterPolicy:
kubectl patch clusterpolicy/cluster-policy --type='json' -p='[
{"op": "replace", "path": "/spec/driver/version", "value": "580.x.x"},
{"op": "replace", "path": "/spec/driver/repository", "value": "vcr.hitechcloud.vn/108942-aiplatform-public"}
]'
Những node join từ thời điểm này sẽ nhận driver 580.x.x.
Các node đã freeze vẫn giữ nguyên driver hiện tại.
Migrate from Approach A → Approach B
Quá trình migrate này cần một maintenance window. Mỗi node sẽ có khoảng ~3 phút GPU unavailability trong lúc driver daemonset restart.
Step 1 — Label từng node với current driver version:
# For each node, set the version label matching what it already has installed
kubectl label node <node> nvidia.com/driver-version=570 --overwrite
Step 2 — Enable NVIDIADriver CRD và disable ClusterPolicy driver management:
helm upgrade nvidia-gpu-operator \
--version v25.3.1 \
-n gpu-operator \
oci://vcr.hitechcloud.vn/108942-aiplatform-public/helm-charts/gpu-operator \
--set driver.nvidiaDriverCRD.enabled=true \
--set driver.nvidiaDriverCRD.deployDefaultCR=false \
--wait
Step 3 — Apply NVIDIADriver CR cho từng version đang dùng:
kubectl apply -f driver-550.yaml
kubectl apply -f driver-570.yaml
# etc.
Operator sẽ restart driver daemonsets trong lúc chuyển đổi, khoảng ~3 phút mỗi node. Sau bước này, cluster của bạn đã ở Approach B và không cần skip label nữa.
Nếu một driver pod vẫn ở trạng thái not-ready vì GPU đang bị giữ bởi một process đang chạy, bạn cần cordon và drain node để evict workloads.
kubectl cordon <node>
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
# Wait for driver pod on that node to reach Running, then uncordon
kubectl uncordon <node>
Approach B — Promote new driver version
Step 1 — Create a CR for the new version:
kubectl apply -f - <<EOF
apiVersion: nvidia.com/v1alpha1
kind: NVIDIADriver
metadata:
name: driver-580
namespace: gpu-operator
spec:
driverType: gpu
repository: vcr.hitechcloud.vn/108942-aiplatform-public
image: driver
version: "580.65.06"
nodeSelector:
nvidia.com/driver-version: "580"
repoConfig:
name: "custom-repo"
EOF
Step 2 — Label new nodes:
kubectl label node <new-node> nvidia.com/driver-version=580
Các node đang tồn tại với driver-version=550 hoặc driver-version=570 sẽ hoàn toàn không bị ảnh hưởng, vì các CR tương ứng không thay đổi.

Không node nào bị tác động trừ khi bạn thay đổi label nvidia.com/driver-version của nó.
Cleanup: khi toàn bộ node của một version đã được decommission, bạn có thể xóa CR đó.
kubectl delete nvidiadriver driver-570
Cách kiểm tra nhanh driver version trên toàn cluster
Bạn có thể kiểm tra nhanh driver version trên toàn bộ GPU node bằng lệnh sau. File gốc bị cắt dòng ở cuối câu lệnh, nên bạn có thể cần hoàn thiện lại phần hiển thị cột theo nhu cầu thực tế của mình.
kubectl get nodes -l nvidia.com/gpu.present=true \
-o custom-columns='NAME:.metadata.name,DRIVER:.metadata.labels.nvidia\.com/cuda\.driver\.major,VERSION-LABE
Nâng GPU Operator mà không đụng tới driver: bạn cần lưu ý gì
Việc upgrade GPU Operator không làm thay đổi driver version trên bất kỳ node nào, vì Operator và driver là hai phần được tách rời hoàn toàn.
Nói cách khác, bạn có thể xem việc nâng GPU Operator là một thay đổi control-plane, còn driver version trên từng node vẫn do ClusterPolicy hoặc NVIDIADriver CR + label quyết định.
Kết luận
Hãy dùng Approach B khi: mỗi node tự khai báo chính xác driver mà nó muốn, và sẽ không có gì thay đổi trừ khi bạn đổi label của nó.
Nếu bạn đang ở Approach A và cluster của bạn có nhiều thế hệ GPU card khác nhau, hãy migrate — vì Approach A không xử lý tình huống đó một cách sạch sẽ trong dài hạn.