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

Mobility Technologiesにおける数100台規模のnodeを使うEKSのAI推論環境

Mobility Technologiesにおける数100台規模のnodeを使うEKSのAI推論環境

JAWS DAYS 2021で発表した資料になります。

https://jawsdays2021.jaws-ug.jp/timetable/track-c-1720/

Toyama Hiroshi

March 20, 2021
Tweet

More Decks by Toyama Hiroshi

Other Decks in Technology

Transcript

  1. 自己紹介 2 • 外山 寛 • @toyama0919 • 株式会社ディー・エヌ・エー ◦

    AIシステム部MLエンジニアリングG • 2020/4から株式会社Mobility Technologiesに業 務委託 • 普段やってること ◦ DeNAのAI projectのインフラ構築 ◦ MoT社DRIVE CHARTのML-OPS ◦ MoT社DRIVE CHARTのk8s運用
  2. AI Test環境 8 • AI Test環境を刷新したいという動機でK8Sの検討が始まった ◦ 旧環境はec2(autoscaling)とsqsをベースに組み合わせた方 式をとっていた。 •

    「前処理>推論>出力」のpipelineをkubeflow pipelinesで実施 している。 • 複数人のデータサイエンティストが同時にTestできる。 ◦ 並列でpipelineが処理できる ◦ sourceとなる動画がs3に大量にあり、それらを並列で処理し ている。
  3. spotインスタンスを活用 10 • 構築早期の段階で数百台のnodeが立つことが頻繁にあったた め、インスタンスの費用を極力抑える必要があった。 • spot instance + autoscalingの知見はec2やecsで運用していた

    ため既にあった。 • 2020年12月にspot instanceをmanaged nodegroupがサポート したが、当初はサポートされていなかった。 • 何故かeksctlからは使える • terraformでも使えないのか調査し始めた • どうも生成されたautoscaling groupを直接書き換えているらしい => それならterraformでもできるはず
  4. terraformでspotインスタンスを活用 11 • terraformでManaged Nodegroupを管理する。 • Managed Nodegroupはlaunch templateとautoscaling groupを

    自動生成する。 • 自動生成されたautoscaling groupの OnDemandPercentageAboveBaseCapacityと OnDemandBaseCapacityを上書きすることでspotとondemand の比率が調整できる ◦ awscliだとaws autoscaling update-auto-scaling-group ~~ • またWeightedCapacityも書き換えることで、instance typeごとの 重みを調節できる
  5. (公式)Managed Nodegroupのspotインスタンス対応 12 • 2020年12月にspot instanceをEKS managed nodegroupがサ ポートした。 •

    (良い)SpotAllocationStrategy=capacity-optimizedと CapacityRebalance=trueがopt-inされている。 • (良い)spotが中断する際に、drainとcordonをEKSのcontrol planeがmanageしてくれる(aws-node-termination-handler相当 の機能) • (辛い)複数instance typeを組み合わせる場合のweightは autoscaling groupのupdateが必要、またオンデマンドの比率調 整も同様
  6. capacity rebalance 13 • 従来の中断通知より前にEC2 Instance rebalance recommendationが通知される。 • rebalance

    recommendationをinstanceが受け取ると新規で instanceの作成が開始されるため容量が一時的に不足する可能 性が大幅に下る。 • EKSのManaged Nodegroupのspot機能は上記がopt-inされて おり, podがpendingになりにくい状況を作れる。 • SpotAllocationStrategy=capacity-optimizedにすると効果的(こ れもopt-inされている)
  7. corednsの負荷増大 16 • kube-system用のnodegroupを作成し、ondemandを最低1台稼 働させて残りはspotで運用 • corednsなどのsystem的なpodはnodeSelectorで専用nodeに所 属させて他の負荷が高いnodeと共存させないようにする • また,

    corednsのpod数を5-10程度に増やした(デフォルトはは2) • kubeflowのpodが大半の通信を行うため、kubeflow上は部分的 にFQDNで通信させることによりDNSのsearchを少なくした。
  8. IAM RoleのNoCredentialsErrorが多発 18 • podを大量に(1000podくらい)起動した際に、aws resourceへの アクセス(主にs3)でNoCredentialsErrorが多発する。 • Managed NodegroupはデフォルトではnodeについているIAM

    Roleの権限をpodが使うことになる。 • EC2 に付与されている IAM Role の認証情報はインスタンスメタ データから取得される。 • インスタンスごとにこのmetadataにアクセスできるTPSに上限が あり、スロットリングされた場合には Boto3 での API Call 時に NoCredentialsError が発生する。
  9. IAM RoleのNoCredentialsErrorが多発(解決) 19 • AWS_METADATA_SERVICE_TIMEOUTを増やしたり、 AWS_METADATA_SERVICE_NUM_ATTEMPTS(retry回数)を 増やしたりもしたが根本解決はしなかった • IAM Roles

    for Service AccountsでpodごとにIAM Roleを設定す ることにより解決した。 • 各Podはk8sから払い出されるservice account tokenを AWS STS に OIDC tokenの形で渡すことにより、IAM の認証情報を 使うことができる。 • instance metadataにアクセスしないため、metadataのthrottling は発生しない
  10. 他にもいろいろ 20 • podが増えすぎてIPアドレスが枯渇してしまった。 ◦ VPC-CNI-pluginにVPCのIPを動的にreleaseする WARM_IP_TARGETやMINIMUM_IP_TARGETなどの設定 があるが、apiを内部でたくさん叩くためthrottlingが発生 ◦ 結局secondaryのsubnetを追加した

    • EKSのmanaged nodegroupのhealth checkでエラーが止まらな い。(実害はなかったが) ◦ aws-authのconfigmapでnodeのrbacをsystem:mastersにし ていた。 ◦ rbacのapiGroupsでcertificates.k8s.ioを許可しないとhealth checkが失敗してしまう
  11. helmをterraformで扱う 21 • 増えてきたhelm packageの管理が辛くなってきたので terraform-provider-helmを使うことにした • terraformでhelm packageの管理ができるので便利 ◦

    削除や更新、追加等がコードで管理できる • 似たようなツールとしてはhelmfileがある ◦ https://github.com/roboll/helmfile • 現在最新バージョンは2.0.2
  12. helmをterraformで扱う(why) 22 • インフラの管理はterraformに集約したい ◦ eksctlやalb-ingressなどインフラを作れるツールは多数ある が分散させたくない • helm packageもコードで管理したい

    ◦ 直接installしているとどのpackageをインフラで管理している のかがわかりにくくなっていく • helmも含めてmodule化しておけば、cluster構成+packageまま でterraform applyだけで量産できる
  13. helmで管理するpackage(why) 23 • 以下のpackageをterraformで管理 ◦ aws-ebs-csi-driver ◦ kubernetes-external-secrets ◦ aws-node-termination-handler

    ◦ cluster-autoscaler ◦ nvidia-device-plugin ◦ cloudwatch-agent(自作package) ◦ fluentd(自作package) • packageも含めてterraformだけで管理できるのが便利 • EKS add-onsで管理できるようになるかもしれないが、現状は VPC-CNIのみ
  14. terraform provider 24 data "aws_eks_cluster_auth" "main" { name = aws_eks_cluster.this.name

    } provider "helm" { kubernetes { host = aws_eks_cluster.this.endpoint token = data.aws_eks_cluster_auth.main.token cluster_ca_certificate = base64decode(aws_eks_cluster.this.certificate_authority.0.data) } }
  15. terraform provider 25 resource "helm_release" "cluster_autoscaler" { name = "cluster-autoscaler"

    chart = "autoscaler/cluster-autoscaler-chart" namespace = "kube-system" # repositoryを指定する repository = data.helm_repository.autoscaler.metadata[0].name set { name = "autoDiscovery.clusterName" value = data.aws_eks_cluster.main.name } }
  16. prometheus 28 • OSSのmonitoringツールでは一番有名かも • クエリが書くのが難しい上、メンバーに覚えさせられると思えな かった。 • メモリの消費が激しく、m5.xlargeでも頻繁にpodが落ちてしまっ た。

    ◦ r5.xlarge(32GB)でなんとか耐えられるという状況 • インフラ的にも学習コスト的にも運用出来るイメージが沸かなかっ た。 • helmで一発でdeploy出来るのは良かった。
  17. cloudwatch container insights 29 • 非常に手軽にAWSマネージドな仕組みだけで詳細なメトリクスが 取得可能 • deployは簡単だが、helm化はされていない。 •

    ECSも使っているため、EKSと並べてメトリクスを見れるは良い。 • UIは見やすく、Managed Serviceであり運用コストも低めで採用 決定 ◦ cluster別やnamespace別のcpu平均使用率みたいな高度な metricsも見れる。
  18. kubeflow 32 • k8s上で動作する機械学習platform • こんな感じで機械学習の機能が盛りだくさん ◦ jupyter notebook ◦

    fairing(trainingの実行、deploy) ◦ MPI Operator ◦ Katib(ハイパーパラメーター最適化) ◦ arena(computing込みのtraining環境) ◦ pipelines(機械学習workflow実行)
  19. kubeflow pipelines 33 • k8s上で動作させる機械学習に特化したworkflow engine • experimentsの概念があり、実行するpipeline(workflow)には experimentsが必須となる •

    後から実験結果を見る際にexperimentsから成功失敗が一覧で 見れる • パラメータを画面から細かく設定できる ◦ この辺はjenkinsっぽいが、可変にするパラメータもcodeで管 理できる
  20. kubeflow pipelines standalone 36 • chartではnotebookはsagemakerを使っており、trainingも sagemaker及びec2でやっているためfairingはいらない • kubeflowをdeployすると無駄なpodがたくさんdeployされるた め、kubeflow

    pipelinesをstandaloneでdeploy。 • これなら平常時はc5.xlarge1台程度のリソースしか使わない ◦ fullでdeployすると3-4台程度になってしまう
  21. kubeflow pipelinesでハマったこと(S3, RDS) 37 • ドキュメント通りにdeployすると、artifactの書き出し先がEBSに なってしまいcontainerが別AZに生まれ変わったりするとEBSに アクセスできず起動しない。 • pipelineの保存先もpodとして起動したmysqlになっており、これ

    もEBSに保存されるため上記と同じ問題が発生 • artifactはs3, pipelineはRDSに保存するようにしないとnodeの zoneが変わったりすると起動しなくなる • artifactの保存先設定(algo)とpipelineのyamlの保存先設定 (minio)が同じs3なのに別々で存在する • 要はebs依存を取り去るのが大変だった
  22. kubeflow pipelinesでハマったこと(ALB) 38 • ALBとpodを通信させる際に最初はALB Ingressを検討したが、 terraform管理との相性が悪く断念 ◦ AWSのresourceはterraformに集約したかった •

    がpodのIP等はterraformで検出できないため、nordportで通信 させるようにした。 ◦ ALBのtarget groupとautoscaling groupを関連付ける事がで きるのでその設定をした。 • terraform k8s providerでingressが使えるのでそっちで管理する のもありかもしれない(と思い始めた • kustomizeがあんまり好きではない(笑
  23. kubeflow pipelineのサンプルコード 41 import kfp from kfp import compiler, dsl,

    components def _preprocess(n: int) -> str: return f"preprocess {n}" def _process(nums: str) -> int: return 1 @kfp.dsl.pipeline(name="parallel-pipeline") def pipeline(n: int) -> None: image = "python:3.8-alpine" preprocess_func = components.func_to_container_op(_preprocess, base_image=image) preprocess_op = preprocess_func(n) process_func = components.func_to_container_op(_process, base_image=image) process_op = process_func(preprocess_op.output) # preprocessの後にprocess process_op.after(preprocess_op) return process_op.output
  24. k8sを触って感じたこと(メリット) 45 • kubectl execでcloud上に即containerを起動できるため、debug がしやすい ◦ と思ったらECSもcontainerに直接アクセス出来るecs-execが 出た! •

    インターネット上(SNS, ブログ含む)にとにかく情報が多く、やりた いことに対する情報がまずみつかる • ECSはアプリ開発者に嫌でもAWSを意識させないといけない (IAM Roleやsubnetなど)が、k8sはインフラとアプリの切り分けが しやすい。
  25. k8sを触って感じたこと(デメリット) 46 • 最初に構築する際の学習コストが高い, これに尽きる ◦ helmやkustomizeなど管理ツール ◦ awsを知っていれば普通に使えるEBS, ALB,

    Autoscalingな どにもk8sのresourceになっている必要があり一手間かかる • バージョンアップが手間 ◦ これも学習コストの1つとも言える ◦ バージョンに依存しているコンポーネントが多く、各コンポーネ ントが新バージョンに対応しているか確認する必要がある。