AWSアーキテクチャ for beginner(Webアプリケーション・コンピューティング編)
はじめに
おはようございます、加藤です。現在AWSには223個(2022/01/05時点)のサービスがあります。コンピューティングのカテゴリだけでも10数個のサービスが存在し、WebアプリケーションをAWS上に構築するエンジニアは要件に応じて利用するサービスを選定しアーキテクチャを決定しなければなりません。
動くだけならばともかくアジリティ・スケーラビリティ・コストパフォーマンスを高水準で満たすアーキテクチャを設計するにはスペシャリストの存在が必要不可欠です。プロジェクトチーム内にスペシャルが存在しない場合は多くの会社がAWSのコンサルティングサービスを提供しているので外注で解決する事ができます。(もちろん、弊社もAWSコンサルティングサービスを提供しております、お気軽にお問い合わせください!)
しかし、コスト・スケジュール・組織的な都合で外注が出来ないことやまずはノウハウを蓄積するためにチャレンジしてみたい場合があります。この記事では、そういったAWS初心者向けのAWSアーキテクチャをデプロイ手法も含めてパターンで紹介します。特徴として初心者向けであるため、アーキテクチャを構築・運用・継続的な改修するための学習コストについても重みをつけてアーキテクチャを検討しています。
タイトルにWebアプリケーション・コンピューティング編とありますが、この記事の対象がWebアプリケーションのコンピューティングが対象であることを明示する意図で続編は予定していません。
アーキテクチャパターン
初心者向けとしては、Amplify Console(静的Webサイトの場合)→App Runner→ECS・Fargate→EC2の順番で検討していただくのが良いと考えています。
Amplify Consoleによる静的Webサイト向けアーキテクチャ
静的なWebサイト(最近のトレンドだとReact、Vue、Next.js、Nuxt.jsなど)向けには、Amplify Consoleがオススメです。静的Webサイトを運用していくために便利な機能が最初から用意されています。
- 静的Webサイトホスティング
- CICDパイプライン
- CDNキャッシュのInvalidation
- Basic認証
- プルリクエスト環境構築
- レスポンスヘッダーのカスタマイズ
Amplify Consoleの構築はコード化せずにマネジメントコンソールから作成し[1]、CICDパイプラインの定義(amplify.yml)はGitリポジトリに含めて行うのがオススメです。Amplify ConsoleにはNext.js限定でサーバーサイドレンダリング(SSR)を提供できる機能がありますが、こちらはバージョン依存が厳しいのでSSRを行いたい場合は後述のApp Runnerを使うことをオススメします。
バックエンド用途には使用できないのでご注意ください。[2]
プルリクエスト毎に環境を作成する機能があるため、ブランチ戦略でGitHubフローを採用した場合においても実際にデプロイされた場合の動作を確認しながらレビュー可能な点がうれしいです。
Amplify Consoleについて詳しくは下記のブログをご参照ください。
フロントエンドエンジニアに捧げるAWS Amplify Console | DevelopersIO
App Runnerによる汎用Webアプリケーション向けアーキテクチャ
App RunnerはWebアプリケーションに特化したコンピューティングサービスです。少ない設定項目でスケーラブルなWebアプリケーション向けのコンピューティングリソースを提供してくれます。AWSが提供するコンテナリポジトリであるECRへイメージがプッシュされると自動でアプリケーションを更新できます(手動更新も可能です)。
ただし同期HTTPリクエストを処理していない時は非アクティブ状態へ移行する仕様のため、バッチ処理やWebSocketやGraphQL Subscriptionには対応していません。
VPC外で実行されるサービスですが、VPCコネクタを利用することでVPC内通信としてRDS/AuroraやElastiCacheなどを利用できます。コネクタを使用するとApp Runnerから始めるアウトバウンド通信はVPC内から出て行くためインターネットへ通信が必要な場合はNat Gatewayが必要になります。(ユーザーリクエストに対するレスポンスはVPC外で行われます。)また、AWS API呼び出し(S3へのアクセスなど)にもNat Gatewayが必要になります。[3]
バックエンドのWebAPIとしての提供はもちろん、サーバーサイドテンプレーティング(テンプレートを使ったサーバーサイドでの動的なHTML生成)、サーバーサイドレンダリングのデプロイ先として利用できます。
リポジトリにGitHubを使用する場合、GitHub ActionsでAWSが提供している aws-actions/amazon-ecr-login を使うことで、ビルドしたコンテナイメージを簡単にECRにアップロードできます。前述のとおり、App RunnerはECRへのプッシュをトリガーにアプリケーションの更新ができます。
自動更新は検証環境だけにして、本番環境では自動デプロイせず、コンテナイメージタグにGitコミットハッシュを設定しておきリリースしたいタイミングでマネジメントコンソールからデプロイを行うようにすると実際の動作を確認してから本番環境へデプロイが行えます。検証環境にもコミットハッシュのついたタグを設定しておくことで、任意のバージョンの動作を確認ができて便利です。
App Runnerはコンテナーを使わずAmplify Consoleのようにサービス内にアプリケーションをビルド・テスト・実行する仕組みを提供しています(対応言語はPython、Node.js、Java)。運用の柔軟性を削ってもAWS構成リソースを減らして管理を簡単にしたい場合は利用を検討しましょう。
App Runnerの構築はコード化に慣れていないのであればマネジメントコンソールでの作成で良いと考えています。App Runnerは数個の設定項目でスケーラブルな環境を提供してくれるのでマネジメントコンソールで構築しても管理が破綻しません。どちらかというとApp Runnerから繋がるリソースの複雑さで考えると良いでしょう。RDS/Auroraと繋ぐだけならセーフだけどさらに複数個のVPCエンドポイントやElastiCacheも必要で開発・検証・本番の3環境作らないといけない。。。となってくる場合はコード化しないと管理が厳しくなります。RDS/Auroraと本番・検証の2環境ぐらいならコード化しなくても良いかなというのが私の感触です。(前述の通りコード化に慣れていないのであればです)
ECS・FargateによるLinuxアプリケーション向けアーキテクチャ
ここまで紹介した方法では実現できないアプリケーションの場合は、ECS・Fargateを検討してください。たとえば下記のような場合はECSを使用する必要があります。
- リクエストを受けるのではなく外部からデータをPullして処理を行う
- レスポンスを返してから非同期で処理を継続する
- 定期的にバッチ処理を行う必要がある
- 複数のコンテナ間のリクエストプライベートネットワーク内で行いたい(≒認証を実装したくない)
また、AWS WAFはWAFを当てたCloudFrontを用意してオリジンとしてApp Runnerを構築すれば使えますが、App RunnerのURLが流出すると直接アクセスが飛んできます。アプリケーションでHTTPヘッダーを解析しCloudFront経由を強制できますが、わずかとはいえアプリケーションがリクエストを処理してしまうのでそこについては許容する必要があります。
EC2によるLinuxアプリケーション向けアーキテクチャ
どうしてもECS・Fargateで実現できないアプリケーションの場合は、EC2を使用してください。この場合でもスケーリングさせたい、オートヒーリングさせたい要望があるならばゴールデンAMIを作成してそれを使ってAuto Scalingを作成することをオススメします。
既存の仮想マシン上で動いているアプリケーションをAWSへ移行する場合は、前述のアーキテクチャではコンテナ化が必要なのでそれを嫌ってEC2を検討することがあるかもしれません。そのアプリケーションが継続的に機能改修する予定が無かったり、数年後でのリタイヤを予定しているならその判断はアリだと思います。
ですが、Dockerによって実現できる事柄が必要なく、これから学ぶことにコストがかかるからといった理由なら考え直して欲しいです。Dockerのエコシステムがここまで発達し、情報もインターネット・書籍ともに調達しやすくなった現在では非常に学習がしやすいし、本質的にDockerが必要かといったことを深く考えずに採用し、巨人の肩に乗った方がパフォーマンスを発揮できると私は考えています。
あとがき
色々と説明不足なところがあるけど、ここまで書くのにだいぶ時間がかかってしまってこれ以上は没になりそうだったので雑だけどリリースします。
-
Amplify ConsoleのGitHub連携をコード化して行う為にはGitHub Private Access Tokenが必要となる。そのためBotアカウントを作成してそのアカウントでトークンを発行してAWS Secret Managerに登録するなどの考慮が必要になり手間がかかる。なので記事中ではマネジメントコンソールでの作成を進めている。フロントエンドのリポジトリが独立しているのならば、初心者に限らずこのやり方で良いと考えている。モノレポ構成の場合は、Amplify ConsoleではなくCloudFront+S3でAWS CDKなどを使って実現するとS3 Deploymentなど便利なコンポーネントがあるためやりやすいと考えている。 ↩︎
-
Amplify ConsoleでNext.jsを使いSSRすればWebAPIとしても動作させることができるかもしれないが、VercelではなくAWSを使っているのにそれはやらないので考慮しませんでした。 ↩︎
-
もしくはAWSサービスに対応するVPCエンドポイントを作成することでも対処できます。インターフェイスVPCエンドポイントの場合はSDKでエンドポイントを設定する必要があるのでご注意ください。 AWS PrivateLink for Amazon S3 - Amazon Simple Storage Service ↩︎
Discussion