Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

実際に運用してわかった! 多種GPU混載Kubernetesクラスタの使われ方と運用省力化

実際に運用してわかった! 多種GPU混載Kubernetesクラスタの使われ方と運用省力化

オンプレでKubernetesクラスタを運用している、PFNのClusterServicesチームの取り組みを紹介します。特に、GPU混載対応やCPUリソース利用効率向上への取り組みを深く取り上げます。

イベントサイト: https://cloudnativedays.connpass.com/event/300864/

Preferred Networks

November 27, 2023
Tweet

More Decks by Preferred Networks

Other Decks in Technology

Transcript

  1. 2 • 2023/08 - ◦ セキュリティチーム (CSO) ◦ Cluster Servicesチーム

    ▪ 兼任 • 2019/08 - ◦ Preferred Networks ◦ Cluster Servicesチーム ▪ オンプレk8s, AWS/GCP • 2014/04 - 2019/07(新卒) ◦ 株式会社ディー・エヌ・エー ◦ セキュリティ技術グループ ◦ 脆弱性診断・チート対策・CSIRT 自己紹介: 汐田 徹也 (Tetsuya Shiota) 2
  2. 3 • PFNのクラスタ構成 • 多種GPU混載クラスタへPodをスケジュールする際の工夫 ◦ GPU指定の方法の複雑さ ◦ GPU Selection

    Specの導入と実装 ◦ 実際のPFNユーザのGPU要求の指定状況 • GPUノードのCPU資源の有効活用 ◦ GPUに対するCPU不足は避けたい ◦ GPUノードのCPU資源の有効活用 ◦ さらに踏み込んだ活用 • 多種GPUに対応したGPU障害の自動検査・自動復旧の仕組み ◦ kube-nvidia-active-monitorによるアーキテクチャを問わない障害 検知 今日話すこと 3
  3. 5 単一k8sクラスタで複数種類のGPUが利用可能 36 cores 384 GB V100 GPU x 8

    100 GbE x 4 128 nodes MN-2a 48 cores 384 GB MN-Core x 4 100 GbE x 4 48 nodes MN-3 128 cores 1,024 GB A100 GPU x 4 100 GbE x 2 42 nodes MN-2b 80 cores 512 GB A30 GPU x 6 100 GbE x 2 42 nodes Icons by https://icons8.com 合計 260 nodes, 1,444 GPU + 192 MN-Core 単一のKubernetesクラスタとして管理 5
  4. 7 PFNではPodのスケジューリングに様々な工夫を行っています - 目的: - リソース利用効率の向上 - オンプレはリソースを使い切らないと損 - 平等性・配分適正化

    - 経営上の優先度と計算資源の割り当ての乖離がないようにする - PFNが実施している手段: - 導入工数低: - AdmissionWebhookによるMutation - Label, Taint, Tolerationによるノード指定 - 導入工数高: - SchedulerPluginによるスケジューラのカスタマイズ - CustomResourceの開発 GPU混載クラスタへPodをスケジュールする際の工夫 7
  5. 8 PFNではPodのスケジューリングに様々な工夫を行っています - 目的: - リソース利用効率の向上 - オンプレはリソースを使い切らないと損 - 平等性・配分適正化

    - 経営上の優先度と計算資源の割り当ての乖離がないようにする - PFNが実施している手段: - 導入工数低: - AdmissionWebhookによるMutation - Label, Taint, Tolerationによるノード指定 - 導入工数高: - SchedulerPluginによるスケジューラのカスタマイズ - CustomResourceの開発 GPU混載クラスタへPodをスケジュールする際の工夫 今日話す 今日話す 8
  6. 9 要求: GPUが1枚ほしい GPU指定の想定パターン(V100のみ時代) apiVersion: v1 kind: Pod spec: containers:

    - resources: limits: nvidia.com/gpu: 1 Kubernetesクラスタ V100 x 1 V100 x 1 9
  7. 10 要求: V100 vram32GBモデル nodeSelectorで対応 GPU指定の想定パターン(V100のみ時代) apiVersion: v1 kind: Pod

    spec: nodeSelector: gpu-model: v100-32gb containers: - resources: limits: nvidia.com/gpu: 1 Kubernetesクラスタ V100(16GB) V100(32GB) gpu-model: v100-32gb Nodeにラベル を付与 10
  8. 11 要求: できればV100-16GB V100-32GBでも可 => preferredDuringScheduling GPU指定の想定パターン(V100のみ時代) apiVersion: v1 kind:

    Pod spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: gpu-model operator: In values: - v100-16gb containers: - resources: limits: nvidia.com/gpu: 1 Kubernetesクラスタ V100(16GB) V100(32GB) gpu-model: v100-32gb gpu-model: v100-16gb 11
  9. 12 2022年からGPUの種類が増えて従来よりも複雑になってきた (実際はコストの高いGPUはtolerationが必要などもっと複雑) • できればV100-16GB, V100-32GBでも可 ◦ requiredDuringSchedulingIgnoredDuringExecutionでモデルを指定 ◦ preferredDuringSchedulingIgnoredDuringExecutionで優先度を指定

    • A100が使いたい ◦ モデル名を指定するラベルを使ってnodeSelectorで対応 • vram 32GB以上でできるだけコストの低いGPUが使いたい ◦ vram量のラベルを列挙 ◦ preferredDuringSchedulingIgnoredDuringExecutionも指定 GPU指定の想定パターン(A30, A100, V100混載) 12
  10. 13 課題: 指定方法がKubernetesに慣れていないと難しい! • できればV100-16GB, V100-32GBでも可 ◦ requiredDuringSchedulingIgnoredDuringExecutionでモデルを指定 ◦ preferredDuringSchedulingIgnoredDuringExecutionで優先度を指定

    • A100が使いたい ◦ モデル名を指定するラベルを使ってnodeSelectorで対応 • vram 32GB以上でできるだけコストの低いGPUが使いたい ◦ vram量のラベルを列挙 ◦ preferredDuringSchedulingIgnoredDuringExecutionも指定 GPU指定の想定パターン(A30, A100, V100混載) 13
  11. 14 そもそも記法が やりたいこと(GPUを指定したい) に対して複雑。 「GPUをどう使いたいか」という 関心事に関する記載が、 manifest内で分散している GPU指定の想定パターン(A30, A100, V100混載)

    apiVersion: v1 kind: Pod spec: nodeSelector: gpu-arch: volta affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: gpu-model operator: In values: - v100-16gb containers: - resources: limits: nvidia.com/gpu: 1 14
  12. 15 課題: ユーザはクラスタでどんなラベルが利用可能なのか把握難しい 今後も管理者が勝手に変える可能性がある • できればV100-16GB, V100-32GBでも可 ◦ requiredDuringSchedulingIgnoredDuringExecutionでモデルを指定 ◦

    preferredDuringSchedulingIgnoredDuringExecutionで優先度を指定 • A100が使いたい ◦ モデル名を指定するラベルを使ってnodeSelectorで対応 • vram 32GB以上でできるだけコストの低いGPUが使いたい ◦ vram量のラベルを列挙 ◦ preferredDuringSchedulingIgnoredDuringExecutionも指定 GPU指定の想定パターン(A30, A100, V100混載) 15
  13. 16 解決法: GPU Selection Specという記法を作成・実装した • gpu-<GPU name>-<minimum VRAM amount>:

    <amount> 「どんなGPUが欲しいか」を直接的に一カ所で書かせる • GPUの枚数 • GPUの種類名 ◦ なんでもいい(any) ◦ 種類指定(v100, a30, a100) • 必要なVRAM量 ◦ なんでもいい(省略) ◦ 下限値 ◦ (多くある分には問題ない) 様々なGPU指定をシンプルな記法で可能にしたい apiVersion: v1 kind: Pod spec: containers: - resources: limits: preferred.jp/gpu-any-24gb: 1 例: 種類はなんでもよいので、 vramが24gbほしい 16
  14. 17 下記のようなmutationを行う、admission webhookを開発した • 入力: Podのmanifest ◦ Podの優先度(high or low)

    ▪ high: 優先度高かつ長寿命 ◦ 必要なVRAM量・GPUの種類 ▪ GPU Selection Spec • 出力: Podのmanifest ◦ node selector ◦ toleration ◦ (nodeAffinity) ▪ (実際はノードの優先度は別レイヤで実装) 様々なGPU指定をシンプルな記法で可能にしたい Pod作成 admission webhook スケジューラ nodeSelector などの付与 17
  15. 18 PriorityによるGPU Selection Spec振る舞いの変更 長時間GPUを遊ばせない、かつ、長時間スペックを持て余さないために • high: 優先度高かつ長寿命 ◦ 記載されたvram量を上回る最小のvram量を持つGPUのみ選定

    ▪ 必要以上のスペックのGPUを確保し続けないように • 長寿命なのでコスト増 ▪ taintとtolerationなどで実現 • low: 優先度低かつ短寿命 ◦ 記載されたvram量を上回るGPUすべてを選定 ▪ 短寿命なのでリソースを遊ばせないことを優先 ※low:high = 2:1くらい(Running Pod数) 18
  16. 24 • 実際のユーザの需要が計測しやすくなった ◦ 利用しているGPUである必要があるのか、スケジュールされている だけかの区別がしやすくなった ◦ GPU・vramごとの需要がわかる • 32GB

    GPUの利用方法がわかりません、といった問い合わせが減った ◦ 結果的にユーザ・クラスタ管理者両者の工数を削減できた • 管理者の都合によるスケジュール変更やラベル変更が可能になった ◦ manifestが「どんなNodeか」から「どんなGPUか」へ ▪ クラスタの構成等が変わってもここは変わらない ◦ 例: A100の流量をユーザが許容出来る範囲で調整できる ▪ 一時的にa100にany指定のPodが入らないようにするなど ▪ 明示的に指定しているPodのみ受け入れるなど GPU Selection Spec導入の恩恵 24
  17. 26 GPUノード導入の際にはCPUは余裕を持ったノードを導入している なぜか: • GPUノードでCPU量が不足するのはリスク ◦ GPUの性能がCPU量不足になる場合がある ◦ CPUに比べて、GPUはコスト高。 ▪

    GPUが活かせなくならないようCPUを搭載すべき • GPU性能とCPU量の適切なバランスは読みづらい ◦ 計算機の利用のされ方は技術の進歩とともに変化する ◦ ワークロードによってはCPUが重要になったりする ▪ GPUで動かしにくい大規模なシミュレーション等 GPUに対するCPU不足は避けたい 26
  18. 27 • CPU PodをGPUノードへスケジューリングしている ◦ GPUノード上のCPUを遊ばせるのはもったいない ◦ PFNのCPU資源需要は常に高い。有ればあるほど良い • 低優先度・短寿命のCPU

    Podに限ってGPUノードにスケジュール ◦ GPU需要をブロックしない GPUノード上のCPU資源の有効活用 CPU Pod(優先度低) CPU Podを追い出し てスケジュール CPU Pod(優先度高) GPU Pod 優先度が高く追い出せないので スケジュールできない => GPUが遊んでしまう 27
  19. 28 • ノード上のCPUリソースを一部優先度高 CPU Pod専用に切り出し ◦ 仮想ResourceをNodeに付与し、優先度高CPU Podがrequestする => 優先度高CPUのCPU占有に上限が付けられる

    ◦ admission webhookによるmutationで実現 ◦ ノードごとに柔軟に変更可能、実際の需要に応じて変更できる さらに踏み込んだGPUノード上のCPU資源の有効活用 GPUノードのCPUコア全体 125(cores) 64 0 32 優先度高 CPU Pod 専用コア GPUノード 優先度低CPU Pod 利用コア 28
  20. 29 • ノード上のCPUリソースを一部優先度高 CPU Pod専用に切り出し ◦ 仮想ResourceをNodeに付与し、優先度高CPU Podがrequestする => 優先度高CPUのCPU占有に上限が付けられる

    ◦ admission webhookによるmutationで実現 ◦ ノードごとに柔軟に変更可能、実際の需要に応じて変更できる さらに踏み込んだGPUノード上のCPU資源の有効活用 allocatable: cpu: 125 nvidia.com/gpu: "4" preferred.jp/cpu-for-high-priority-cpu-pods: 32 requests: cpu: 30 preferred.jp/cpu-for-high-priority-cpu-pods: 30 admission-webhookで cpuと同数のリソースが自動付与される k8s上の操作だけで変更可能 29
  21. 30 Nodeに独自仮想リソースを付与するのは、Gatekeeperなどでも可能 • PFNではPodSecurityPolicyの後継としてGatekeeperを活用 ◦ tech blog • PodのPolicy・Mutationだけでなく、Nodeのmutationも可能 他には、device

    pluginを 書くなどの方法がある GatekeeperでNodeに仮想リソースを付ける apiVersion: mutations.gatekeeper.sh/v1 kind: Assign spec: applyTo: - groups: [""] kinds: ["Node"] versions: ["v1"] location: 'status.capacity. "preferred.jp/cpu-for-high-priority-cpu-pods"' parameters: assign: # 32 cores * 1000 (milli) value: "32000" 30
  22. 32 監視と自動修復 Servers icon by https://icons8.com 自己診断 修復処理 監視 Issue

    作成 通知 調査・修復処理 監視 システム node-operation-controller alertmanager-to-github 32
  23. Node Conditionを活用したノード障害検知 • Node Condition ◦ ノードの状態を表すKubernetes上の概念 ◦ デフォルトのタイプに加えて、独自のタイプを定義可能 →

    既知のノード障害に対して独自のNode Conditionを定義 • 独自のNode Conditionの例 ◦ GPURuntimeError ◦ GPUIsLost ◦ GPUPendingPage ◦ DStateProcess ◦ PCIeLinkDegraded 33
  24. 障害検知 → Node Conditionの設定方法 • kube-nvidia-active-monitor (自社開発) ◦ ワークロードを実行してはじめて分かるGPUの問題を検知 ◦

    GPUを使う簡単なワークロードをtaintを付けて定期実行 ▪ 欠点: GPUを占有してしまう ◦ 問題を見つけると GPURuntimeError を設定 • Node Problem Detector (OSS) https://github.com/kubernetes/node-problem-detector ◦ 問題を見つけるとNode Conditionを設定出来る ◦ カスタムプラグインを自社開発 ◦ リソースは占有しない 34
  25. kube-nvidia-active-monitorによる障害検知 導入して良かった点: • GPU障害はMetrics監視等では網羅できない ◦ 原因不明だが、なぜかCUDA Memoryを確保しようとするとエラー という事象は多い => 実際にCUDA

    Memoryを確保すればわかることが多い • CUDAが利用出来るGPUなら種類を問わず検知できる ◦ 見るべきMetricsはGPUアーキテクチャや世代によって変わったり する 35
  26. 37 監視と自動修復 Servers icon by https://icons8.com 自己診断 修復処理 監視 Issue

    作成 通知 調査・修復処理 監視 システム node-operation-controller alertmanager-to-github 37
  27. マニュアル対応: alertmanager-to-github https://github.com/pfnet-research/alertmanager-to-github • Alertmanager からの Webhook を受け取って GitHub イシューを作成

    ◦ 新しいアラートから GitHub イシューを作成 ◦ アラートが resolved ステータスになるとイシューをクローズ ◦ アラートが再度 firing ステータスになるとイシューをリオープン • Node Condition も Prometheus でメトリクスとして収集 ◦ アラートとして一元化して扱うことができる • GitHub イシューの assignee は自動で設定 • GitHub イシューには過去の対応履歴が残る → 将来の自動化の参考 38
  28. まとめ • 多種GPU混載Kubernetesクラスタでは、GPUの要求記述が複雑になる ◦ 「どんなノードか」から「どんなGPUか」といった記載へ変更 ◦ GPU Selection Specと呼んでいる •

    GPUノードのCPU資源の有効活用 ◦ 余裕を持ってCPUを搭載し、CPUワークロードで無駄なく活用する ◦ 仮想リソースによる優先度に応じた柔軟なスケジューリング • GPU障害の自動検査・自動復旧の仕組み ◦ 実際にGPUを使うテストが効果的 ◦ 既知の問題の検知後は自動再起動などを実施 39
  29. 40 • Preferred Networksの計算基盤関連チームでは採用を実施中です! ◦ 機械学習プラットフォームエンジニア (クラスタのサービス化) ◦ ストレージエンジニア (ストレージの企画設計管理運用)

    ◦ 大規模計算基盤エンジニア/リサーチャー (クラスタの物理設計、MN-Coreを含めた先端システム設計等) • カジュアル面談もやってます → We're Hiring !! 40