先日LightsailがDockerイメージからのデプロイをサポートしました。
https://aws.amazon.com/jp/blogs/news/lightsail-containers-an-easy-way-to-run-your-containers-in-the-cloud/
AWS上でのコンテナサービスはECS/EKSをはじめ様々ありますが、今回のLightsailコンテナは、シンプルなアプリケーションを簡単に提供することに特化したサービスと言うことが出来そうです。
また、ECSのデプロイツールであるCopilotもGAとなりました。
こちらもとても簡単にECS環境が構築できるということで注目です。
そこで、現在AWSでDockerイメージから手軽にWebアプリケーションをデプロイする方法をいくつか比較してそれぞれの使いどころなどを考えてみたいと思います。
今回は手軽にデプロイが可能な方法として以下の3つについて比較します。
Lightsail
Lightsailのコンソールからコンテナサービスを起動することで、All-in-OneのWebアプリケーションが構築できます。
デプロイ手順
参考: プライベートなコンテナイメージを Amazon Lightsail コンテナサービスで使う | Developers.IO
詳細な手順は上記参考記事を見て頂くとして、必要な作業ステップは
- 事前準備
- AWS CLI v2のインストール
- lightsailプラグインのインストール
- DockerイメージをLightsailにpush
3. ローカルでdocker build
を実行
4. AWS CLIでaws lightsail push-container-image ...
を実行 - デプロイ
6. push済みのイメージからデプロイするイメージを選択
7. インスタンスサイズやPort、環境変数などを設定
となります。
コンテナレジストリがアプリケーションにセットで付いていてPushとデプロイがそれぞれ行えるようなイメージですね。
新しいイメージをデプロイした結果ヘルスがNGになった場合は自動で以前の正常なコンテナにロールバックもしてくれるようです。
AutoScaling
インスタンス数の変更やスケールアップはボタン1つで簡単に実行可能ですが、
今のところ、AutoScalingには対応していないようです。
メトリクス
CloudWatchアラームにも今のところ対応していないようですが、
簡単なCPUとメモリの平均のみは確認出来ます。
ログ
CloudWatch logsにログを流すことは出来ないようです。
Lightsailコンソールからのみログを確認することが出来ます。
VPC接続
今のところVPC接続が出来る様子はありません。
あくまでコンテナで簡潔するケース、publicにアクセス出来るサービスとの連携のみで足りるケースでの利用を想定した方がよさそうです。
private subnetにいるRDSと連携するような用途は今のところ難しいのかも。
まとめ
- ローカルでbuildしたイメージをPushしてデプロイするだけ。というのはとてもシンプル
- ロードバランサーも含まれていてある程度の可用性もあるのもよい
- 監視やAutoScalingがちゃんと欲しい場合、RDSにつなぎたい場合など、本格的なサービス提供に使うのは難しそう
Elastic Beanstalk (Docker platform)
BeanstalkのプラットフォームでDockerを選択することで、プラットフォームとしてDockerEngineを動かしてその上でコンテナを起動して動かすことが出来ます。
デプロイ手順
デプロイまでのステップはおおよそ以下の流れになります。
- 事前準備
- Dockerプラットフォームを選択したBeanstalkの環境を作成する
- Beanstalkの構成定義を作成
3. Dockerrun.aws.jsonを作成
4. Dockerfile,Dockerrun.aws.json,Dockerのbuildに必要なファイルを含むArtifact一式を構成 - デプロイ
6.eb deploy
などのコマンドでデプロイ
Dockerrun.aws.jsonサンプル
{
"AWSEBDockerrunVersion": 1,
"Ports": [
{
"ContainerPort": 8000
}
]
}
deploy.zipサンプル
deploy.zip
|- Dockerfile
|- Dockerrun.aws.json
|- index.html
DockerfileとDockerrun.aws.jsonを含むzipファイルを作成し、それをデプロイすることで、各インスタンスでdocker build
& docker run
が実行されコンテナを起動することが出来ます。
ECR等のコンテナレジストリからPullすることも出来ますが、今回想定している簡単なDockerイメージのデプロイという用途としてはこれで十分なケースもあるかと思います。
環境が構築出来れば、後は一式のzipファイルをデプロイするだけですのでその後の展開は容易です。
運用
Beanstalkの場合はEC2インスタンス上でDockerホストが起動してコンテナが立ち上がる構成になるため、標準的な運用インフラはほぼほぼそのまま使えることになります。
EC2単独での実行、ALBとAutoScalingグループを含んだ冗長構成、CloudWatchとの連携やVPC、SecurityGroupの設定など個別のカスタマイズが可能です。
ただし逆に言うとカスタマイズ箇所が多いということでもあり、手軽さという点では一歩劣ります。
EC2インスタンスで動く関係上、Fargateのように細かなCPU/メモリスペックを指定してサービスを構築することは出来ません。
まとめ
- Beanstalkの仕組みに乗る形でコンテナサービスを構築できる
- Beanstalkの運用に慣れている人には向いている
- 必要な機能は一通りカスタマイズして使える
- EC2インスタンス上で動くためECS Fargateほどの柔軟性はない
Copilot (ECS)
CopilotはECSを構築するためのCLIツールで、Copilotが提供するフレームワークに沿った形でサービスを定義して構築することで簡単にECSクラスタやその他必要なリソースを一括作成してくれます。
参考: AWS Copilot のご紹介 | Amazon Web Services ブログ
最近ついにv1.0.0がリリースされました。
手順
参考: ECSのオペレーションを劇的に簡略化するAWS Copilotが発表されました! | Developers.IO
詳細な手順は例によって上記記事が大変詳しいです。いつもありがとうございます。
必要なステップは下記の通りです。
- 事前準備
2. copilotのインストール - 環境の構築
4. Applicationの作成
5. Environmentの作成
6. Serviceの作成
7. Manifestの定義 - デプロイ
Applicationの作成
Getting Startedとしては記事の通りcopilot init
で対話的にセットアップするのが早くて便利ですが、細かくカスタマイズしたい場合はcopilot app init
で始めることで空のアプリケーションを作ることも出来ます。
copilot app init
コマンドではApplicationの登録と、Copilotから諸々操作するのに必要なRoleだけが作られます。
この時Applicationが登録されるAWSアカウントはaws configureでdefaultに紐付けられたアカウントか、環境変数AWS_PROFILE
で指定されたアカウントのようです。
--profile
パラメータは指定出来ません。
Environmentの作成
copilot env init
コマンドでdev/stg/prod/testといった環境を作成出来ます。
ここでは--profile
パラメータも指定出来るため、prod環境だけ別のAWSアカウントへデプロイするといったことも出来そうです。
また、ここでVPCやサブネットを指定することで既存のVPCにタスク定義を配備することも出来ます。
copilot env init --name prod --profile prod-web \
--import-vpc-id vpc-xxxxxxxx \
--import-public-subnets subnet-aaaaaa,subnet-bbbbbbbbb \
--import-private-subnets subnet-ccccccccc,subnet-ddddddddd
Serviceの作成
copilot svc init
コマンドでサービスを定義出来ます。
ここでDockerfileを指定しておきます。
copilot svc init --name api \
--svc-type "Load Balanced Web Service" \
--dockerfile ./Dockerfile
このコマンドで、指定したDockerfileをbuildしてpushするためのECRリポジトリも合わせて作成されます。
Manifestの定義
サービス作成でプロジェクト内に生成された${service-name}/manifest.yml
を編集して必要なインスタンスサイズ等を定義します。
manifest.ymlサンプル
http:
path: '/'
healthcheck: '/health'
cpu: 256
memory: 512
count:
range: 2-3
cpu_percentage: 70
range指定でAutoScalingを設定することも出来ます。
デプロイ
copilot deploy
コマンドで、指定した環境にデプロイが開始されます。
ローカルでdocker buildしたイメージをECRにプッシュし、ECSクラスターを作成し、タスク定義を作成し、サービスを開始するというところまで一気に実行されます。
Lightsailと比較するとさすがに設定項目は多いですが、ECSクラスターを手で構築する手間を考えるとCLIコマンド3つ4つとmanifestファイルの定義のみでWebサービスが立ち上がるのは相当に楽です。
Beanstalkの各種設定と比較してもかなり楽に思えます。
注意点としてはまだGAしたばかりということで細かいところではうまく動かないところもありそうですが今回みたいようなシンプルなケースでは概ね問題なさそうでした。
まとめ
- ECSを少し抽象化したフレームワークのような感触でWebサービスを立ち上げることが出来る
- ECSの構築に必要なロールの扱いなどを意識しなくてよい
料金比較
ここではそれぞれの方法について同程度スペックでの料金比較するため
vCPU : 1
メモリ : 2GB
リージョン : ap-northeast-1
インスタンス数 : 2
の条件で1ヶ月動かした場合の料金を試算してみました。
データ転送量その他の料金は除いた概算です。(2020/12現在)
Lightsail
プランMedium x2 : $80
Beanstalk
EC2 (t2.small) x2 : $49
ALB: $17
合計: $66
ECS
Fargate: $35
ALB: $17
合計: $52
同条件で比較するとLightsailが意外と安くないなという感じになりますね。
あくまで同条件での見積もりになるので、
小規模な場合はどうかというケースで例えばt4g.nano(2vCPU,0.5GB)あたりにするとBeanstalkは$30ほどになりますが、Lightsailではnanoプラン(0.25vCPU,0.5GB)では$14まで下げることができます。
ALBがコミというところにLightsailの料金的な強みがあるので、小規模の方が相対的にLightsailに分があり、規模が大きくなるほどECS Fargateに移行する方がメリットが出てきそうです。
結論
小規模で簡単なアプリケーションを単独でホストしたいならLightsailはとても強いサービスと言えそうです。
一方で出来ないことも多く、本格的なサービス運用にはさすがに向かなそうですので、その場合はCopilotを活用してECSでサービス提供するというのは手軽さを考慮してもとても良さそうに思えます。
Beanstalkによるアプリケーション構築は、Beanstalkでの構築に慣れている人にとっては十分簡単ですが、他の2つと比較すると相対的に重たい手順になってきました。
まとめ始めた時は手軽さ⇔高機能の関係がLightsail < Beanstalk < Copilot
みたいな順になるかなと想像していましたが、思ったよりBeanstalkのメリットが小さくなっていましたね。
少し前までは「とはいえECSは初期セットアップもそれなりに大変ですし学習コストもあるので、簡単なアプリケーションをホストしたいだけであればBeanstalkも便利ですよ」などと推していたりもしたのですが、いよいよBeanstalkのDockerプラットフォームは役割を終えたと言える日が近そうです。
Copilotは先日1.0.0がリリースされたばかりということでこれからもっとECSが使いやすくなっていくと思われるので今後も期待していきたいです。