EKS/Kubernetesで画像カテゴリ分類のGPU推論環境をProduction Readyにするまで
こちらは Eureka Advent Calendar 2021の12/20の記事となります.
English Version:
はじめに
こんにちは、エウレカSREチームのnari/wapperと申します👋
最近は、データライフサイクル・プライバシープロジェクト/データプラットフォームの移行/審査サービスのMLシステムのインフラなどを担当したりしています(Site Reliability Engineerなのかわからなくなってきた)
その中で今回は、審査サービスにおける画像カテゴリ分類モデルを、EKSで本番環境にリリースした話を紹介したいと思います。 EKS Clusterの本番環境設定のポイントは、セキュリティ項目も含めてたくさんありますが、今回はGPU推論環境ならではのポイントにフォーカスしてみたいと思います。
対象読者
- Kubernetesに関する基礎知識(Cluster/Pod/Deploymentなど)をお持ちの方
- EKS/Kubernetesを使ったGPU推論の本番環境構築方法に興味がある人
どうGPU推論環境を本番リリースしていくか
1. EKS GPU環境のk8sノード/コンテナを設定する
この章の概要のアーキテクチャは以下の通りです。(⚠︎これはあくまで私の理解であり、正しいことを保証するものではありません)
- 登場するコンポーネント
- Nvidia Driver
- nvidia-container-runtime
- runcをラップしたruntime、prehookでGPUを制御できるようにしたもの
- https://github.com/NVIDIA/nvidia-container-runtime
- nvidia-device-plugin
- クラスタの各ノードに搭載されているGPUの数を公開し、KubernetesクラスタでGPU対応コンテナを実行することを可能にするもの
- https://github.com/NVIDIA/k8s-device-plugin
- CUDA
CUDAは並列コンピューティングプラットフォームとプログラミングモデルで、GPUを使った汎用コンピューティングをシンプルにする
(https://blogs.nvidia.com/blog/2012/09/10/what-is-cuda-2/より引用)
- Pytorch
- 弊社が採用しているオープンソースの機械学習フレームワーク
- https://pytorch.org/
1.1 ノードの設定(Nvidia Driver/Nvidia container runtime/Amazon EKS optimized accelerated Amazon Linux AMIs and MNG)
今回は、一旦AWSが提供しているmanagedな機能をフルで使っていくことにしました。
- Amazon EKSに最適化されたAmazon Linux AMIを使用する
In addition to the standard Amazon EKS optimized AMI configuration, the accelerated AMI includes the following: NVIDIA drivers and nvidia-container-runtime (as the default runtime)
(https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.htmlから引用)- Kubernetes v1.21 がDocker container runtimeをサポートする最後のVersionになるようです
- GPUインスタンスと最適化AMIを指定してMNG(Managed Node Group)を作成する
Terraform example
# FYI https://www.terraform.io/docs/providers/aws/r/eks_node_group.html resource "aws_eks_node_group" "node" { ... capacity_type = "AL2_x86_64_GPU" # Amazon EKS optimized accelerated Amazon Linux AMI instance_types = ["g4dn.xlarge"] # GPU instance ... }
1.2 Nvidia device pluginをノードに導入する
Nvidia device pluginをDaemonSetとして、kubectlでインストールします。(適宜node collctorなどの設定は変更します)
# You can also copy https://github.com/NVIDIA/k8s-device-plugin/blob/master/nvidia-device-plugin.yml and manage it # Modify node collector/tolerance/affinity if needed kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.9.0/nvidia-device-plugin.yml
1.3 CUDA/PytorchコンテナのDockerfileを作成し、それをDeploymentとして作成する
PytorchやCUDAなどの機械学習ライブラリ周りで最も難しいことの1つは、互換性考慮しながらどのバージョンのどのツールをインストールするかをコントロールすることです。
今回は、データサイエンティストが使っているPytorchのバージョンにCUDA環境を互換性がある形に合わせていく必要がありました。(詳しくは https://pytorch.org/get-started/previous-versions/ )
最終的に、そのバージョンのPytorchが動作する、PythonとCUDAの環境をまとめてベースイメージとして管理することにしたところ、かなり管理が簡単になりました。( 参考: https://github.com/qts8n/cuda-python/blob/master/runtime/Dockerfile および https://github.com/docker-library/python/blob/master/3.9/bullseye/Dockerfile)
2. CPU推論ワークロードとGPU推論ワークロードを分離する
既に審査サービスでは、テキスト分類のためのCPU推論モデルのワークロードが存在していました。(詳しくはこちら: https://medium.com/eureka-engineering/aws-solution-days-ai-machine-learning-day-tokyo-で登壇しました-45563b66d10 )
そして、この画像分類GPU推論モデルを、既存のテキスト分類のCPU推論ワークロードに影響を与えることなくリリースする必要がありました。
そこで、Node AffinityをつかってCPUモデルはCPU用のMNGに、nvidia.com/gpuのlimits・requestsの設定でGPUモデルはGPU用のMNGに配置することで、ワークロードを完全に分離することでこのリリースを実現することができました。
次の図は、その概要図になります。
3. DatadogでGPUモニタリングの設定をする
- Nvidia NVMLを使って、DatadogでGPUのメトリクスを取得し、可視化してみました。
- ただ、Official Pageの説明では設定が不十分で再利用性がないので、自分でサンプル設定コードで書いて公開しました。詳しくはこちらを参考にしてみてください。
- https://github.com/fukubaka0825/nvml-for-datadog-in-k8s
- 公式のdatadog helm chartはnvmlをサポートしていませんので、daemonsetでプロビジョニングする必要があります
- マニュアルでは説明されていませんが、EKSの場合はdatadog agent設定で環境変数
DD_CLUSTER_NAME
を指定する必要があります - IRSA+ASCPでよりセキュアな設定にしています
- https://github.com/fukubaka0825/nvml-for-datadog-in-k8s
- 結果、設定できたダッシュボードは以下のようになります。
4. ポッドとノードのスケール戦略を決定する(負荷テスト/キャパシティプランニング)
ポッドスケール戦略
- HPA(horizontal pod scaler: Horizontal Pod Autoscaling | Kubernetes)を使用
GPUの使用率でスケーリングするか、CPUの使用率でスケーリングするか決定
キャパシティプランニング
最大リクエスト数での負荷テストを行い、最初に配置するサーバーのスペックを決定しました。
- 以下は、vegetaでのコマンドと結果の例です。
-> % nappa curl -v -XPOST https://example.com/ping -d '{ "image_url": "hoge" }' | vegeta attack -format=json -duration=300s -rate=2/s | tee results.bin | vegeta report Requests [total, rate, throughput] 30, 3.10, 3.07 Duration [total, attack, wait] 9.759s, 9.667s, 92.698ms Latencies [min, mean, 50, 90, 95, 99, max] 86.44ms, 140.245ms, 105.532ms, 211.702ms, 260.299ms, 489.439ms, 489.439ms Bytes In [total, mean] 2460, 82.00 Bytes Out [total, mean] 3870, 129.00 Success [ratio] 100.00% Status Codes [code:count] 200:30 Error Set:
また、以下のようにvegetaはHTMLで結果を可視化することもできます。
-> % nappa curl -v -XPOST https://example.com -d '{ "image_url": "hoge" }' | vegeta attack -format=json -duration=10s -rate=1/s | tee results.bin cat results.bin | vegeta report -type="hist[0,100ms,200ms,300ms]" cat results.bin | vegeta plot > plot.html
ノードスケール戦略
- Cluster Autoscalerを使用しています(https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)
アクセラレータの設定をラベリングして、Cluster AutoscalerがGPU optimizeのプロセスを考慮して適切にスケールダウン/アップできるようにします
label = { "k8s.amazonaws.com/accelerator" = "nvidia-tesla-t4" #g4dn gpu REF: https://github.com/kubernetes/autoscaler/blob/7e5f8f0045c195376d773fc64998e2f8b7566316/cluster-autoscaler/cloudprovider/aws/aws_cloud_provider.go#L41 }
それ以外については、GPUノードのスケーリングのための特別な設定のために必要なし
- Cluster Autoscalerはとても優れたツールで、Affinity/toleranceやGPU/CPU/メモリの要求/使用率などの設定に従って適切にノードをスケーリングしてくれます
- Cluster Autoscalerを使用しています(https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)
これらすべての設定の結果は次のようになります
今後の展望
1.審査サービスのMLパイプラインのモダナイゼーション
審査サービスでの機械学習ワークフローはかなり手作業ベースになっています。具体的に言うと、データサイエンティストがローカルのノートブックでデータ収集、データクリーニング、モデルトレーニング、評価を実行を通してモデルを作成し、データサイエンティストとSRE/MLOpsエンジニアがそれらを本番環境のAPIエンドポイントとしてリリースしていきます。
この再現性のかなり乏しいフローは、管理するモデル数の上昇に対してスケールするとはあまり言い難い作りになっています。そこで、kubeflowや他のMLパイプライン管理ツールなどを用いて自動化パイプラインを構築することで、信頼性とリリースサイクルどちらも向上させながらスケールする状態に持っていきたいです。
2. feature storeの導入
また、ML学習時とオンライン提供時でデータソースが異なることによるデータの不整合によって起こる問題を減少させるため、オンライン・オフラインどちらでも複数の特徴セットに対して共通の処理を可能とするfeature storeを導入したりして行けたらなと思っています。 (feature storeは推薦ドメインですでに採用済みだったりします: https://medium.com/eureka-engineering/vertex-ai-mlops-b74cdff19681)
(https://valohai.com/machine-learning-pipeline/ から引用)
We are hiring SRE/MLOps Engineers!!
絶賛SREもMLOps Engineerも募集中ですので、もし少しでもエウレカやMatch Groupに興味がありましたら是非Twitter DMまでお願いします!
Meetyも開いてますので、こちらでも是非気軽にお話ししましょう〜