天天看點

NVIDIA GPU Operator分析三:NVIDIA Device Plugin安裝

背景

我們知道,如果在Kubernetes中支援GPU裝置排程,需要做如下的工作:

  • 節點上安裝nvidia驅動
  • 節點上安裝nvidia-docker
  • 叢集部署gpu device plugin,用于為排程到該節點的pod配置設定GPU裝置。

除此之外,如果你需要監控叢集GPU資源使用情況,你可能還需要安裝

DCCM exporter

結合Prometheus輸出GPU資源監控資訊。

要安裝和管理這麼多的元件,對于運維人員來說壓力不小。基于此,NVIDIA開源了一款叫

NVIDIA GPU Operator

的工具,該工具基于

Operator Framework

實作,用于自動化管理上面我們提到的這些元件。

NVIDIA GPU Operator有以下的元件構成:

  • 安裝nvidia driver的元件
  • 安裝nvidia container toolkit的元件
  • 安裝nvidia devcie plugin的元件
  • 安裝nvidia dcgm exporter元件
  • 安裝gpu feature discovery元件

本系列文章不打算一上來就開始講NVIDIA GPU Operator,而是先把各個元件的安裝詳細的分析一下,然後手動安裝這些元件,最後再來分析NVIDIA GPU Operator就比較簡單了。

在本篇文章中,我們将介紹NVIDIA GPU Operator安裝NVIDIA Device Plugin的原理。

NVIDIA Device Plugin介紹

本小節簡單的介紹一下什麼是NVIDIA Device Plugin(如果需要更詳細的了解k8s device plugin機制,請參考網上其他文檔)。在介紹NVIDIA Container Toolkit時,我們提到過,當啟動docker容器時,可以通過環境變量指定容器所需的GPU,例如:

$ docker run -d --name gpu-test -e NVIDIA_VISIBLE_DEVICES=0,1 centos:7 sleep 5000           

但是在Kubernetes叢集中應該如何給一個應用指定使用GPU呢?可以通過給pod的容器指定環境變量NVIDIA_VISIBLE_DEVICES實作嗎?可以,但是這樣做有一些問題:

  • 因為kubernetes叢集中有很多節點,每個節點的GPU數量可能不同,假設指定pod的容器的環境變量為”“NVIDIA_VISIBLE_DEVICES=3,4”,但是pod排程到節點是随機的,最終pod所在的節點如果隻有一張GPU卡,那麼pod将啟動失敗。
  • 直接在pod的容器中指定環境變量NVIDIA_VISIBLE_DEVICES,使用者無法維護哪些節點的哪些GPU已經使用,哪些未使用。

Kubernetes從1.8開始支援裝置插件機制,隻要使用者實作與裝置相對應的device plugin,然後在pod送出時指定需要使用多少個裝置,kubernetes就能為pod自動挂載裝置并且維護節點上裝置狀态(即哪些裝置已使用,哪些裝置未使用)。

NVIDIA Device Plugin的工作原理簡單的概況為:

  • pod spec中的resources.limits字段寫入運作該pod需要多少個GPU裝置,像下面這樣:
kind: Pod
metadata:
  name: gpu-pod
spec:
  containers:
    - name: gpu-container-1
      image: centos:7
      resources:
        limits:
          nvidia.com/gpu: 2 # 代表為該Pod申請了2個GPU。           
  • 每個節點的kubelet元件維護該節點的GPU裝置狀态(哪些已用,哪些未用)并定時報告給排程器,排程器知道每一個節點有多少張GPU卡可用。
  • 排程器為pod選擇節點時,從符合條件的節點中選擇一個節點。
  • 當pod排程到節點上後,kubelet元件為pod配置設定GPU裝置ID,并将這些ID作為參數傳遞給NVIDIA Device Plugin
  • NVIDIA Device Plugin将配置設定給該pod的容器的GPU裝置ID寫入到容器的環境變量NVIDIA_VISIBLE_DEVICES中,然後将資訊傳回給kubelet。
  • kubelet啟動容器。
  • NVIDIA Container Toolkit檢測容器的spec中存在環境變量NVIDIA_VISIBLE_DEVICES,然後根據環境變量的值将GPU裝置挂載到容器中。

在叢集中部署NVIDIA Device Plugin

接下來示範一下怎樣在叢集中部署nvidia device plugin。

前提條件

在進行操作之前,請确認下面的條件是否滿足:

  • 叢集的版本 > 1.8。
  • 叢集中的GPU節點已經安裝了GPU驅動,如果沒有安裝驅動,請參考本系列檔案中關于NVIDIA驅動的安裝。
  • 叢集中的GPU節點已經安裝NVIDIA Container Toolkit,如果沒有安裝,請參考本系列檔案中關于NVIDIA Container Toolkit的安裝。

安裝步驟

1.下載下傳gpu-operator源碼。

$ git clone -b 1.6.2 https://github.com/NVIDIA/gpu-operator.git
$ cd gpu-operator
$ export GPU_OPERATOR=$(pwd)            

2.确認節點已經打了标簽nvidia.com/gpu.present=true。

$ kubectl get nodes -L nvidia.com/gpu.present
NAME                       STATUS   ROLES    AGE   VERSION            GPU.PRESENT
cn-beijing.192.168.8.44    Ready    <none>   13d   v1.16.9-aliyun.1   true
cn-beijing.192.168.8.45    Ready    <none>   13d   v1.16.9-aliyun.1   true
cn-beijing.192.168.8.46    Ready    <none>   13d   v1.16.9-aliyun.1   true
cn-beijing.192.168.9.159   Ready    master   13d   v1.16.9-aliyun.1
cn-beijing.192.168.9.160   Ready    master   13d   v1.16.9-aliyun.1
cn-beijing.192.168.9.161   Ready    master   13d   v1.16.9-aliyun.1           

3.修改assets/state-device-plugin/0300_rolebinding.yaml,注釋兩個字段,否則無法送出:

  • 将userNames這一行和其後面的一行注釋。
#userNames:
#- system:serviceaccount:gpu-operator:nvidia-device-plugin           
  • 将roleRef.namespace這一行注釋。
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nvidia-device-plugin
# namespace: gpu-operator-resources           

4.修改assets/state-device-plugin/0400_device_plugin.yml,填入正确的鏡像。

  • 更改container nvidia-device-plugin-ctr的鏡像為nvcr.io/nvidia/k8s-device-plugin:v0.8.2-ubi8。
      containers:
      - image: "nvcr.io/nvidia/k8s-device-plugin:v0.8.2-ubi8"
        name: nvidia-device-plugin-ctr
        securityContext:
          privileged: true           
  • 更改initContainer toolkit-validation的鏡像為nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2。
      initContainers:
      - name: toolkit-validation
        image: "nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2"
        command: ['sh', '-c']
        args: ["/tmp/vectorAdd"]
        securityContext:
          privileged: true           

5.部署device plugin。

$ kubectl apply -f assets/state-device-plugin           

6.檢視pod是否已經處于running。

$ kubectl get po -n gpu-operator-resources -l  app=nvidia-device-plugin-daemonset
NAME                                   READY   STATUS    RESTARTS   AGE
nvidia-device-plugin-daemonset-kllvw   1/1     Running   0          78s
nvidia-device-plugin-daemonset-lxdl6   1/1     Running   0          78s
nvidia-device-plugin-daemonset-pwqb4   1/1     Running   0          78s           

7.檢視pod日志。

$ kubectl logs nvidia-device-plugin-daemonset-kllvw -n gpu-operator-resources --tail=20
2021/03/26 07:11:02 Loading NVML
2021/03/26 07:11:02 Starting FS watcher.
2021/03/26 07:11:02 Starting OS watcher.
2021/03/26 07:11:02 Retreiving plugins.
2021/03/26 07:11:02 Starting GRPC server for 'nvidia.com/gpu'
2021/03/26 07:11:02 Starting to serve 'nvidia.com/gpu' on /var/lib/kubelet/device-plugins/nvidia-gpu.sock
2021/03/26 07:11:02 Registered device plugin for 'nvidia.com/gpu' with Kubelet           

驗證

為了驗證叢集節點的GPU是否可用,可以送出一個tensorfolw任務(該任務申請了一個GPU,即nvidia.com/gpu: 1),任務的yaml如下:

$ cat /tmp/gpu-test.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-gpu
  labels:
    test-gpu: "true"
spec:
  containers:
  - name: training
    image: registry.cn-beijing.aliyuncs.com/ai-samples/tensorflow:1.5.0-devel-gpu
    command:
    - python
    - tensorflow-sample-code/tfjob/docker/mnist/main.py
    - --max_steps=300
    - --data_dir=tensorflow-sample-code/data
    resources:
      limits:
        nvidia.com/gpu: 1
    workingDir: /root
  restartPolicy: Never           

1.送出任務。

$ kubectl apply -f /tmp/gpu-test.yaml           

2.檢視pod是否處于Running。

$ kubectl get po -l test-gpu=true
NAME       READY   STATUS    RESTARTS   AGE
test-gpu   1/1     Running   0          2m54s           

3.檢視pod日志。

$ kubectl logs test-gpu  --tail 10
Accuracy at step 220: 0.9288
Accuracy at step 230: 0.936
Accuracy at step 240: 0.9393
Accuracy at step 250: 0.9405
Accuracy at step 260: 0.9409
Accuracy at step 270: 0.9428
Accuracy at step 280: 0.9399
Accuracy at step 290: 0.9408
Adding run metadata for 299
Total Train-accuracy=0.9408           

說明各個元件(nvidia driver,nvidia container toolkit, nvidia device plugin)能夠正常工作。

總結

本篇文章簡單介紹了nvidia device plugin并嘗試在k8s叢集中以daemonset方式部署nvidia device plugin,最後通過運作一個tensorflow任務驗證nvidia device plugin是否正常工作。

繼續閱讀