Open193

Amena開発日記

ピン留めされたアイテム
uehruehr

ピン留め

サービス構想

  • 3D Photo生成サービス
  • Web UIから静止画をアップロードするだけで簡単に3D Photoを生成

※3D Photo↓

開発用Organization

https://github.com/amena-dev

アーキテクチャ

amena-architecture

主に使いたい技術

  • MQ
    • オリジナル静止画のEnque
    • 3Dフォトグラフィ生成エンジンによるDeque
  • IaC
    • Terraformを用いたインフラ構築(AWS)
  • Kubernetes
    • Amazon EKSによるコンテナオーケストレーション
    • オートスケーリング機構
uehruehr

まずはPoCと思ったが、核となる3Dフォトグラフィ生成部は既存の実装を使う(≒すでに効果は実証されている)のでスキップ、まずは全体のインフラ構成を詰める。

uehruehr

余談だが、GitLabの「Project」にあたる機能がGitHubでは「Organization」で使えるのは良い発見だった(Zennインスパイア)

uehruehr

基本方針として、このプロダクトで習得したいのは主にインフラ周りの技術なので、アプリケーション層はそこまで凝りたくない。逆に言えばアプリケーション層をシンプルに保てるインフラ構成を目指したい。

uehruehr

ログイン機能は面倒臭くて付けたくないので、ざっと以下フローでアップロード〜成果物確認までを行う方針で検討。もしかするとDBも要らなくなるか?

  1. クライアント:静止画をフォームからアップロード
  2. システム:リクエストをEnqueし受付IDを発行
  3. クライアント:システムから受付IDを受け取ってCookieへセット
  4. システム:成果物をS3 Bucket://{{受付ID}}に格納(数分掛かる見込み)
  5. クライアント:Cookieの受付IDを元に一定周期で成果物が出来てないか問合せ
  6. クライアント:成果物ができていたら署名付きURl経由でS3からダウンロード

こうするとユーザアカウント情報管理が不要なのでシステムをだいぶシンプルに保てる。Cookieを削除すると成果物を取りにいけなくなるが、まあそれは仕様として(間違って削除しても再度リクエスト投げれば良い。)

uehruehr

あと、何気にシェアードナッシングを達成できるので冗長化にも強そう。

uehruehr

いや、上記の構成だと一人のユーザが同時にいくつも解析リクエストを投げられてしまうか。
IP単位でスタック数を制御しようにも複数台のPCでこられたらどうしようもない。

Googleアカウントでログインし、そのIDごとに一度にスタックできる解析リクエスト数を制御しようか(例えば一つのアカウントにつきスタックできる解析依頼は3つまでとか)

その場合別途DBでアカウント毎の解析進行数を管理?それともMQを見てそれぞれの依頼に紐づいているアカウントIDを確認できる?その辺りは調査。

uehruehr

以下のフローにしよう。DB使うのは本意ではなかったがまあセキュリティの面で仕方ないか。

  1. クライアント:Googleアカウントでログイン
  2. クライアント:GoogleのAuthTokenと共に静止画をフォームからアップロード
  3. システム:リクエストをEnqueしGoogleアカウントIDと受付IDをDBへ保存
  4. システム:成果物をS3 Bucket://{{受付ID}}に格納(数分掛かる見込み)
  5. クライアント:一定周期でログイン中のGoogleアカウントに紐づいている成果物が出来てないか問合せ
  6. クライアント:成果物ができていたら署名付きURl経由でS3からダウンロード
uehruehr

参考:バックエンドサーバを用いて認証する

## Google APIクライアントライブラリを使用する
本番環境にて Google IDトークンを検証するには、Google API Client Libraries (例えば、Java、Node.js、PHP、Python)のいずれかを使用することが推奨される方法です。
uehruehr

まあアカウント使う仕様になると前から考えてた課金機能も実現しやすくなるので良い。

uehruehr

MQについて、取り敢えずシンプルそうなAmazon SQSの方針で検討してみる。

uehruehr

なお今回は費用面は一切気にせず好きに作ってみる。最悪月10くらい掛かっても良い。

uehruehr

terraform apply 時に以下エラー発生

Error: error creating EKS Cluster (eks-dev-cluster): InvalidParameterException: unsupported Kubernetes version                                             
{                                                                                                                                                          
  RespMetadata: {                                                                                                                                          
    StatusCode: 400,                                                                                                                                       
    RequestID: "{{ID}}"                                                                                               
  },                                                                                                                                                       
  ClusterName: "eks-dev-cluster",                                                                                                                          
  Message_: "unsupported Kubernetes version"                                                                                                               
} 

variables.tfcluster_version = "1.12"cluster_version = "1.18"に直したら通った。

uehruehr

怒られた
Error: Error creating launch configuration: ValidationError: The key pair 'KEY' does not exist

uehruehr

aws_key_pairを使ってterraformでkey_pairを作るようにして通った。
terraformまともに弄るの初めてだけどだいぶスラスラ設定読めるようになってきた、これは良い。

resource "tls_private_key" "eks-private-key" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "aws_key_pair" "eks-key" {
  key_name   = var.key_name
  public_key = tls_private_key.eks-private-key.public_key_openssh
}

〜〜〜

resource "aws_launch_configuration" "lc" {
  associate_public_ip_address = true
  iam_instance_profile        = aws_iam_instance_profile.eks-node.id
  image_id                    = data.aws_ami.eks-node.image_id
  instance_type               = var.instance_type
  name_prefix                 = "eks-node"
  key_name                    = aws_key_pair.eks-key.key_name
〜〜〜
uehruehr

初Apply!!これはめでたい!!
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

uehruehr
$ terraform output eks-configmap > ./outputs/eks-configmap.yaml
$ terraform output kubectl-config > ./outputs/kube-config.yaml
uehruehr

kubectl apply Done!!! 正常にクラスタ作成されてることをコンソールで確認済み!!やった!!
しかしNodeが立ち上がってない...?

uehruehr

コンソールに以下表示。contextあたりが怪しそうか。

Your current user or role does not have access to Kubernetes objects on this EKS cluster
This may be due to the current user or role not having Kubernetes RBAC permissions to describe cluster resources or not having an entry in the cluster’s auth config map.
uehruehr

上記の問題でEKSコンソールからは見れないが、EC2コンソールからはちゃんとnode立ち上がっているのを確認できた!!!

uehruehr

kc get nodesでもEKSコンソールからも立ち上がってるnodeが見えないが、EC2コンソールで確認するとEKS由来のEC2インスタンスは立ち上がってる。contextやIAMが関連してると思うが良く分からん。

uehruehr

しかし依然WEBのEKSコンソールからは権限不足でnodeが見えない。ちゃんとIAMも付与出来てるっぽいんだが...。

uehruehr

作成したnodeにpodが載った!!!これはめでたい!!!やった!!!

$ kc logs -f myapp-pod                                                                                  
Hello Kubernetes!
uehruehr

tf applyまでのフロー確立できたからあとは早い
残:CW, S3, SQS, Route53, RDS

uehruehr

完全OSSにしようかと思ってたがさすがにセキュリティ面が怖いのでterraform設定はprivate repositoryへ

uehruehr

前から気になっていたNode.jsのFastifyフレームワークで実装してみる

uehruehr

こんな感じのディレクトリ構成に

src
├── 3dphoto
│   ├── 3dphoto.controller.ts
│   ├── 3dphoto.routes.ts
│   └── 3dphoto.service.ts
├── common
│   └── interfaces
│       └── response.interface.ts
├── router.ts
├── server.ts
└── version
    └── version.routes.ts
uehruehr

AuthorizationとErrorHandlingのフローをさくっと組み立てた。これから本質のロジック実装に入る。

src
├── 3dphoto
│   ├── 3dphoto.controller.ts
│   ├── 3dphoto.routes.ts
│   └── 3dphoto.service.ts
├── common
│   ├── authorization.ts
│   ├── error
│   │   ├── error.class.ts
│   │   └── error.handler.ts
│   └── interfaces
│       └── response.interface.ts
├── router.ts
├── server.ts
└── version
    └── version.routes.ts

uehruehr

コンテナ化して動かしたfastifyだとちゃんとポートフォワード設定してもレスポンス返ってこない...と2時間くらい詰まってたが、どうやらコンテナ化するときはlisten時に0.0.0.0を設定しないといけなかったらしい。
https://www.fastify.io/docs/latest/Getting-Started/#your-first-server

Before

server.listen(3000, (err, address) => {

After

server.listen(3000, "0.0.0.0", (err, address) => {
uehruehr

TYPEORMにEntity認識されないなぁ...と悩んでたけど、entitiesをdist向きにするのを忘れてただけだった
Before

    "entities": [
       "src/entity/*.ts"
    ],

After

    "entities": [
       "dist/entity/*.js"
    ],
uehruehr

マイグレーションまでこれでうまくいった

    "entities": [
        "dist/entity/*.js"
    ],
    "migrations": [
        "src/migration/*.ts"
    ],
uehruehr

input_image table作成してapi側から参照するところまでできてる

uehruehr

backendサーバーからSQSへEnqueue出来た!これは良い

uehruehr

あとは仕様書どうりにAPI実装やるだけ

uehruehr

backendサーバからS3へimage画像を保存できた。ここまで来たらこっちのもん。

uehruehr

本当に、本当に今更だけど、↓は完全にあることを見落としてた

いや、上記の構成だと一人のユーザが同時にいくつも解析リクエストを投げられてしまうか。
IP単位でスタック数を制御しようにも複数台のPCでこられたらどうしようもない。

Googleアカウントでログインし、そのIDごとに一度にスタックできる解析リクエスト数を制御しようか(例えば一つのアカウントにつきスタックできる解析依頼は3つまでとか)

その場合別途DBでアカウント毎の解析進行数を管理?それともMQを見てそれぞれの依頼に紐づいているアカウントIDを確認できる?その辺りは調査。

そもそも進行してる解析をDBで管理しなくてもS3のinput bucketを見れば良いだけの話だろう...完全に盲点だった。なんで今のいままでこんな簡単なことに気がつかなかったんだろう。

諸々設計修正する。

uehruehr

output取得API Done. これでweb-backend実装はほぼ終わり。
次は3DPhoto生成エンジンを作り込む。

uehruehr

現状のディレクトリ構成。ほぼ1日でここまでしっかり構成作り込めたのは良い。
あとは意外にS3とSQSとの連携が簡単だった。

src
├── 3dphoto
│   ├── 3dphoto.controller.ts
│   ├── 3dphoto.routes.ts
│   └── 3dphoto.service.ts
├── common
│   ├── authorization
│   │   └── authorization.ts
│   ├── aws
│   │   ├── aws.s3.ts
│   │   └── aws.sqs.ts
│   ├── config
│   │   ├── config-local.json
│   │   ├── config-production.json
│   │   ├── config.json
│   │   └── config.ts
│   ├── error
│   │   ├── error.class.ts
│   │   └── error.handler.ts
│   └── interfaces
│       └── interface.response.ts
├── router.ts
├── server.ts
└── version
    └── version.routes.ts

8 directories, 16 files

uehruehr

あと何気にRDSいらなくなったことで全体的な工数がガクッと減った。良い気づきだった。

uehruehr

愚直にビルドしたらモデル含めてimageが5GBもあるな...これからダイエットする

uehruehr

モデルを含めない場合でも4.16GBあるな、おかしい。
pytorchとかcuda関連ツールで容量食ってる?

uehruehr

ビンゴ、pipパッケージのインストール手順省くと1.48GBまでに。

uehruehr

推論エンジンのソースコード削ったら876MB。
大体内訳がわかってきた。

uehruehr

そして876MBはちょうどベースのpython imageの大きさ。
こんなでかいのか。

uehruehr

alpine導入するとさらに80MB減らせる見込みだけど、opencvのビルドエラーで面倒くさいことになってる。まあ妥協してpython3.7-slim使う方針で行こう。残りは必須なライブラリだから4GB imageはのちの課題としてひとまず妥協。

uehruehr

流石に5GBは大きすぎる、もう少し内訳を探る

uehruehr
56K     /usr/local/lib/python3.7/site-packages/proglog                                                                                                     
248K    /usr/local/lib/python3.7/site-packages/wheel                                                                                                       
292K    /usr/local/lib/python3.7/site-packages/certifi                                                                                                     
408K    /usr/local/lib/python3.7/site-packages/requests                                                                                                    
444K    /usr/local/lib/python3.7/site-packages/tqdm                                                                                                        
504K    /usr/local/lib/python3.7/site-packages/transforms3d                                                                                                
516K    /usr/local/lib/python3.7/site-packages/idna                                                                                                        
872K    /usr/local/lib/python3.7/site-packages/urllib3                                                                                                     
1.1M    /usr/local/lib/python3.7/site-packages/moviepy                                                                                                     
1.1M    /usr/local/lib/python3.7/site-packages/tifffile                                                                                                    
1.6M    /usr/local/lib/python3.7/site-packages/chardet
2.7M    /usr/local/lib/python3.7/site-packages/setuptools
5.0M    /usr/local/lib/python3.7/site-packages/imageio
8.8M    /usr/local/lib/python3.7/site-packages/pip
9.9M    /usr/local/lib/python3.7/site-packages/vispy
11M     /usr/local/lib/python3.7/site-packages/networkx
25M     /usr/local/lib/python3.7/site-packages/numpy
35M     /usr/local/lib/python3.7/site-packages/matplotlib
35M     /usr/local/lib/python3.7/site-packages/torchvision
43M     /usr/local/lib/python3.7/site-packages/cynetworkx
65M     /usr/local/lib/python3.7/site-packages/scipy
1.4G    /usr/local/lib/python3.7/site-packages/torch
uehruehr

小手先のテクニック使っても4GB程度が限界だった...いったんissue切ってとりあえずこのまま進む

uehruehr

pythonからSQSとS3連携できた。あとはこの仕組みを既存の推論エンジンに組み込む。

uehruehr

せやな

I think direct writing on S3 using multipart upload is a good solution. It will upload quickly and the process will be fast. As of now we are saving the output video on a local file and then that file is uploaded to S3 which takes time (1. video rendering 2. uploading 3. Deleting the video) and then respond to the client.
uehruehr

バックエンド側でSQS EnqueからS3画像保存までラグがあって、クライアントがMessage受信してS3からDLする頃にS3にオブジェクトがないという現象が起きていた。そうか、このためにSQSのMessage配信ラグ設定があったのか、学び。

uehruehr

delay sec = 1でうまくいった。にしても、Enque(from: backend) からDeque & S3 DL (from: 解析engine)までにこれまで1sもかかってなかったってことか、予想以上に早いな

uehruehr

バックエンドAPIへ画像POSTしたらSQS経由で同時に解析エンジンが動き出すところまで動いてる

uehruehr

REST APIでポチッとするだけでほぼ同時に別コンソールの解析エンジンが動き出す体験、良い。

uehruehr

API POST → 解析エンジンが動作 → S3へ成果物をOutput
まで、若干荒削りだけど動いた

uehruehr

docker runで立ち上げたpythonのprint内容がdocker logsで見えないなと思ったら、どうやらpython -uオプションで起動してあげないとstdoutをバッファしちゃうっぽかった。

uehruehr

Dequeしたあと処理で何かしらエラーが起こったらS3のoutputバケットにerror.jsonを吐くようにした

uehruehr

文献漁ってると解析エンジンのimageで10GB以上ある場合もあると知った。
よし4GBで妥協しよう()

uehruehr

と、ここで解析エンジンをdockerで動かすとvispyがqt5を要求してクラッシュする問題がでた。
vispy & EGLでどうにかできないか探り中。

uehruehr

うーん、EGLはGPUレンダリングか。dockerでvispy動かすにはどうすれば。

engine_1  | RuntimeError: Could not import backend "EGL":
engine_1  | Could not initialize
uehruehr

osmesaで動かしたが以下エラーが発生

error: attributeerror("'looseversion' object has no attribute 'version'")
uehruehr

手元のmac開発機だとcuda入らないので、g3sインスタンスにcudaやnvidia driver入れてエンジン単体で動かすと正常に動いた。GPU前提でDockerfile修正してエンジン開発はfixさせよう。

uehruehr

よし!g3sインスタンス&DockerでエンジンのSQS, S3連携まで動かせた。

uehruehr

ロゴアップデート、さらにイメージカラーを追加。ロゴと文字のバランスが難しいなぁ...。

uehruehr

あとインフラコストを抑えるために、解析Queueが0の場合はkubeのオートスケーリングで解析Node・Podも0にしたい

uehruehr

フロントデザイン脳内で色々fixしてきた。土日で一気に作り上げよう。

uehruehr

だめだフロントデザインにこだわり過ぎてるな...ここは次の休みでもうfixさせよう

uehruehr

なるほど、イベントに対して並行処理が必要な場合「イベント発火→SNS→複数SQSへ配信」というフローがあるのか。

https://dev.classmethod.jp/articles/cross-account-sqs-message-send-patterns/
"SNSを挟むべき代表的なユースケースとしてFanoutパターンがあります。一つ目イベントに対して並行して処理を行う場合には、SNSをメッセージのハブの様に使用してPub/Subモデルのアーキテクチャを採用してPublisherで複数メッセージを送信せずにSNSに任せましょう。"

uehruehr

あーSNS挟みたいいいい。しかし今回のシステムではメリットなさそうか。。。

uehruehr

これまでS3へのinput画像配置とSQSへの解析依頼putはバックエンド側でやってたけそ、そもそもSQSへのputはS3のtrigger機能使えば自動で行けそう?要検討。

uehruehr

いやあくまでReact HooksはFunction ComponentでStateを使えるようにするだけってやつか?
もう面倒臭くなった(本来アプリ層にここまで時間をかけたくなかった)から、Class Component & Stateを酷使してAPIとフロントの連携としよう。

uehruehr

とりあえず全APIとフロント表示との連携はできてる。
あとは細かいフロントのエラーハンドリングやログイン機構を作り込む。

uehruehr

しかしtrigger機能は一定も負荷を超えるとラグが酷くなるという話も聞くんだよなあ、要検証

uehruehr

ALB Ingress Controllerなる便利なものがあるのか。。。

uehruehr

ALBのリソース管理をTerraformでやるかk8sでやるか考えないとなのか。もともとTerraformでやる想定だったが、ここはインフラとアプリケーション層の接合部だからなぁ...。

uehruehr

ALB経由でフロントエンド疎通や!!!!

uehruehr

おら!!!!!k8s設定完了してfront, back, ai engineの全疎通取れたぞ!!!!!!!これでサービスとして初めて本番乗った!!!!あとは細かいところ詰めるぞ!!!

uehruehr

backend podやfrontend podのCPU使用率ベースのスケーリングはあっさりできたけど、AI EngineのSQS Queue数を見てのスケーリングが一筋縄ではいかないなぁ...もう少し格闘。

uehruehr

うーん、ALB ingress導入まではできたんだが、External DNSでamena.uehr.coのレコード連携までうまくいかないなぁ...。

uehruehr

初期ロードマップで予定していたタスクは全て完了。あとは細かい仕様やAIエンジンの性能改善に注力する。

uehruehr

現在p2.xlargeインスタンスでCPU推論を動かしていて、8m/imgの性能しか出ていない...。
UXを考えると、遅くとも5m/imgを目指したい。

uehruehr

8m/imgはあくまでリクエストキューが1枚しかない場合の数値。現状キュー数に応じてのオートスケールができていないため、キュー数に比例して解析時間も長くなる。GPU対応の後はアーキテクチャ的な速度改善も入れる。

uehruehr

cuda有効かしてpytorchでGPU認識できているにも関わらず早くならないなぁ...。

uehruehr

AIエンジンのpytorch側からGPUを認識できているにも関わらず、いくらGPUインスタンススペックあげても画像一枚の処理時間がほとんど変わらないなぁ...。CPUスペックも付随してアップしてるはずなんで、どうしてもこの値が処理性能限界か...? そんなことある?

p2.xlarge: 8m/img
p2.8xlarge: 8m/img
p2.16xlarge: 8m/img
g4dn.xlarge: 8m/img
g4dn.8xlarge: 6m/img
g4dn.16xlarge: 7m/img
uehruehr

もう少しエンジンの実装レベルも詰めてみて、それでもダメならアーキテクチャ面の速度改善に移る。

uehruehr

nvidia-smiでGPU使用率見るの忘れてた...

uehruehr

p3.xlargeだと10m掛かった。nvidia-smiでGPUメモリ使用率確認すると、平均:1%, 最大: 40%。
逆に遅くなったのは謎...。

uehruehr

おっとCPU使用率100%に張り付いてるぞ、これか

uehruehr

CPU最適化インスタンスのc5.metalで試すと7m/img

  • GPUの有無は処理速度に関係ない?
  • CPU性能格段に上がったのに処理速度はほぼ変わらず
    • CPU使用率はずっと100%以上

もうよく分からなくなってきた

uehruehr

最終段階で以下を詰める(優先度順)
・エンジン水平スケール
・CI/CD
・軽微なUX
・各種資料

uehruehr

KEDA

ええやん

キューの中のメッセージ数を定期的に確認して、メッセージ数に応じた数の処理(Pod)を実行します。メッセージが0件ならPodは起動されませんし、大量にメッセージがあれば、それに応じた数のPodを起動します。

https://www.beex-inc.com/blog/k8s-event-driven-keda/

uehruehr

以前の検証でGPUの有無はAIエンジンの処理性能に影響しないと分かったのでAIエンジンの実行環境はCPUインスタンスを採用予定。本来SQS TriggerでCPU処理動かすならLambdaで良いのでは?というのがあると思うが、以下理由によりあくまでPodで動かす方針で。

  • Lambdaだと起動毎にモデルを落としてくる必要あり
    • Podだと既にモデルが含まれてるImageで起動するだけで良い
  • 今後AIエンジンをGPUチューニングで高速化させる可能性がある
    • LambdaはGPU対応してない
uehruehr

KEDAでQueue数に応じたPodのスケーリングはできたが問題発生。例えばPod Aの処理が済んでQueueが一つ減った時、本来は役割を終えたPod Aを落として欲しいが、処理中のPod Bが落とされてしまう場合がある...。

Pod A: 処理済み
Pod B: 処理中
uehruehr

Down対象のPodをどう選んでいるのかをk8sのソースレベルで追ったところ、どうやらこうなっていたらしい。これを見ると、処理中のPodは ready だとControllerに認識させておけば、 優先度下がる?試してみよう。

// Sort the pods in the order such that not-ready < ready, unscheduled
// < scheduled, and pending < running. This ensures that we delete pods
// in the earlier stages whenever possible.

getPodsToDelete
https://github.com/kubernetes/kubernetes/blob/f794c824b1e6e68b302d94f42f60af4759e18c6d/pkg/controller/replicaset/replica_set.go#L684:6

uehruehr

画像処理中は input/ フォルダにinput画像が格納されるので、その画像があるか否かでRediness Probeを設定しよう。

uehruehr

AIエンジン、処理に少なくともMemory 6Gi割り当てないとOEM Killedになる事がわかった。常時1Nodeは稼働させるとして、常駐コストを最小限に抑えられるインスタンスタイプを探す。

uehruehr

見事に以下の地雷を踏み抜いたが、なんとか思い通りにSQSのMSG数に応じてスケールアウトされるようになった。

  • 処理済みのPodでなく処理中のPodがスケールインされてしまう
    • Readiness Probeで処理済みのPodはNot Readyとすることで処理済みのPodから優先でTerminateするように
  • MSGが複数Podに重複配信されてしまう
    • Pod側でメッセージを受信してすぐに可視性タイムアウトを設定
  • KEDAが「利用可能メッセージ」「処理中メッセージ」の前者のMSG数しか見ておらず、MSGの処理に入った瞬間に(利用可能-1, 処理中+1)スケールインされてしまう
    • KEDAのソースコードを修正し前者と後者のMSG数の合算をSQSメトリクスとして扱うように
uehruehr

KEDAの仕様に関しては正直絶望したが、ソースコード弄ってなんとかできたのは胸熱だった。↑みたいに書くとあっさりしてるが、それぞれの解に行き着くまでが長かった...。この辺りのスケールアウト仕様、一回フローに起こたいな。

uehruehr

AIエンジン、処理に少なくともMemory 6Gi割り当てないとOEM Killedになる事がわかった。常時1Nodeは稼働させるとして、常駐コストを最小限に抑えられるインスタンスタイプを探す。

今はMemory 8Giある m5.large で動かしてるが、たまにOemKilledやEvicted起こるな...。しゃあない、常駐コスト増えるが16Giのインスタンス採用するか。Podには7Gi割り当てて、1Node 2Podの構成にしよう。

uehruehr

いや、常駐コストケチりたいんで、8Giインスタンスでもう少し探ってみよう

uehruehr

だめそうか...現状以下の構成で常駐になってるけど、このまま動かすと月5万以上掛かってくる想定。
とりあえず今はこのままで、コスト削減は後で対応しよう。

instance: m5.large
default node: 2
ai engine node: 1
uehruehr

だめそうか...現状以下の構成で常駐になってるけど、このまま動かすと月5万以上掛かってくる想定。
とりあえず今はこのままで、コスト削減は後で対応しよう。

instance: m5.large
default node: 2
ai engine node: 1

↑、試算間違えた、この構成だと月3万行かないくらいか

uehruehr

m5.large でAIエンジン動かすと2割のPodでOem Killed発生という話、何回やっても見事に2割に収束する。面白い。

uehruehr

m5.largeより $0.03/hour 高くはなるがメモリ16Gi乗ってる r5.large 試してみるか。

uehruehr

r5.largeを使った2Pod/Nodeの構成でうまく稼働してくれた。このインスタンスで行くか。

uehruehr

もろもろ調整して以下に落ち着いた、この構成で常駐コストは1.7万/月くらいに抑えられるはず。

default node: t3.medium x 1
ai engine node: r5.large x 1