全部產品
Search
文件中心

Container Service for Kubernetes:配置及管理ack-nvidia-device-plugin組件

更新時間:Jan 10, 2026

GPU裝置外掛程式(NVIDIA Device Plugin)是Kubernetes叢集中用於管理每個節點的GPU的組件,使得Kubernetes能夠更方便、高效地利用GPU資源。本文介紹在獨佔GPU調度情境下,如何對ACK節點的NVIDIA Device Plugin進行升級、重啟、GPU裝置隔離、版本查看與更新等操作。

使用說明

對於以DaemonSet方式部署的NVIDIA Device Plugin,有如下幾點需要說明:

  • 叢集在建立時,會自動安裝該組件。

  • 如果卸載該組件將導致擴容的GPU節點無法正常上報GPU資源。

  • 叢集由低版本升級到1.32過程中,會同時將以Static Pod方式部署的NVIDIA Device Plugin升級為ACK組件形式。

  • 該DaemonSet存在一個NodeSelector(ack.node.gpu.schedule=default),GPU節點在添加到叢集中時,ACK添加節點的指令碼會自動為該GPU節點打上該標籤,使DaemonSet能夠在GPU節點上部署對應的Pod。

重要
  • 若節點作業系統為Ubuntu 22.04或Red Hat Enterprise Linux(RHEL) 9.3 64位,由於ack-nvidia-device-plugin組件會為Pod預設配置環境變數NVIDIA_VISIBLE_DEVICES=all,可能會因為節點執行systemctl daemon-reloadsystemctl daemon-reexec命令後,無法訪問GPU裝置導致NVIDIA Device Plugin無法正常工作。更多詳情,請參見運行GPU容器出現Failed to initialize NVML: Unknown Error的問題怎麼辦?

  • 若在2025年05月01日之前將叢集從低版本升級到1.32版本,叢集中可能會同時存在以Static Pod方式部署和DaemonSet方式部署的NVIDIA Device Plugin。可執行如下指令碼查看以Static Pod方式部署的節點。

    #!/bin/bash
    for i in $(kubectl get po -n kube-system -l component=nvidia-device-plugin | grep -v NAME | awk '{print $1}');do
        if kubectl get po $i -o yaml -n kube-system | grep 'kubernetes.io/config.source: file' &> /dev/null;then
        kubectl get pod $i -n kube-system -o jsonpath='{.spec.nodeName}{"\n"}'
        fi
    done

    預期輸出:

    cn-beijing.10.12.XXX.XX
    cn-beijing.10.13.XXX.XX

    通過預期輸出可以看到部分節點中仍存在以Static Pod方式部署的NVIDIA Device Plugin。可以使用如下方式將Static Pod方式部署的NVIDIA Device Plugin遷移到DaemonSet。

    kubectl label nodes <NODE_NAME> ack.node.gpu.schedule=default
  • 1.31及以下版本的叢集在升級節點池的過程中也會升級NVIDIA Device Plugin,對於NVIDIA Device Plugin非標準的配置將被重設。

版本差異

ack-nvidia-device-plugin組件隨著叢集版本的不同,其實現方式和管理原則如下表所示。

特性

1.32及以上叢集版本

1.20至1.31間叢集版本

部署方式

DaemonSet

Static Pod

管理方式

控制台組件管理

手動維護

節點標籤要求

ack.node.gpu.schedule=default

無特殊要求

隨節點池升級策略

手動升級

自動升級

若叢集版本低於1.20,建議手動升級叢集

前提條件

查看NVIDIA Device Plugin版本

1.32及以上叢集版本

針對以DaemonSet方式部署的組件,可在控制台組件管理頁面定位ack-nvidia-device-plugin組件,在組件卡片上查看目前的版本。

1.20至1.31間叢集版本

針對以Static Pod方式部署的組件,可執行以下命令查看組件版本。

kubectl get pods -n kube-system -l component=nvidia-device-plugin \
  -o jsonpath='{range .items[*]}{.spec.containers[0].image}{"\t"}{.spec.nodeName}{"\n"}{end}' \
  | awk -F'[:/]' '{split($NF, a, "-"); print a[1] "\t" $0}' \
  | sort -k1,1V \
  | cut -f2- \
  | awk -F'\t' '{split($1, img, ":"); print img[NF] "\t" $2}'

升級NVIDIA Device Plugin

  1. 升級ack-nvidia-device-plugin組件。

    1.32及以上叢集版本

    1. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

    2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,單擊組件管理

    3. 在組件管理頁面,搜尋ack-nvidia-device-plugin組件,在其卡片位置單擊升級

    4. 在彈出的對話方塊中,單擊確定

    1.20至1.31間叢集版本

    1. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇節點管理 > 節點

    2. 選中需要批量維護的GPU節點,在節點列表下方單擊批量營運,然後在批量營運對話方塊選擇執行Shell命令,單擊確定

      重要

      建議先選擇少量GPU節點進行升級,操作完成驗證節點Device Plugin正常工作後,再大大量操作。

    3. 在自動跳轉的OOS介面,選擇執行模式失敗暫停後,單擊下一步:設定參數

    4. 在設定參數頁面,選擇運行Shell指令碼,並粘貼如下樣本指令碼。

      說明
      • 指令碼中RUN_PKG_VERSION參數需修改為叢集對應的大版本號碼(例如:1.30)。請勿填入小版本號碼(例如:1.30.1),否則會導致指令碼報錯。

      • 指令碼中REGION_ID參數需修改為當前叢集所在的地區ID,例如:cn-beijing。

      #!/bin/bash
      set -xe
      
      RUN_PKG_VERSION=1.30
      REGION_ID=cn-beijing
      
      function update_device_plugin() {
      	base_dir=/tmp/update_device_plugin
      	rm -rf $base_dir
      	mkdir -p $base_dir
      	cd $base_dir
      	region_id=$REGION_ID
      	PKG_URL=https://aliacs-k8s-${region_id}.oss-${region_id}-internal.aliyuncs.com/public/pkg/run/run-${RUN_PKG_VERSION}.tar.gz
      	curl -sSL --retry 3 --retry-delay 2 -o run.tar.gz $PKG_URL
      	tar -xf run.tar.gz
      
      	local dir=pkg/run/$RUN_PKG_VERSION/module
      	sed -i "s@registry.cn-hangzhou.aliyuncs.com/acs@registry-${region_id}-vpc.ack.aliyuncs.com/acs@g" $dir/nvidia-device-plugin.yml
      	mkdir -p /etc/kubernetes/device-plugin-backup
      	mkdir -p /etc/kubernetes/manifests
      	mv  /etc/kubernetes/manifests/nvidia-device-plugin.yml /etc/kubernetes/device-plugin-backup/nvidia-device-plugin.yml.$(date +%s)
      	sleep 5
      	cp -a $dir/nvidia-device-plugin.yml /etc/kubernetes/manifests
      	echo "succeeded to update device plugin"
      }
      
      if [ -f /etc/kubernetes/manifests/nvidia-device-plugin.yml ]; then
      	update_device_plugin
      else
      	echo "skip to update device plugin"
      fi
    5. 單擊下一步:確定,確認資訊無誤後單擊建立

      建立後自動跳轉至任務執行管理頁面,可查看任務運行狀態。查看執行輸出succeeded to update device plugin,表明更新成功。

  2. 檢查組件是否正常運行。

    執行如下命令,查看GPU節點上Device Plugin是否正常工作。

    1. 在Workbench或CloudShell上使用kubectl串連叢集

    2. 使用如下命令檢查NVIDIA Device Plugin是否重啟:

      kubectl get po -n kube-system -l component=nvidia-device-plugin 

      樣本輸出,通過AGE時間判斷Pod是否重啟。

      NAME                             READY   STATUS    RESTARTS      AGE
      nvidia-device-plugin-xxxx        1/1     Running   1             1m
    3. 判斷所有Pod重啟後,執行如下指令碼檢測節點是否上報GPU資源:

      #!/bin/bash
      
      # 擷取所有合格 NVIDIA Device Plugin Pod及其所在節點
      PODS=$(kubectl get po -n kube-system -l component=nvidia-device-plugin -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}')
      
      # 遍曆每個 Pod 的節點
      echo "$PODS" | while IFS=$'\t' read -r pod_name node_name; do
          # 擷取節點的 nvidia.com/gpu 資源分派值
          gpu_allocatable=$(kubectl get node "$node_name" -o jsonpath='{.status.allocatable.nvidia\.com/gpu}' 2>/dev/null)
      
          # 檢查資源值是否為 0
          if [ "$gpu_allocatable" == "0" ]; then
              echo "Error: node=$node_name, pod=$pod_name, resource(nvidia.com/gpu) is 0"
          fi
      done

      如果出現節點上報資源為0, 可參考重啟NVIDIA Device Plugin

重啟NVIDIA Device Plugin

在ACK的獨佔GPU調度情境下,節點上GPU的裝置上報的Device Plugin預設以一個Pod的形式部署,所以重啟過程需要在目標節點上進行。

1.32及以上叢集版本

  1. 執行如下命令,查詢對應節點的Device Plugin Pod。

    kubectl get pod -n kube-system -l component=nvidia-device-plugin -o wide | grep <NODE>
  2. 執行如下命令,重啟對應的Device Plugin Pod。

    kubectl delete po <DEVICE_PLUGIN_POD> -n kube-system 

1.20至1.31間叢集版本

  1. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇節點管理 > 節點池

  2. 節點池頁面,單擊節點池名稱,進入節點管理,登入目標GPU節點。

    如果作業系統為ContainerOS,為了減少潛在的安全風險,ContainerOS原則上不支援任何使用者直接登入到系統進行一系列可能無法追溯的操作,也不提供SSH登入功能。若仍然有登入執行個體進行營運操作的需求,請參見營運ContainerOS節點
  3. 選中需要批量維護的GPU節點,在節點列表下方單擊批量營運,然後在批量營運對話方塊選擇執行shell命令,單擊確定

    重要

    建議先選擇少量GPU節點進行重啟,操作完成驗證節點Device Plugin正常工作後,再大大量操作。

  4. 在自動跳轉的OOS介面,選擇執行模式失敗暫停後,單擊下一步:設定參數

  5. 在設定參數頁面,選擇運行shell指令碼,並粘貼如下樣本指令碼。

    #!/bin/bash
    set -e
    
    if [ -f /etc/kubernetes/manifests/nvidia-device-plugin.yml ]; then
    	cp -a /etc/kubernetes/manifests/nvidia-device-plugin.yml /etc/kubernetes
    	rm -rf /etc/kubernetes/manifests/nvidia-device-plugin.yml
    	sleep 5
    	mv /etc/kubernetes/nvidia-device-plugin.yml /etc/kubernetes/manifests
    	echo "the nvidia device is restarted"
    else
    	echo "no need to restart nvidia device plugin"
    fi
  6. 單擊下一步:確定,確認資訊無誤後單擊建立。建立後自動跳轉至任務執行管理頁面,可查看任務運行狀態。

  7. 執行如下命令,查看GPU節點上Device Plugin是否正常工作。

    kubectl get nodes <NODE_NAME> -o jsonpath='{.metadata.name} ==> nvidia.com/gpu: {.status.allocatable.nvidia\.com/gpu}'

    預期輸出:

    cn-hangzhou.172.16.XXX.XX ==> nvidia.com/gpu: 1

    GPU節點上報的nvidia.com/gpu擴充資源不為0,說明Device Plugin正常工作。

修改NVIDIA Device Plugin裝置標識符

Device-Plugin在為Pod分配裝置時會在節點上建立一份Checkpoint檔案,用於記錄和儲存哪些裝置已經被分配,以及它們對應Pod的資訊。在NVIDIA Device Plugin中,Checkpoint檔案預設使用GPU的UUID作為每個GPU裝置的唯一識別碼(Key)。可以參見下文將該Key修改為裝置的Index,以解決VM冷遷移導致的UUID丟失等問題。

1.32及以上叢集版本

  1. 執行如下命令,修改NVIDIA Device Plugin Daemonset。

    kubectl edit ds -n kube-system ack-nvidia-device-plugin
  2. 添加如下環境變數CHECKPOINT_DEVICE_ID_STRATEGY

        env:
          - name: CHECKPOINT_DEVICE_ID_STRATEGY
            value: index
  3. 重啟NVIDIA Device Plugin,使得修改內容生效。

1.20至1.31間叢集版本

  1. 在目標節點上的/etc/kubernetes/manifests/nvidia-device-plugin.yml檔案中查看Device-Plugin的鏡像Tag,其所代表的版本號碼即為Device-Plugin的版本。如果版本號碼大於等於0.9.3,則無需修改版本號碼,否則請將版本號碼修改為最新的版本號碼v0.9.3-0dd4d5f5-aliyun

  2. 修改/etc/kubernetes/manifests/nvidia-device-plugin.yml檔案中的Static Pod的環境變數,參見以下代碼增加一個環境變數CHECKPOINT_DEVICE_ID_STRATEGY

        env:
          - name: CHECKPOINT_DEVICE_ID_STRATEGY
            value: index
  3. 重啟NVIDIA Device Plugin,使得修改內容生效。

開啟GPU裝置隔離功能

重要

GPU裝置隔離操作僅支援在nvidia-device-plugin的v0.9.1及以上版本中使用。可以參見下文查看NVIDIA Device Plugin版本

在ACK的獨佔GPU調度情境下,出於某些原因(例如GPU裝置故障等),需要隔離節點上的某個GPU裝置,ACK提供了一個機制供手動對節點上的某個裝置進行隔離,以避免新的GPU應用Pod被分配到這張GPU卡。具體的操作方式如下:

在目標節點/etc/nvidia-device-plugin/的目錄下操作unhealthyDevices.json這個檔案,如果此檔案不存在,請建立此檔案。unhealthyDevices.json的檔案格式請按照以下JSON格式編排,數組中可以包含多個裝置標識符,請根據需要添加。

{
  "index": ["x", "x"],
  "uuid": ["xxx", "xxx"]
}

可以根據個人偏好,在JSON中填寫目標隔離裝置的indexuuid(同一個裝置只需填寫任意一個),儲存檔案後即可自動生效。

設定完成後,可以通過查看Kubernetes Node上報的Resource中的nvidia.com/gpu資源的數量以查看隔離的效果。

掛載GDR裝置並開啟GPU記憶體拷貝加速

適用範圍

從v0.5.0開始,ack-nvidia-device-plugin支援掛載GDR裝置到GPU容器中。此能力要求如下條件:

  • 叢集版本>=1.32。

  • 節點為靈駿節點。

  • 節點已安裝GDR軟體。

    可通過登入節點後執行lsmod | grep gdrdrv查看是否有GDR核心模組已經載入,樣本輸出如下:
    gdrdrv                196608  0
    nvidia              14680064  88 nvidia_uvm,nvidia_peermem,gdrdrv,nvidia_modeset
  • 節點已安裝nvidia-container-toolkit且版本>= 1.15.0。

    可通過登入節點後執行nvidia-container-cli --version確認版本,樣本輸出如下:
    cli-version: 1.17.8
    lib-version: 1.17.8

開啟GDR加速

  1. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,單擊組件管理

  3. 在組件管理頁面,搜尋ack-nvidia-device-plugin組件,在其卡片位置單擊配置

  4. 在彈出的對話方塊中,勾選启用 GDRCopy 以支持 GPU 内存拷贝加速(开启后,将在已安装GDR软件且nvidia-container-toolkit版本 >= 1.15.0的灵骏节点上生效)

驗證啟用結果

  1. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇工作負載 > 無狀態

  2. 無狀態頁面,單擊使用YAML建立資源使用以下範例程式碼建立應用。

    apiVersion: v1
    kind: Pod
    metadata:
      name: tensorflow-mnist
      namespace: default
    spec:
      containers:
      - image: registry.cn-beijing.aliyuncs.com/acs/tensorflow-mnist-sample:v1.5
        name: tensorflow-mnist
        command:
        - python
        - tensorflow-sample-code/tfjob/docker/mnist/main.py
        - --max_steps=100000
        - --data_dir=tensorflow-sample-code/data
        resources:
          limits:
            nvidia.com/gpu: 1  # 為該容器申請1張GPU卡。
        workingDir: /root
      restartPolicy: Always
  3. 通過如下命令進入Pod內部:

    kubectl exec -ti tensorflow-mnist -- ls /dev/gdrdrv

    預期輸出:

    /dev/gdrdrv

    說明掛載gdrdrv裝置成功。

常見問題

如何關閉NVIDIA Device Plugin原生GPU隔離能力?

問題背景

當節點 GPU 出現異常時,ACK 會通過 NVIDIA Device Plugin 自動隔離異常GPU,防止任務被調度到異常GPU上。而自動隔離並不會執行自動修複,您仍需手動重啟或維修節點,並建議配置 GPU 異常警示以便及時處理。關於NVIDIA Device Plugin原生GPU隔離能力的更多資訊,請參見k8s-device-plugin

  • 隔離後,若節點剩餘 GPU 不足以滿足任務需求(如 8 卡任務在僅有 7 卡可用時),任務將無法調度,可能導致GPU資源閑置。

  • GPU狀態恢複正常後,對該GPU裝置的隔離會自動解除。

  • 如需關閉自動隔離(出現異常GPU仍然上報資源,不做異常GPU隔離),請參考後續解決方案。

解決方案

  1. 確認組件是否已開啟原生的GPU隔離能力。

    如果未開啟,則無需執行後續的關閉操作。

    1.32及以上叢集版本

    登入Container Service管理主控台,在目的地組群的組件管理中檢查ack-nvidia-device-plugin版本。如果版本為v0.1.0,則說明已開啟GPU隔離能力。

    1.20至1.31間叢集版本

    1. 在Workbench或CloudShell上使用kubectl串連叢集

    2. 檢測NVIDIA Device Plugin是否開啟GPU隔離能力。

      check_gpu_isolation_enabled() {
          echo "Checking nodes with NVIDIA Device Plugin deployed as static pods that have GPU isolation enabled (i.e., DP_DISABLE_HEALTHCHECKS is not set to 'all')..."
      
          # Get pod names with the expected label
          pods=$(kubectl get pods -n kube-system -l component=nvidia-device-plugin --no-headers -o custom-columns=":metadata.name" 2>/dev/null)
      
          if [ -z "$pods" ]; then
              echo "No pods found with label 'component=nvidia-device-plugin'."
              return 0
          fi
      
          found=0
          while IFS= read -r pod; do
              [ -z "$pod" ] && continue
      
              # Check if it's a static pod: annotation kubernetes.io/config.source must be "file"
              config_source=$(kubectl get pod "$pod" -n kube-system -o jsonpath='{.metadata.annotations.kubernetes\.io/config\.source}' 2>/dev/null)
      
              if [ "$config_source" != "file" ]; then
                  # Not a static pod (e.g., managed by DaemonSet), skip
                  continue
              fi
      
              # Get node name
              node=$(kubectl get pod "$pod" -n kube-system -o jsonpath='{.spec.nodeName}' 2>/dev/null)
              [ -z "$node" ] && continue
      
              # Check if DP_DISABLE_HEALTHCHECKS is set to "all"
              disabled_value=$(kubectl get pod "$pod" -n kube-system -o jsonpath='{range .spec.containers[*]}{range .env[?(@.name=="DP_DISABLE_HEALTHCHECKS")]}{.value}{"\n"}{end}{end}' 2>/dev/null | head -n1)
      
              # If not set or not equal to "all", health checks are active → isolation is enabled
              if [ -z "$disabled_value" ] || [ "$disabled_value" != "all" ]; then
                  echo "Node: $node, Static Pod: $pod"
                  found=1
              fi
          done <<< "$pods"
      
          if [ "$found" -eq 0 ]; then
              echo "No static pods found with GPU isolation enabled."
          else
              echo "Note: The above nodes will automatically isolate faulty GPUs via NVIDIA Device Plugin."
          fi
      }
      
      check_gpu_isolation_enabled

      預期輸出:

      Checking nodes with NVIDIA Device Plugin deployed as static pods that have GPU isolation enabled (i.e., DP_DISABLE_HEALTHCHECKS is not set to 'all')...
      Node: cn-beijing.192.168.XXX.XXX, Static Pod: nvidia-device-plugin-cn-beijing.192.168.XXX.XXX
      Note: The above nodes will automatically isolate faulty GPUs via NVIDIA Device Plugin.

      若輸出結果中包含Note: The above nodes will automatically isolate faulty GPUs via NVIDIA Device Plugin.,則說明已開啟GPU隔離能力。

  2. 通過升級組件關閉GPU隔離能力。

    最新版本的NVIDIA Device Plugin組件已預設關閉原生的GPU隔離能力,請升級NVIDIA Device Plugin組件至最新版。

相關文檔