GPU Driver Operations trên Kubernetes: Hai Cách Quản Lý Nhiều NVIDIA Driver Version Trong Production

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ốngApproach A — Skip LabelApproach B — NVIDIADriver CRD
New clusterWorksWorks, cleaner
Migrate existing clusterZero downtime~3 min downtime (daemonset restart)
New node auto-gets driverYesNo — pending until labeled
Freeze a nodeAdd skip labelDon’t change its version label
Promote new versionFreeze all nodes + update ClusterPolicyCreate new CR, label new nodes
Skip labels neededYesNo

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.

Screenshot 2026-04-03 110627.png

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.

Similar Posts