「Docker／Kubernetes」Kubernetesの拡張リソース・デバイスプラグインモジュール

この記事では、バージョン1.11で導入される予定の**Kubernetes**の拡張リソースとデバイスプラグインモジュールについて探っていきます。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/kubernetes-extended-resource-and-device-plugin-modules_593770)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

KubernetesのGPUのスケジューリングや運用の仕組みについて最近報じられた記事によると、バージョン1.11では従来のalpha.kubernetes.io/nvidia-gpuのメインコードを非推奨とし、GPU関連のスケジューリングやデプロイメントコードを完全にメインコードから削除し、その代わりに、Kubernetesの組み込みモジュールである**拡張リソース**と**デバイスプラグイン**の2つのモジュールと、デバイスプロバイダが開発したデバイスプラグインを組み合わせて、デバイスクラスタからワーキングノードへのスケジューリングを実装し、デバイスをコンテナでバインドするというものです。

Kubernetesの2つのモジュールについて簡単に紹介します。

- **拡張リソース**
これはカスタムリソースの拡張方法です。開発者は、リソース名とリソースの総数をAPIサーバーに報告する必要があります。スケジューラは、リソースポッド内の作成・削除に基づいて利用可能なリソース数を増減させ、スケジューリング時にリソース要件を満たすノードを決定します。拡張リソースの増分、減分は整数でなければなりません。例えば、1GPUを割り当てることはできますが、0.5GPUを割り当てることはできません。この関数は不透明な整数リソースを置き換え、いくつかの名前を変更するだけなので、バージョン1.8では安定しています。キーワード整数を削除すれば、将来的には0.5 GPUを割り当てることができるようになるのでしょうか？

- **デバイスプラグイン**
一般的なデバイスプラグイン機構と標準デバイスAPIインタフェースを提供します。機器ベンダーは、Kubeletのメインコードを変更することなく、APIを実装することで、GPU、FPGA、高性能NIC、InfiniBandなどのデバイスを拡張することができます。この機能は、Kubeernetes 1.8と1.9のAlpha版にあり、Kubeernetes 1.10のBeta版にも搭載される予定です。この機能はまだ新しい機能なので、`--feature-gate=DevicePlugins=true`に設定して有効にする必要があります。

#デバイスプラグインの設計
###API設計

実は、Device Plugin は `ListAndWatch` と `Allocate` メソッドを実装したシンプルな gRPC サーバで、`/var/lib/kubelet/deviceplugins/`以下の Unix ソケット、例えば `/var/lib/kubelet/deviceplugins/nvidia.sock` をリッスンしています。

```
service DevicePlugin {
    // returns a stream of []Device
    rpc ListAndWatch(Empty) returns (stream ListAndWatchResponse) {}
    rpc Allocate(AllocateRequest) returns (AllocateResponse) {}
}
```

これらの中では
- **ListAndWatch**：Kubelet はこの API を呼び出してデバイスを検出し、デバイスの状態を更新します (例えば、デバイスが不健康になるなど)。
- **Allocate**：Kubelet がデバイスを使用するコンテナを作成する際に、Kubelet はこの API を呼び出してデバイスに対する操作を行い、コンテナの初期化に必要なデバイス、ボリューム、環境変数の設定を取得します。


###プラグインのライフサイクル管理
プラグインが起動すると、Kubelet `/var/lib/kubelet/device-plugins/kubelet.sock` に GRPS 形式で登録し、プラグインのリスニング用 Unix ソケット、API バージョン、デバイス名 (例: nvidia.com/gpu) を提供します。Kubelet はデバイスをノードの状態で公開し、Extended Resource リクエストで API サーバに送信します。スケジューラは、その情報に基づいてデバイスをスケジュールします。

プラグインが起動すると、Kubeletはプラグインへの永続的なlistAndWatch接続を確立します。不健全なデバイスを検出すると、プラグインは自動的にKubeletに通知します。デバイスがアイドル状態であれば、Kubelet はそのデバイスを割り当て可能なリストから削除します。

プラグインは、Kubelet ソケットを使って Kubelet の状態を監視します。Kubelet が再起動すると、プラグインも再起動し、再び Kubelet に登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/106de203-210d-4cee-017c-a20a1e515b78.png)

##デプロイメント方法
一般的には、デーモンセットの展開と非コンテナ展開をサポートしています。ただし、公式にはデーモンセットの展開を推奨しています。

##実装例
**Nvidia公式GPUプラグイン**
NVIDIAは、ユーザーフレンドリーなGPUデバイスプラグイン[NVIDIA/k8s-device-plugin](https://github.com/NVIDIA/k8s-device-plugin?spm=a2c65.11461447.0.0.66055f18nlZMKr)を提供しており、これはDevice Pluginsインターフェースをベースにしています。従来の `alpha.kubernetes.io/nvidia-gpu` のように、CUDA で必要なライブラリを指定するためにボリュームを使用する必要はありません。

```
apiVersion: apps/v1
kind: Deployment

metadata:
  name: tf-notebook
  labels:
    app: tf-notebook

spec:

  template: # define the pods specifications
    metadata:
      labels:
        app: tf-notebook

    spec:
      containers:
      - name: tf-notebook
        image: tensorflow/tensorflow:1.4.1-gpu-py3
        resources:
          limits:
            nvidia.com/gpu: 1
```

#結論
Kubernetesがエコシステムでの地位を獲得したことで、拡張性はその主戦場となるでしょう。ヘテロジニアスコンピューティングは、Kubernetesにとって重要な新たな戦場となります。しかし、ヘテロジニアスコンピューティングには、強力なコンピューティングと高性能なネットワークが必要です。そのため、GPU、FPGA、NIC、InfiniBandなどの高性能なハードウェアと統一的に統合する必要があります。Kubernetes Device Pluginはシンプルで、そして今なお進化を続けています。[Alibaba Cloud Container Service](https://www.alibabacloud.com/ja/product/container-service)は、このDevice PluginをベースにしたKubernetes GPU 1.9.3クラスタの提供を開始します。

同様の記事を読んで、アリババクラウドの製品やソリューションについて詳しく知りたい方は、[www.alibabacloud.com](https://www.alibabacloud.com/ja)

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*