こんにちは。AWS CLIが好きな福島です。
※5選と言いながら、AWSサービスのアイコン4つしかないですが、Lambdaを使った構成が2つあります。
本ブログでは、WebアプリをデプロイするAWS構成を5つご紹介します。
構成は、Python + サーバーサイドレンダリングを行うことを前提に考えておりますが、 該当しない場合でも、参考にしていただける部分はあるかなと思います。
また、ブログの後半ではAWS構成5選を実際に構築する方法も紹介しております。 その際にデプロイするWebアプリは、以下のブログで紹介したものをデプロイします。
構成
構成パターンは以下の通りです。
- 構成パターン①: WAF + ALB + VPC + EC2
- 構成パターン②: WAF + ALB + VPC + ECS(Fargate)
- 構成パターン③: WAF + App Runner
- 構成パターン④: WAF + ALB + VPC + Lambda
- 構成パターン⑤: WAF + CloudFront + Lambda
画像小さいですが、全ての構成パターンを含めた図は以下の通りです。
各構成ごとの画像は後半に掲載します。
構成パターンの説明
- 全て、送信元のIPでアクセス制限できる構成で考えてみました。
- インターネットからのアクセスを想定した図になっていますが、①-④はプライベートアクセスに限定することも可能です。
- ①,②,④はWAFなしでもALBのセキュリティグループにて、送信元のIPでアクセス制限が可能です。(今回は③,⑤に合わせてWAFを入れています。)
- Webアプリを動かす基盤として、EC2 or ECS(Fargate) or App Runner or Lambdaのどのサービスを使うのかが、各構成でポイントになります。
- Lambdaを使う構成では、LambdaでWebアプリを動かすためのLambda Web Adapterを使います。
- 今回デプロイするWebアプリの都合上、どの構成にもDynamoDBを作成します。
構成判断フロー図
どの構成を利用するかの大枠の判断フローを私なりにまとめてみました。(主観的な要素も含まれてます。)
もちろんこれが全てではないため、開発や運用の体制、個々のワークロードの要件ごとに詳細な確認や検討は必要になります。
説明
- 低コストを重視し、手軽に実装したい場合、Lambdaの利用を検討するのが良いかと思います。
- ただし、Lambdaでは(App Runnerも)Websocketを使えないため、Websocketを使いたい場合、EC2 or ECS(Fargate)を検討する必要があります。
- Websocketは、生成AIを活用したチャットアプリを手軽に作れるStreamlitなどで使われています。
- また、Lambdaのコールドスタートなどにより、個々のワークロードで求める性能(リクエストの処理速度など)を満たせるかは要確認です。
- Lambdaを使わない場合、仮想サーバ(EC2) or コンテナ(ECS(Fargate), App Runner)が選択肢になると思います。
- その際は、アプリの更新頻度が高いのか、コンテナ技術を習得しているのか(学ぶ余裕があるのか)、が判断軸の1つになると思います。
- コンテナ技術を利用するメリットはあるものの、学習ハードルがあるのも事実なので、案件メンバーによって使い慣れた仮想サーバ(EC2)を使う選択もアリだと思います。
- また、コンテナを利用したいけど、できる限り手軽に実装したい場合は、App Runnerを使うのが良いと思います。
- ただし、Websocketが使えなかったり、ALBのCognito統合による認証機能の実装ができないなどの制約もあるので、詳細は要確認です。
各構成にWebアプリをデプロイしてみる
ここから各構成ごとにインフラ構築〜Webアプリをデプロイする例をご紹介します。
デフォルトでは、デプロイしたWebアプリは0.0.0.0/0
でアクセスできるようになっているため、ご注意ください。
送信元のIPを制限したい場合は、parameters.json
もしくはsamconfig.toml
のAllowSourceIp
の設定を変更してください。
まずは、各構成を構築するコードを保存したリポジトリをクローンします。
git clone https://github.com/kazuya9831/blog-sample.git
ディレクトリ構成は以下のイメージです。
$ tree deploy-web-app-to-aws deploy-web-app-to-aws ├── 1_waf-alb-ec2 │ └── ... 省略 ... ├── 2_waf-alb-ecs │ └── ... 省略 ... ├── 3_waf-app-runner │ └── ... 省略 ... ├── 4_waf-alb-lambda │ └── ... 省略 ... ├── 5_waf-cloudfront-lambda │ └── ... 省略 ...
構成パターン①: WAF + ALB + VPC + EC2
デプロイするリソースは以下の通りです。Webアプリは、ユーザーデータを活用し、セットアップします。
ディレクトリを移動する。
cd blog-sample/deploy-web-app-to-aws/1_waf-alb-ec2
CloudFormationをデプロイする。
aws cloudformation deploy \ --stack-name web-app-on-waf-alb-ec2 \ --template-file template.yml \ --parameter-overrides file://parameters.json \ --capabilities CAPABILITY_NAMED_IAM
スタックのアウトプットからWebアプリのURLを確認しブラウザからアクセスする。
echo "http://$(aws cloudformation describe-stacks \ --stack-name "web-app-on-waf-alb-ec2" \ --query "Stacks[].Outputs[?OutputKey=='ALBFQDN'].[OutputValue]" \ --output text)"
正常にデプロイが完了すると以下のように表示されると思います。
構成パターン②: WAF + ALB + VPC + ECS(Fargate)
ディレクトリを移動する。
cd blog-sample/deploy-web-app-to-aws/2_waf-alb-ecs
CloudFormationをデプロイする。
aws cloudformation deploy \ --stack-name web-app-on-waf-alb-ecs \ --template-file template.yml \ --parameter-overrides file://parameters.json \ --capabilities CAPABILITY_NAMED_IAM
コンテナイメージをビルドし、ECRにアップロードします。
cd tools ./build-and-push.sh
ECSのサービス数を1に更新します。
aws ecs update-service \ --cluster web-app-on-waf-alb-ecs-dev-ecs-cluster \ --service web-app-on-waf-alb-ecs-dev-ecs-service \ --desired-count 1
スタックのアウトプットからWebアプリのURLを確認しブラウザからアクセスする。
echo "http://$(aws cloudformation describe-stacks \ --stack-name "web-app-on-waf-alb-ecs" \ --query "Stacks[].Outputs[?OutputKey=='ALBFQDN'].[OutputValue]" \ --output text)"
正常にデプロイが完了すると以下のように表示されると思います。
構成パターン③: WAF + App Runner
ディレクトリを移動する。
cd blog-sample/deploy-web-app-to-aws/3_waf-app-runner
ECRのリポジトリを作成する。
aws ecr create-repository \ --repository-name web-app-on-app-runner-ecr-repository
コンテナイメージをビルドし、ECRにアップロードします。
cd tools ./build-and-push.sh
CloudFormationをデプロイする。
cd ../ aws cloudformation deploy \ --stack-name web-app-on-waf-app-runner \ --template-file template.yml \ --parameter-overrides file://parameters.json \ --capabilities CAPABILITY_NAMED_IAM
スタックのアウトプットからWebアプリのURLを確認しブラウザからアクセスする。
echo "http://$(aws cloudformation describe-stacks \ --stack-name "web-app-on-waf-app-runner" \ --query "Stacks[].Outputs[?OutputKey=='AppRunnerServiceUrl'].[OutputValue]" \ --output text)"
正常にデプロイが完了すると以下のように表示されると思います。
構成パターン④: WAF + ALB + VPC + Lambda
ディレクトリを移動する。
cd blog-sample/deploy-web-app-to-aws/4_waf-alb-lambda
SAMをデプロイする。
sam build && sam deploy
スタックのアウトプットからWebアプリのURLを確認しブラウザからアクセスする。
echo "http://$(aws cloudformation describe-stacks \ --stack-name "waf-alb-lambda" \ --query "Stacks[].Outputs[?OutputKey=='ALBFQDN'].[OutputValue]" \ --output text)"
正常にデプロイが完了すると以下のように表示されると思います。
構成パターン⑤: WAF + CloudFront + Lambda
ディレクトリを移動する。
cd blog-sample/deploy-web-app-to-aws/5_waf-cloudfront-lambda/waf-template
CloudFormationでWAFのWeb ACL,IPSetをデプロイする。スタックをデプロイするリージョンは、バージニア北部です。 WAFのSCOPEがCloudFrontのリソースは、バージニア北部リージョンを指定する必要があるためです。
aws cloudformation deploy \ --stack-name web-app-on-waf-cloudfront-lambda \ --template-file waf-template.yml \ --parameter-overrides file://parameters.json \ --capabilities CAPABILITY_NAMED_IAM \ --region us-east-1
デプロイしたWAFのARNを取得する。
WAF_ARN=$(aws cloudformation describe-stacks \ --stack-name "web-app-on-waf-cloudfront-lambda" \ --query "Stacks[].Outputs[?OutputKey=='WAFWebACLArn'].[OutputValue]" \ --output text \ --region us-east-1 )
SAMで残りのリソースを東京リージョンにデプロイする。
cd ../ sam build && sam deploy --parameter-overrides WAFWebACLArn=${WAF_ARN}
スタックのアウトプットからWebアプリのURLを確認しブラウザからアクセスする。
aws cloudformation describe-stacks \ --stack-name "web-app-on-waf-cloudfront-lambda" \ --query "Stacks[].Outputs[?OutputKey=='CloudFrontDistributionURL'].[OutputValue]" \ --output text
正常にデプロイが完了すると以下のように表示されると思います。
終わりに
今回は、WebアプリをデプロイするAWS構成5選を紹介しました。 どなたかのお役に立てれば幸いです。