WebアプリをデプロイするAWS構成5選(CFnテンプレート付き)

記事タイトルとURLをコピーする

こんにちは。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.tomlAllowSourceIpの設定を変更してください。

まずは、各構成を構築するコードを保存したリポジトリをクローンします。

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選を紹介しました。 どなたかのお役に立てれば幸いです。

福島 和弥 (記事一覧)

2019/10 入社

AWS CLIが好きです。