iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 16
0
DevOps

其實我真的沒想過要利用研替剩餘的 30 天分享那些年 On-premise Container & Kubernetes 經驗系列 第 16

[Day16] 利用 Device Plugins 提供硬體加速

前言

Device Plugins 是 Kubernetes v1.8 版本開始加入的 Alpha 功能,目標是結合 Extended Resource 來支援 GPU、FPGA、高效能 NIC、InfiniBand 等硬體設備介接的插件,這樣好處在於硬體供應商不需要修改 Kubernetes 核心程式,只需要依據 Device Plugins 介面來實作特定硬體設備插件,就能夠提供給 Kubernetes Pod 使用。而本篇會稍微提及 Device Plugin 原理,並說明如何使用 NVIDIA device plugin。

P.S. 傳統的alpha.kubernetes.io/nvidia-gpu將於 1.11 版本移除,因此與 GPU 相關的排程與部署原始碼都將從 Kubernetes 核心移除。

Device Plugins 原理

Device Plugins 主要提供了一個 gRPC 介面來給廠商實現ListAndWatch()Allocate()等 gRPC 方法,並監聽節點的/var/lib/kubelet/device-plugins/目錄中的 gRPC Server Unix Socket,這邊可以參考官方文件 Device Plugins。一旦啟動 Device Plugins 時,透過 Kubelet Unix Socket 註冊,並提供該 plugin 的 Unix Socket 名稱、API 版本號與插件資源名稱(vendor-domain/resource,例如 nvidia.com/gpu),接著 Kubelet 會將這些曝露到 Node 狀態以便 Scheduler 使用。

Unix Socket 範例:

$ ls /var/lib/kubelet/device-plugins/
kubelet_internal_checkpoint  kubelet.sock  nvidia.sock

一些 Device Plugins 列表:

節點資訊

部署沿用之前文章建置的 HA 環境進行測試,全部都採用裸機部署,作業系統為Ubuntu 18.04+:

IP Address Hostname CPU Memory Role Extra Device
172.22.132.11 k8s-m1 4 16G Master None
172.22.132.12 k8s-m2 4 16G Master None
172.22.132.13 k8s-m3 4 16G Master None
172.22.132.21 k8s-n1 4 16G Node None
172.22.132.22 k8s-n2 4 16G Node None
172.22.132.32 k8s-g2 4 16G Node GTX 1060 3G *2

事前準備

安裝 Device Plugin 前,需要確保以下條件達成:

  • 所有節點需要安裝 Docker
$ curl -fsSL "https://get.docker.com/" | sh
  • GPU 節點需正確安裝指定版本的 NVIDIA Driver 與 CUDA。
$ wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
$ sudo dpkg -i cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
$ sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
$ sudo apt-get update 
$ sudo apt-get install -y linux-headers-$(uname -r)
$ sudo apt-get -o Dpkg::Options::="--force-overwrite" install -y cuda-10-0 cuda-drivers
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

$ sudo apt-get update && sudo apt-get install -y nvidia-docker2
$ sudo systemctl restart docker

安裝 NVIDIA Device Plugin

若上述要求以符合,再開始前需要在每台 GPU worker 節點修改/lib/systemd/system/docker.service檔案,將 Docker default runtime 改成 nvidia,依照以下內容來修改:

...
ExecStart=/usr/bin/dockerd -H fd:// --default-runtime=nvidia
...

這邊也可以修改/etc/docker/daemon.json檔案,請參考 Configure and troubleshoot the Docker daemon

完成後儲存,並重新啟動 Docker:

$ sudo systemctl daemon-reload && sudo systemctl restart docker

確認上述完成,接著在主節點透過 kubectl 來部署 NVIDIA Device Plugins:

$ kubectl create -f https://gist.githubusercontent.com/kairen/bf967d566d35edda381edb9ba8659f7b/raw/ccc18711bf016d5b836280226785c1ad0282c035/nvidia-device-plugin.yml
daemonset "nvidia-device-plugin-daemonset" created

$ kubectl -n kube-system get po -o wide
NAME                                       READY     STATUS    RESTARTS   AGE       IP               NODE
...
nvidia-device-plugin-daemonset-nwx2s       1/1     Running   0          49s    10.244.255.80   k8s-g2   <none>           <none>

由於目前 NVIDIA Device Plugin 的 beta3 有問題,因此以 beat1 為主。

測試 GPU

首先執行以下指令確認是否可被分配資源:

$ kubectl get nodes "-o=custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu"
NAME     GPU
k8s-g2   2
...

當 NVIDIA Device Plugins 部署完成後,即可建立一個簡單範例來進行測試:

$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  restartPolicy: Never
  containers:
  - image: nvidia/cuda
    name: cuda
    command: ["nvidia-smi"]
    resources:
      limits:
        nvidia.com/gpu: 1
EOF
pod "gpu-pod" created

$ kubectl get po -o wide
NAME                     READY   STATUS      RESTARTS   AGE     IP              NODE     NOMINATED NODE   READINESS GATES
gpu-pod                  0/1     Completed   0          21m     10.244.255.81   k8s-g2   <none>           <none>

$ kubectl logs gpu-pod
Sat Oct 01 15:28:38 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.87.01    Driver Version: 418.87.01    CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 106...  Off  | 00000000:05:00.0 Off |                  N/A |
|  0%   38C    P8     6W / 120W |      0MiB /  3019MiB |      1%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

從上面結果可以看到 Kubernetes Pod 正確的使用到 NVIDIA GPU。

結語

Kubernetes 提供了 Device Plugin Interface 來讓硬體供應商實現自家硬體與 Kubernetes 整合的功能,這使 Kubernetes 社區不在需要維護各種廠商的硬體整合程式,以減少核心程式碼的複雜性,一方面能更加專注在規範 Device Plugin 標準的事情。

Reference


上一篇
[Day15] 自建私有容器儲存庫(Container Registry)與實現內容信任(Content Trust)
下一篇
[Day17] Kubernetes 邊緣運算 - 淺談 K3s Part1
系列文
其實我真的沒想過要利用研替剩餘的 30 天分享那些年 On-premise Container & Kubernetes 經驗30

尚未有邦友留言

立即登入留言