nariのエンジニアリング備忘録

SRE/Devops/AWS/自動化/IaC/Terraform/Go/DDD など

EKS/Kubernetesで画像カテゴリ分類のGPU推論環境をProduction Readyにするまで

f:id:st5818129:20211220020232p:plain

こちらは Eureka Advent Calendar 2021の12/20の記事となります.

English Version:

medium.com

はじめに

こんにちは、エウレカSREチームのnari/wapperと申します👋

最近は、データライフサイクル・プライバシープロジェクト/データプラットフォームの移行/審査サービスのMLシステムのインフラなどを担当したりしています(Site Reliability Engineerなのかわからなくなってきた)

その中で今回は、審査サービスにおける画像カテゴリ分類モデルを、EKSで本番環境にリリースした話を紹介したいと思います。 EKS Clusterの本番環境設定のポイントは、セキュリティ項目も含めてたくさんありますが、今回はGPU推論環境ならではのポイントにフォーカスしてみたいと思います。

対象読者

  • Kubernetesに関する基礎知識(Cluster/Pod/Deploymentなど)をお持ちの方
  • EKS/Kubernetesを使ったGPU推論の本番環境構築方法に興味がある人

どうGPU推論環境を本番リリースしていくか

1. EKS GPU環境のk8sノード/コンテナを設定する

この章の概要のアーキテクチャは以下の通りです。(⚠︎これはあくまで私の理解であり、正しいことを保証するものではありません)

f:id:st5818129:20211220020333p:plain

1.1 ノードの設定(Nvidia Driver/Nvidia container runtime/Amazon EKS optimized accelerated Amazon Linux AMIs and MNG)

今回は、一旦AWSが提供しているmanagedな機能をフルで使っていくことにしました。

  • Amazon EKSに最適化されたAmazon Linux AMIを使用する
  • 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に配置することで、ワークロードを完全に分離することでこのリリースを実現することができました。

次の図は、その概要図になります。 f:id:st5818129:20211220020505p:plain

3. DatadogでGPUモニタリングの設定をする

f:id:st5818129:20211220020521j:plain

f:id:st5818129:20211220020627p:plain

4. ポッドとノードのスケール戦略を決定する(負荷テスト/キャパシティプランニング)

  • ポッドスケール戦略

    • HPA(horizontal pod scaler: Horizontal Pod Autoscaling | Kubernetes)を使用
    • GPUの使用率でスケーリングするか、CPUの使用率でスケーリングするか決定

      • ステージ環境での負荷テスト
      • 負荷テスト環境
      • GPUの使用率が飽和する前にCPUの使用率が飽和するという結果になったので、CPUの使用率を基準にHPAを設定することにしました。 f:id:st5818129:20211220020557p:plain
    • キャパシティプランニング

      • 最大リクエスト数での負荷テストを行い、最初に配置するサーバーのスペックを決定しました。

        • 以下は、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
      

      f:id:st5818129:20211220124624p:plain

  • ノードスケール戦略

    • 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/メモリの要求/使用率などの設定に従って適切にノードをスケーリングしてくれます
  • これらすべての設定の結果は次のようになります

f:id:st5818129:20211220020809p:plain

今後の展望

1.審査サービスのMLパイプラインのモダナイゼーション

審査サービスでの機械学習ワークフローはかなり手作業ベースになっています。具体的に言うと、データサイエンティストがローカルのノートブックでデータ収集、データクリーニング、モデルトレーニング、評価を実行を通してモデルを作成し、データサイエンティストとSRE/MLOpsエンジニアがそれらを本番環境のAPIエンドポイントとしてリリースしていきます。

この再現性のかなり乏しいフローは、管理するモデル数の上昇に対してスケールするとはあまり言い難い作りになっています。そこで、kubeflowや他のMLパイプライン管理ツールなどを用いて自動化パイプラインを構築することで、信頼性とリリースサイクルどちらも向上させながらスケールする状態に持っていきたいです。

f:id:st5818129:20211220020840p:plain

2. feature storeの導入

また、ML学習時とオンライン提供時でデータソースが異なることによるデータの不整合によって起こる問題を減少させるため、オンライン・オフラインどちらでも複数の特徴セットに対して共通の処理を可能とするfeature storeを導入したりして行けたらなと思っています。 (feature storeは推薦ドメインですでに採用済みだったりします: https://medium.com/eureka-engineering/vertex-ai-mlops-b74cdff19681)

f:id:st5818129:20211220020851p:plain

(https://valohai.com/machine-learning-pipeline/ から引用)

We are hiring SRE/MLOps Engineers!!

絶賛SREもMLOps Engineerも募集中ですので、もし少しでもエウレカやMatch Groupに興味がありましたら是非Twitter DMまでお願いします!

twitter.com

Meetyも開いてますので、こちらでも是非気軽にお話ししましょう〜

meety.net