はじめに
Note:
pluginのデモはR640にFPGA1枚刺し環境では動いたのだが,
R740にFPGA2枚刺し環境だとnlb3(コンテナ内の実行ファイルの名前)がFPGAデバイスを見つけられなかった
./nlb3 -B 0x86
みたいにちゃんとデバイス指定をすれば動くのでデモのtest_fpga.sh
で2枚刺しを想定した呼び出し方をしていないのが問題っぽい
もう一度確認してみたところちゃんと動きました
追記:
openvino_container_for_PAC
このプラグインを用いてOpenVINOのJobをFPGAで動かす方法をgithubにまとめてupしておきました(結構雑ですが)
kubernetesの公式ページにDevice Pluginsがいくつか載っていますが,
その中でも「intel device plugins for kubernetes」を動かすまでのエントリです.
環境 (準備物)
今回はこのプラグインを使用してFPGAがスケジューリングされるかを確認したいので,
Intel PACが刺さったPowerEdge R640をk8sノードとして追加し,PACのドライバを入れておきます.
また,デバイスプラグインをコンパイルするためにGoをインストールしておきます.
- R640 (with Intel PAC)
- ↑をk8sのノードとして追加
- Acceleration Stack環境をインストール
- Go言語環境をインストール
プラグインのインストール
準備ができたらプラグインのインストールを進めていきます.
プラグインを動かすためには下記の3つが必要となります.
CRD (Custom Resource Definition) を使っているらしい.
- FPGA device plugin
- FPGA admission controller webhook
- FPGA prestart CRI-O hook
1. FPGA device plugin
ここでの作業は,FPGAサーバで行う
device pluginの設定は全てのFPGAサーバで行う必要がある(★1 or ★2あたり).
imageの配布もお忘れなく.
ソースコードを入手
$ mkdir -p $GOPATH/src/github.com/intel/
$ cd $GOPATH/src/github.com/intel/
$ git clone https://github.com/intel/intel-device-plugins-for-kubernetes.git
device pluginのビルド
Goでビルドを行うためGo自体のインストールとGOPATH
の設定を予めしておく必要がある.
$ cd $GOPATH/src/github.com/intel/intel-device-plugins-for-kubernetes
$ make fpga_plugin
kubelet のソケットが /var/lib/kubelet/device-plugins/
ディレクトリに存在するか確認する
$ ls /var/lib/kubelet/device-plugins/kubelet.sock
/var/lib/kubelet/device-plugins/kubelet.sock
device pluginの動作モードを選ぶ
FPGA device pluginは af
モードと region
モードがあり,どちらかを選択する必要がある.
af
モードは予めAFUを書き込んだFPGAを公開するモード.AFU IDをリソースとして登録することができる.
region
モードはFPGAのPA(Partial reconfiguration Area)そのものを公開するモード.FPGAのインタフェースIDをリソースとして登録できる.
という認識...間違ってたら直します
af
にしたい人は★1へ, region
にしたい人は★2へお進み下さい.
自分は,demo (test-fpga-region.yaml) を動かしたいので★1に進みました.
(regionと名前がついているが,afリソースを指定していた)
★1(Case1) Run FPGA device plugin in af mode
1.k8sのadmin権限でプラグインを実行する
$ export KUBE_CONF=/var/run/kubernetes/admin.kubeconfig # path to kubeconfig with admin's credentials
$ export NODE_NAME="<node name>" # if the node's name was overridden and differs from hostname
$ sudo -E $GOPATH/src/github.com/intel/intel-device-plugins-for-kubernetes/cmd/fpga_plugin/fpga_plugin -mode af -kubeconfig $KUBE_CONF
FPGA device plugin started in af mode
device-plugin start server at: /var/lib/kubelet/device-plugins/fpga.intel.com-af-f7df405cbd7acf7222f144b0b93acd18.sock
device-plugin registered
2.FPGAサーバにデバイスプラグインが登録されたかを確認する
プラグインを導入した時点でnodeのcapacityとallocatableにFPGAリソースが現れ,FPGAの利用可能な数が表示されるようになります.
$ kubectl describe node <node name> | grep fpga.intel.com
fpga.intel.com/af-f7df405cbd7acf7222f144b0b93acd18: 1
fpga.intel.com/af-f7df405cbd7acf7222f144b0b93acd18: 1
★2(Case2) Run FPGA device plugin in region mode
1.k8sのadmin権限でプラグインを実行する
$ export KUBE_CONF=/var/run/kubernetes/admin.kubeconfig # path to kubeconfig with admin's credentials
$ export NODE_NAME="<node name>" # if the node's name was overridden and differs from hostname
$ sudo -E $GOPATH/src/github.com/intel/intel-device-plugins-for-kubernetes/cmd/fpga_plugin/fpga_plugin -mode region -kubeconfig $KUBE_CONF
FPGA device plugin started in region mode
device-plugin start server at: /var/lib/kubelet/device-plugins/fpga.intel.com-region-ce48969398f05f33946d560708be108a.sock
device-plugin registered
Check if FPGA device plugin is registered on master:
2.FPGAサーバにデバイスプラグインが登録されたかを確認する
$ kubectl describe node <node name> | grep fpga.intel.com
fpga.intel.com/region-ce48969398f05f33946d560708be108a: 1
fpga.intel.com/region-ce48969398f05f33946d560708be108a: 1
3.region
の場合はnodeにアノテーション設定する
kubectl annotate node mynode "fpga.intel.com/device-plugin-mode=region
Deploy FPGA device plugin as DaemonSet
1.プラグイン用のサービスアカウントを作成する
$ kubectl create -f deployments/fpga_plugin/fpga_plugin_service_account.yaml
serviceaccount/intel-fpga-plugin-controller created
clusterrole.rbac.authorization.k8s.io/node-getter created
clusterrolebinding.rbac.authorization.k8s.io/get-nodes created
2.デーモンセットの作成
$ kubectl create -f deployments/fpga_plugin/fpga_plugin.yaml
daemonset.apps/intel-fpga-plugin created
3.イメージの作成
$ make intel-fpga-plugin
このイメージはデフォルトで af
モードとして動作するので, region
モードで動かしたいときは,先程のアノテーション設定が必要.
2. FPGA admission controller webhook
webhookイメージの作成
$ export SRC=$GOPATH/src/github.com/intel/intel-device-plugins-for-kubernetes
$ cd $SRC
$ make intel-fpga-admissionwebhook
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
intel-fpga-admissionwebhook 089ab82d18cceed0217e36a1600d9462018f44d5 267bd3a2524f 7 sec ago 25.2MB
intel-fpga-admissionwebhook devel 267bd3a2524f 7 sec ago 37.7MB
webhooサービスのデプロイ
cfssl
と jq
が必要らしいのでインストールしてない人は先にインストールしてから scripts/webhook-deploy.sh
実行しましょう.
$ cd $SRC
$ ./scripts/webhook-deploy.sh
Create secret including signed key/cert pair for the webhook
Creating certs in /tmp/tmp.Ebb77GBKqm
certificatesigningrequest.certificates.k8s.io/intel-fpga-webhook-svc.default created
NAME AGE REQUESTOR CONDITION
intel-fpga-webhook-svc.default 0s system:admin Pending
certificatesigningrequest.certificates.k8s.io/intel-fpga-webhook-svc.default approved
secret/intel-fpga-webhook-certs created
Removing /tmp/tmp.Ebb77GBKqm
Create FPGA CRDs
customresourcedefinition.apiextensions.k8s.io/acceleratorfunctions.fpga.intel.com created
customresourcedefinition.apiextensions.k8s.io/fpgaregions.fpga.intel.com created
acceleratorfunction.fpga.intel.com/arria10-nlb0 created
acceleratorfunction.fpga.intel.com/arria10-nlb3 created
fpgaregion.fpga.intel.com/arria10 created
clusterrole.rbac.authorization.k8s.io/fpga-reader created
clusterrolebinding.rbac.authorization.k8s.io/default-fpga-reader created
Create webhook deployment
deployment.extensions/intel-fpga-webhook-deployment created
Create webhook service
service/intel-fpga-webhook-svc created
Register webhook
mutatingwebhookconfiguration.admissionregistration.k8s.io/fpga-mutator-webhook-cfg created
CRDのリソース定義については af
が ./deployment/fpga_admissionwebhook/af-crd.yaml
,
region
が ./deployment/fpga_admissionwebhook/region-crd.yaml
にあります.
また, AFU ID/Interface ID のマッピングにはmappings-collection.yaml
を使います.
例えば,podが要求するリソースに fpga.intel.com/arria10-nlb3
と書くと,
fpga.intel.com/af-f7df405cbd7acf7222f144b0b93acd18
に翻訳され,
fpga.intel.com/af-f7df405cbd7acf7222f144b0b93acd18
をAllocatableにもつノードにpodが立てられます.
3. FPGA prestart CRI-O hook
CRI-O hookのビルド
$ cd $GOPATH/src/github.com/intel/intel-device-plugins-for-kubernetes
$ make fpga_crihook
'Acceleration Stack for Runtime' のダウンロード
a10_gx_pac_ias_1_1_pv_rte_installer.tar.gz
をココからダウンロードして $GOPATH/src/github.com/intel/intel-device-plugins-for-kubernetes/deployments/fpga_plugin
ディレクトリに保存する
CRI hookとその依存関係など含む init コンテナをビルド
$ cd $GOPATH/src/github.com/intel/intel-device-plugins-for-kubernetes/deployments/fpga_plugin
$ ./build-initcontainer-image.sh
...
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
intel-fpga-initcontainer devel 8d9c9adca145 6 days ago 19MB
intel-fpga-initcontainer e30f8763c7209577fbaa720addd80271214e8bec 8d9c9adca145 6 days ago 19MB
4. check plugin
プラグインが正しくインストールされたかを確認します.
うまく動いていない場合,動作に必要なimageがノードに配布されているかを確認しましょう.
kubectl get all
うまく動いていれば, pod/intel-fpga-plugin-xxxxx
と xxx/intel-fpga-webhook-xxxx
のステータスがrunningやavailableになっているはずです.
$ k get all --all-namespaces
## POD
NAMESPACE NAME READY STATUS RESTARTS AGE
default pod/intel-fpga-webhook-deployment-7688655c78-9q4kp 1/1 Running 3 6d6h
kube-system pod/intel-fpga-plugin-zlzn9 1/1 Running 0 5d21h
...
## Service
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/intel-fpga-webhook-svc ClusterIP 10.109.230.217 <none> 443/TCP 6d6h
...
## deployment
NAMESPACE NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
default deployment.apps/intel-fpga-webhook-deployment 1 1 1 1 6d6h
...
## replicaset
NAMESPACE NAME DESIRED CURRENT READY AGE
default replicaset.apps/intel-fpga-webhook-deployment-7688655c78 1 1 1 6d6h
kubectl describe
FPGAノードの状態確認
$ k describe no r640-2
Name: r640-2
Roles: <none>
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/hostname=r640-2
Annotations: flannel.alpha.coreos.com/backend-data: {"VtepMAC":"**:**:**:**:**:**"}
flannel.alpha.coreos.com/backend-type: vxlan
flannel.alpha.coreos.com/kube-subnet-manager: true
flannel.alpha.coreos.com/public-ip: *.*.*.*
fpga.intel.com/device-plugin-mode: region
kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Wed, 28 Nov 2018 16:48:15 +0900
Taints: <none>
Unschedulable: false
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
OutOfDisk False Wed, 05 Dec 2018 17:02:18 +0900 Sat, 01 Dec 2018 12:15:51 +0900 KubeletHasSufficientDisk kubelet has sufficient disk space available
MemoryPressure False Wed, 05 Dec 2018 17:02:18 +0900 Sat, 01 Dec 2018 12:15:51 +0900 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Wed, 05 Dec 2018 17:02:18 +0900 Sat, 01 Dec 2018 12:15:51 +0900 KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False Wed, 05 Dec 2018 17:02:18 +0900 Wed, 28 Nov 2018 16:48:15 +0900 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Wed, 05 Dec 2018 17:02:18 +0900 Sat, 01 Dec 2018 12:15:51 +0900 KubeletReady kubelet is posting ready status
Addresses:
InternalIP: *.*.*.*
Hostname: r640-2
Capacity:
cpu: 16
ephemeral-storage: 51171Mi
fpga.intel.com/af-d8424dc4a4a3c413f89e433683f9040b: 0
fpga.intel.com/af-f7df405cbd7acf7222f144b0b93acd18: 0
fpga.intel.com/region-9926ab6d6c925a68aabca7d84c545738: 1
hugepages-1Gi: 0
hugepages-2Mi: 40Mi
memory: 131484456Ki
pods: 110
Allocatable:
cpu: 16
ephemeral-storage: 48291014167
fpga.intel.com/af-d8424dc4a4a3c413f89e433683f9040b: 0
fpga.intel.com/af-f7df405cbd7acf7222f144b0b93acd18: 0
fpga.intel.com/region-9926ab6d6c925a68aabca7d84c545738: 1
hugepages-1Gi: 0
hugepages-2Mi: 40Mi
memory: 131341096Ki
pods: 110
System Info:
Machine ID: *
System UUID: *
Boot ID: *
Kernel Version: 3.10.0-693.el7.x86_64
OS Image: CentOS Linux 7 (Core)
Operating System: linux
Architecture: amd64
Container Runtime Version: docker://18.9.0
Kubelet Version: v1.12.3
Kube-Proxy Version: v1.12.3
PodCIDR: 10.244.2.0/24
Non-terminated Pods: (3 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
--------- ---- ------------ ---------- --------------- -------------
kube-system intel-fpga-plugin-bhswp 0 (0%) 0 (0%) 0 (0%) 0 (0%)
kube-system kube-flannel-ds-amd64-4cdnl 100m (0%) 100m (0%) 50Mi (0%) 50Mi (0%)
kube-system kube-proxy-4v7x8 0 (0%) 0 (0%) 0 (0%) 0 (0%)
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 100m (0%) 100m (0%)
memory 50Mi (0%) 50Mi (0%)
fpga.intel.com/af-d8424dc4a4a3c413f89e433683f9040b 0 0
fpga.intel.com/af-f7df405cbd7acf7222f144b0b93acd18 0 0
fpga.intel.com/region-9926ab6d6c925a68aabca7d84c545738 0 0
Events: <none>
Running demo
Run demo
ここでは NLB (ネイティブループバック) のAFUが書き込まれたAFリソースを指定してうごかすデモを行います.
※実際には test-fpga-region.yml
というファイルですが,
リポジトリ内は yml
と yaml
が混在していたので,Qiitaでは yaml
で統一してます.
cd $GOPATH/src/github.com/intel/intel-device-plugins-for-kubernetes/demo
kubectl apply -f test-fpga-region.yaml
Check Status
実行後, Completed
となっていればスケジューリングは正しく動いています.
$ kubectl get po
NAME READY STATUS RESTARTS AGE
test-fpga-region 0/1 Completed 0 81m
Check log
また,コンテナの標準出力を確認して,問題なくFPGAが動いているかも確認.
$ kubectl logs test-fpga-region
Running nlb3
Cachelines Read_Count Write_Count Cache_Rd_Hit Cache_Wr_Hit Cache_Rd_Miss Cache_Wr_Miss Eviction 'Clocks(@200 MHz)' Rd_Bandwidth Wr_Bandwidth
1 1 0 0 0 0 0 0 142 0.090 GB/s 0.000 GB/s
VH0_Rd_Count VH0_Wr_Count VH1_Rd_Count VH1_Wr_Count VL0_Rd_Count VL0_Wr_Count
1 1 0 0 0 0
nlb3 succeeded as expected
Running nlb0 sample
Error: device enumeration failed.
Please make sure that the driver is loaded and that a bitstream for
AFU id: D8424DC4-A4A3-C413-F89E-433683F9040B is programmed.
nlb0 failed as expected
SUCCESS
もし以下のようにnlb3が実行できないと怒られたらPACに書き込まれているbitstreamを確認する.
kubectl logs test-fpga-region
Running nlb3
Error: device enumeration failed.
Please make sure that the driver is loaded and that a bitstream for
AFU id: F7DF405C-BD7A-CF72-22F1-44B0B93ACD18 is programmed.
nlb3 failed
FAILURE: unexpeced nlb3 failure
bitstream の書き換え
以下は,AFU IDの確認方法と,nlb3の書き込み方法です.
$ cat /sys/class/fpga/intel-fpga-dev.0/intel-fpga-port.0/afu_id
d8424dc4a4a3c413f89e433683f9040b
$ sudo fpgaconf $OPAE_PLATFORM_ROOT/hw/samples/nlb_mode_3/bin/nlb_mode_3.gbs
$ cat /sys/class/fpga/intel-fpga-dev.0/intel-fpga-port.0/afu_id
f7df405cbd7acf7222f144b0b93acd18
おわりに
今回はk8sでFPGAをスケジューリングを試してみましたが,
今度はOpenVINOのコンテナイメージを用意していろいろ試したいなーと思います.
以下model optimizerをk8s上で動かしたという内容
https://ai.intel.com/openvino-model-server-boosts-ai-inference-operations/
Appendix. AFU ID
filename | afuid |
---|---|
hello_afu.gbs | 850adcc2-6ceb-4b22-9722-d43375b61c66 |
hello_intr_afu.gbs | 850adcc2-6ceb-4b22-9722-d43375b61c66 |
hello_mem_afu.gbs | 35f9452b-25c2-434c-93d5-6f8c60db361c |
dma_afu.gbs | 331DB30C-9885-41EA-9081-F88B8F655CAA |
streaming_dma_afu.gbs | eb59bf9d-b211-4a4e-b3e3-753ce68634ba |
eth_e2e_e10.gbs | 05189fe4-0676-dd24-b74f-291af34e1783 |
eth_e2e_e40.gbs | 26b40788-034b-4389-b3c1-51a1b62ed6c2 |
nlb_mode_0.gbs | d8424dc4-a4a3-c413-f89e-433683f9040b |
nlb_mode_3.gbs | f7df405c-bd7a-cf72-22f1-44b0b93acd18 |