Web アプリケーションコンテナをクラスタ無しでデプロイするのに最適な AWS サービスを探したときのメモ

この記事は AWS その2 Advent Calendar 2020 の 16 日目の記事です。

あるコンテナ化された Web アプリケーションを AWS 上にデプロイする必要がありましたので、どのサービスを使うべきか検討したときの話です。

以上の条件下で、コンテナをデプロイするサービスと DB をどうすべきか検討しました。

候補① ECS/Fargate

実際にデプロイしてみましたが、Copilot CLI の出来の良さに驚きました。簡単にデプロイできるし、Application/Service/Environment の抽象化がとても使いやすそうでぜひ今後も使っていきたい… という感じだったのですが、主にFargate の値段の高さに断念しました。

Fargate ではひとつのタスクに割り当てる vCPU を決められるのですが、これが最低 0.25 vCPU です。だいたい月 1000 円ちょっとですが、万が一 0.25 vCPU では足りなくなった場合、ECS/Fargate では AutoScale でタスクをで増やすのが基本的な考え方になります。しかし今回は 1 コンテナのみという条件があるため、もともと余裕を持ってコンテナに CPU を割り振っておかなければなりません。

対して EC2 の場合、2 vCPU を積んだ t3.micro インスタンスでほぼ同じ値段ですから(1 vCPU あたりの性能が単純に比較できない気がしますが、だいたい同じでしょう)、今回の条件で Fargate を採用するのはあまり理に叶った選択ではないと判断しました。

候補② ECS/EC2

こちらも Copilot CLI を使えるあたり本命感が出ていますが、ECS/Fargate を触ってみて分かったのは ECS はクラスタを管理することに特化しているということでした。コンテナはいつ置き換えられても良いという前提の上で動くので、今回のようなアプリケーションだとちょっと余計な心配事を増やすことになるなと考えました。どうせ EC2 の OS 等の管理コストを払うならシングルインスタンスモードもサポートした Beanstalk のほうが良いだろうということで、今回は見送りました。

候補③ Lambda

最近 Lambda のコンテナイメージのサポートが発表されましたが、そもそも Lambda だと 1 つの実行環境(インスタンス)は常に 1 つのリクエストしか受けないというモデルのため、1 つの実行環境がすべてのリクエストを受けるのは現実的ではありません。max_instances の設定値を 1 にすれば Lambda 実行環境も 1 つまでしか立ち上がりませんが、すべてのリクエストが直列に実行されることになってしまいます。

候補④ Elastic Beanstalk

結論から言うと今回は Beanstalk を採用することにしたのですが、初めて触るユーザーからするといろいろと癖が強くかなり苦労させられました。ebcli の単純な使い方で完結する範囲なら良く動いてくれるのですが、.ebextensions に手を出し始めると正直ものすごい手探り状態でした。.ebextensions さえ書けばあとは誰でもデプロイができるようになるかと思えば、VPC Subnet ID など環境によって手動で書き換えなければならない箇所などもあり、最終的には ebcli ではなく CloudFormation(CDK) で Beanstalk 環境を構築することにしました。実例が少なくデプロイが問題なくできるようになるまで何度もトライアンドエラーが必要でしたが、1回のイテレーションにだいたい 5 分ほどかかるのが大変でした。

とまあ恨み言ばかり書きましたが、一度慣れてしまえば EC2 インスタンスをイミュータブルっぽく扱えるのは大きなメリットです。 EC2 なので安く済みますし、Instance Connect で簡単にシェルに入ってデバッグ出来ますし、中で何が動いてるのか理解しやすいという意味では楽でした。

最後にデータベースの選定についてもメモしておきます。

データベース 候補① RDS PostgreSQL

特に Aurora を選ばない理由がなかったので今回は見送りました。

データベース 候補② Aurora Serverless

Serverless という単語に惹かれて Aurora Serverless を検討しましたが、ここ

「サーバーレス」は「クラスターがオンデマンドで自動スケールするのでプロビジョニングが不要」といったニュアンスです。

「サーバーレス」に惑わされないようにしましょう。

と言われてる通りあまりサーバーレスアーキテクチャという感じではありませんでした。Aurora Serverless は「時間あたりの料金が割高な代わりに、一定時間トラフィックが無いと自動的に停止してくれる(再開には 1 分ほどかかる)」という特徴を持った DB ですが、今回は 1 分のレイテンシは許容できなかったので候補から外しました。

データベース 候補③ Aurora

普通にこちらを選びました。

まとめ

普段 Lambda&DynamoDB ばかりで仕事をしているせいで何もかも触ったことのないサービスだったので、とても勉強になる一件でした(その代わりコンテナをひとつ動かすにしては時間を掛けすぎてしまいましたが…)。

また機会があれば Beanstalk(シングルインスタンス) + Aurora を CDK で構築したときに得られた細々とした知見を書けたらいいなと思っています。