Slide 1

Slide 1 text

kubernetesでGPUを 管理するために スケジューラをいじってみた

Slide 2

Slide 2 text

● 名前:上村 真也(@uesyn) ● 所属:KDDI株式会社 ● 主な業務内容 ○ 新しいサーバインフラ基盤の検証 (NFV向け/コンテナ/GPU) ○ NFV人材育成講師 ● 趣味 ○ ゲーム(特にFPS) 自己紹介 Gopher君

Slide 3

Slide 3 text

皆さん kubernetes 使ってますか?

Slide 4

Slide 4 text

それでは本題

Slide 5

Slide 5 text

背景〜ある会社の研究所のお話〜 ● 研究者がGPUを欲しがる ● GPUを割り当てたリソースをユーザに提供(手動) GPUを1つください 研究者 研究者 兼 研究所インフラ担当者 はい、どうぞ 社内の GPU搭載サーバ群

Slide 6

Slide 6 text

Problems 丹精込めた愛情たっぷり手作り GPUリソース ● 管理者がボトルネックとなり払い出しに時間がかかる 社内で利用するGPUリソースを共通化できていない ● 規模の経済が働かない パブリッククラウドの GPUリソースを利用できない ● 社外に出せないデータの存在 ● 必然的に社内基盤が必要 共通GPU演算基盤が必要!!!

Slide 7

Slide 7 text

Can we solve them with kubernetes? 7

Slide 8

Slide 8 text

GPUをkubernetesで管理する 検証環境を作ってみました!

Slide 9

Slide 9 text

kubernetes Master GPU Servers CPU Servers Ingress Controller(ユーザごとに分離) ストレージ Kubernetesのワーカーノード GPUを使わない処理用 実際に作った環境の構成

Slide 10

Slide 10 text

基板上に作ったサンプルアプリ アプリについて ● 動画上の物体検出 ● アップロードされた動画を リアルタイム処理 ・解析するワーカーをいつでも増減可能   ・GPUでもCPUでも解析可能

Slide 11

Slide 11 text

やったこと 1) GPUを使うコンテナのスケジューリング 2) 1クラスタでマルチテナント環境な基盤 ● GPU搭載ノードは共有 ● GPU非搭載ノードは専有 3) コンテナ基盤のセキュリティの検証 ● スケジューラに関しては ドキュメントがない部分も。。。 ● セキュリティは社内利用なので甘々に 今日はここのお話

Slide 12

Slide 12 text

kubernetesのGPUリソースの管理 ● kubeletでは最小限のデバイスディスカバリのみサポート ○ CPUやメモリやディスク ○ GPUは標準で管理されない ● ベンダー固有のデバイスはExtended ResourceとDevice Pluginとで管理

Slide 13

Slide 13 text

Extended ResourceとDevice Plugin Extended Resource ● Built-inされているリソース以外の数を表現 ○ ResourceNameと数(integer) ○ 0.5個GPUが欲しいといった要求不可能 ● コンテナ間の共有・オーバーコミット不可能 Device Plugin ● ベンダー固有デバイスを kubeletへ通知 ● デバイスをAllocateする情報をkubeletへ渡す ● kubernetesのコアコードをいじらず実装可能 ● NVIDIAのGPUを扱うにはNVIDIA/k8s-device-plugin ○ https://github.com/NVIDIA/k8s-device-plugin

Slide 14

Slide 14 text

Device Pluginについて ● Registry ○ Device Pluginをkubeletへ登録 ○ 利用するExtended ResourceNameを通知 ● ListAndWatch ○ 利用可能なデバイスをkubeletへ通知 ● Allocate ○ コンテナ作成前にCRI-Specへ下記の値を挿入 ■ 環境変数 ■ マウント ■ デバイス ■ アノテーション 出典:https://github.com/kubernetes/community/blob/master/contributors/ design-proposals/resource-management/device-plugin.md

Slide 15

Slide 15 text

NVIDIAのGPU用Device Pluginのコードを読んでみると・・・ 15 NVIDIA/k8s-device-plugin ● NVIDIAのGPUをkubernetesで扱うためのDevice Plugin ● Allocateで実装されているのは 環境変数をコンテナ作成時に挿入するのみ https://github.com/NVIDIA/k8s-device-plugin/blob/v1.10/server.go

Slide 16

Slide 16 text

Device PluginだけじゃGPUは使えない! NVIDIA container runtime ● コンテナでNVIDIAのGPUを利用できるようにしたものの総称 ○ libnvidia-containerやツール等 ● 特定の環境変数(NVIDIA_VISIBLE_DEVICES)が入っていればGPUを割り当て ● OCIで定義されるprestart hookでnvidia-container-runtime-hookを呼び出す ○ コイツがGPUをコンテナに割り当てる 出典:https://devblogs.nvidia.com/wp-content/uploads/2018/05/pasted-image-0-27.png

Slide 17

Slide 17 text

GPUを持ったコンテナの起動 ● CPUやmemoryのようにrequests, limitsを指定して利用 ● GPUの場合limitsのみで動作 ○ limitsのみを指定した場合requestsも同じ値になる ○ requestsを書く場合limitsも同じ値を指定する必要

Slide 18

Slide 18 text

GPUコンテナのスケジューリングの課題 実際に発生した状況 ● GPUを2つ搭載するノードが2台ある ● 以下の順番でPodを起動 1. GPUを1つ使うPod① → ○ 2. GPUを1つ使うPod② → ○ 3. GPUを2つ使うPod③ → X ● でも2つのGPU空きリソースが存在 ノード1 ノード2 Pod① Pod③ Pod②

Slide 19

Slide 19 text

GPUコンテナのスケジューリングの課題 理想としては・・・ ● リソース効率を考えると GPUは使用率が高くなるように 埋まってくれると嬉しい ノード1 ノード2 Pod③ Pod② Pod①

Slide 20

Slide 20 text

スケジューリングを実施するコンポーネント kube-apiserver kube-scheduler kube-controller-manager kubelet kube-proxy これがスケジューリングする マスター側 ノード側

Slide 21

Slide 21 text

スケジューラの設定を変えれば いけるんじゃないか?

Slide 22

Slide 22 text

kubernetesのスケジューリング ● kube-schedulerがPodをスケジューリング ○ Predicates ■ Podを配置可能なノードを通すフィルタ ○ Priorities ■ Podが配置できるノードの中で最適なノードを決定 ノード A ノード B ノード C ノード A ノード B Predicates (フィルタ) ノード C Priorities (ランキング付け) ノード A ノード B この設定を変更すれば…?

Slide 23

Slide 23 text

Prioritiesのざっくりとした仕組み PriorityC のスコア PriorityA のスコア PriorityB のスコア 重み 重み 合計がノードのスコア Priorities ● いくつかのPriorityを付ける処理の組み合わせで構成 ○ 例: ■ LeastRequestedPriority: PodのリソースのRequest合計が少ないノード優先 ■ BalancedResourcePriority: CPUとメモリの使用率のバランスをとるように 重み

Slide 24

Slide 24 text

使えそうなPriorityを探してみた(1/2) ● pkg/scheduler/algorithm/prioritiesの中で使えそうなPriorityはないか? ○ ImageLocalityPriority ○ InterPodAffinityPriority ○ NodeAffinityPriority ○ NodeLabelPriority ○ NodePreferAvoidPodsPriority ○ ResourceLimitsPriority ○ SelectorSpreadPriority ○ TaintTolerationPriority ○ LeastRequestedPriority ○ BalancedResourcePriority ○ MostRequestedPriority ● 漏れがあったらごめんなさい 使えそう?

Slide 25

Slide 25 text

● CPUとメモリの使用率が高いノードを優先的にコンテナを起動する設定は存在 ● GPU(Extended Resource)は対象外 https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/scheduler/algorithm/priorities/most_requested.go 使えそうなPriorityを探してみた(2/2)

Slide 26

Slide 26 text

なら、スケジューラを拡張 するしかない!

Slide 27

Slide 27 text

kubernetesのschedulerの拡張方法 1. kube-schedulerに手を加えて、既存のものと置き換える ● 基盤をVerUPするたびに手を加える必要があり 2. Multiple-scheduler ● 実はkubernetesでは複数のスケジューラを起動可能 ■ 実際に使うスケジューラはどれか一つ ■ 既存のものと拡張したものを配置すれば ● PodのSpecにスケジューラを指定 ● ユーザ側の操作が不可欠なため、好ましい方法ではない 3. Scheduler extender ● kube-schedulerが呼び出す外部APIとして実装される 今回はこれを採用

Slide 28

Slide 28 text

Scheduler extenderの作り方 Scheduler extenderを利用したスケジューリング kube-scheduler Predicates kube-scheduler Priorities ノード A ノード B ノード scheduler-extender Predicates scheduler-extender Priorities ● 標準のkube-schedulerで管理されていないリソースのスケジューリングのために必要だと書いてあった 出典:https://github.com/kubernetes/community/blob/master/contributors/design-proposals/scheduling/scheduler_extender.md

Slide 29

Slide 29 text

Scheduler Extenderをこんな感じで作ろう ノード1 ノード2 ● GPUの専有枚数の多いほどがスコアが高くなるように ○ Priorityのみ実装 ● スコア =  ( リクエストGPU数 + ノード上の専有されている GPU数) / ノードが持ってるGPU数 * 10 ○ Maxが10になるように正規化 ■ Priorityのルール Pod① GPUを1つください スコア = (1+1) / 2 * 10 = 10 スコア = (1+0) / 2 * 10= 5

Slide 30

Slide 30 text

Scheduler extenderの実装 ● ↓こんなリクエストがくるので https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/scheduler/api/types.go

Slide 31

Slide 31 text

Scheduler extenderの実装 ● ↑こんなリプライを返してあげる https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/scheduler/api/types.go https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/scheduler/api/types.go

Slide 32

Slide 32 text

実装していい感じに動きました!

Slide 33

Slide 33 text

Scheduler Extenderが動作していない時の挙動 https://github.com/kubernetes/kubernetes/blob/release-1.11/pkg/scheduler/api/v1/types.go ● v1.10 ○ Ignorableがtrueの挙動 ● v1.11 ○ Configで設定可

Slide 34

Slide 34 text

Scheduler Extenderが動作していない時の挙動 https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/scheduler/api/v1/types.go

Slide 35

Slide 35 text

GPU何枚使ってるかどうやって調べるの? ~ノード単位で見る場合①~ ● とりあえずkubectl describe node (Client v1.10) 何枚使ってるかわからん!

Slide 36

Slide 36 text

GPU何枚使ってるかどうやって調べるの? ~ノード単位で見る場合②~ ● とりあえずkubectl describe node (Client v1.11) ○ 1.11からExtended ResourceのAllocated resoucesも見れるように!

Slide 37

Slide 37 text

GPU何枚使ってるかどうやって調べるの? ~クラスタ全体で見る場合~ ● kube-state-metricを使う ○ v1.4.0からExtended Resourceもmetricsとして収集可能に! https://github.com/kubernetes/kube-state-metrics/pull/451

Slide 38

Slide 38 text

おわり