😸

WEB3層アーキテクチャをAWS上に作成してみた

2024/12/18に公開

はじめに

2025年1月から、AWS系のエンジニアになることになりました。
今回「Cloudtech」さんの動画でAWSサービスをたくさん触ることができましたので、勉強したことをまとめてみようと思います。
https://kws-cloud-tech.com/

なお、WEBサーバ層とアプリケーション層の中身(ソースコードなど)については、本記事ではノータッチとさせていただきます。
あくまでAWSサービスに絞って、解説させていただきます。

対象

・サーバやネットワーク関連の基礎知識を習得されている方
・今回使用するAWSサービスについて、基礎知識をお持ちの方

作成物

よくあるWeb3層アーキテクチャを以下のように再現してみました。

①WEBサーバ層
S3の静的ウェブサイトホスティング機能とClouFrontを使用しています。
また、独自ドメインでアクセスできるように、Route53で独自ドメインとClouFrontのディストリビューションドメイン名を紐づけています。
通信はHTTPS化したいので、ACMで作成した証明書をClouFrontに配置しています。

②アプリケーション層
ECS+Fargateを採用しています。前段にALBを配置しそのターゲットグループにECSのタスクを指定しています。
また、WEBサーバ層からアプリケーション層の通信をhttps://独自ドメインで実施したいので、ALBに対して、サーバ証明書の配置をし、Route53で独自ドメインとALBのリソース名をAliasレコードとして紐づけています。

③DBサーバ層
RDSを採用し、使用エンジンはMySQLとしています。
※本記事ではあまり深く触れません。

使用したリソース一覧

・Amazon VPC
・Internet Gateway
・Nat Gateway
・Amazon RDS
・Application Load Balancer
・Amazon S3
・Amazon CloudFront
・Amazon Route53
・AWS Certificate Manager
・Amazon ECS
・AWS Fargate

VPC周り準備


以下のリソースを作成します。
VPC
10.0.0.0/16
サブネット

サブネット名 CIDR AZ
elb-subnet-01 10.0.1.0/24 ap-northeast-1a
elb-subnet-02 10.0.2.0/24 ap-northeast-1c
api-subnet-01 10.0.3.0/24 ap-northeast-1a
api-subnet-02 10.0.4.0/24 ap-northeast-1c
DB-subnet-01 10.0.5.0/24 ap-northeast-1a
DB-subnet-02 10.0.6.0/24 ap-northeast-1c

AWS InternetGateway
AWS NATGateway
任意のパブリックサブネットに配置
ルートテーブル
Public用
デフォルトゲートウェイにインターネットゲートウェイを設定

Private用
デフォルトゲートウェイにNAT Gatewayを設定
※api-subnet-01とapi-subnet-02に配置されているタスクから、コンテナイメージ取得時にECRにアクセスするため設定しています。

フロントエンド


以下リソースを作成します。

Route53
独自ドメインでアクセスできるようにしたいので、Route53で独自ドメインとAWSのサービス名をAliasレコードとして紐づけます。
なお、今回は「お名前.com」で購入したドメインをRoute53で管理するので
①「お名前.com」でドメインを購入
②Route53で購入したドメインと同じドメイン名でホストゾーンを作成
③「お名前.com」で管理されているネームサーバを、Route53で管理しているネームサーバに変更する
※example.comというドメインの場合は、.comのレジストリに対して、以下のようなレコードが登録されることで、example.comの名前解決が可能になる。

example.com NS ns-567.awsdns-34.com
example.com NS ns-890.awsdns-56.net
example.com NS ns-123.awsdns-78.co.uk

ACM
今回はClouFrontとALBに証明書を配置するので、二種類のドメイン証明書を発行します。
ちなみにClouFrontに配置する場合は、ACMでの発行時Regionがバージニア北部である必要があるので注意が必要です。
ドメインの所有権を検証する方法は、DNSを選択しましたが、こちらもわざわざRoute53の画面で操作する必要はなく、ACMの画面からDNS検証をすることが可能です。
※ACMが生成した検証用の値と、ACMが指定する検証用ドメインをRoute53でCNAMEとして紐づけることで、DNS検証が完了します。

例
_x1.example.com CNAME _y2.acm-validations.aws

S3
バケットを作成し、その際に静的ウェブサイトホスティングを有効にします。
また、バケットポリシーは以下のようにClouFrontのみからアクセスを許可するようにします。
※バケットポリシーについては、ClouFrontの設定画面から作成可能です

{
        "Version": "2008-10-17",
        "Id": "PolicyForCloudFrontPrivateContent",
        "Statement": [
            {
                "Sid": "AllowCloudFrontServicePrincipal",
                "Effect": "Allow",
                "Principal": {
                    "Service": "cloudfront.amazonaws.com"
                },
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::バケット名(自動入力されます)/*",
                "Condition": {
                    "StringEquals": {
                      "AWS:SourceArn": "CloudFrontのARN(自動入力されます)"
                    }
                }
            }
        ]
      }

このため、直でS3にアクセスしようとすると、以下のようなエラーが表示されます。

CloudFront
ディストリビューションを作成し、オリジンにS3を選択します。またOrigin Access Controlを使用することで、オリジンに指定したS3へのアクセスをCloudFrontからのみに制限することができます。

ちなみにですが、独自ドメインでClouFrontにアクセスできるようにする場合は、CNAMEの登録が必要です。
※ClouFrontとしては、登録されたCNAMEからのリクエストのみを受け付ける仕組みになっているようです。

また、ClouFrontへの通信をSSL化するためには、以下でACMから発行されたサーバ証明書を選択する必要があります。

バックエンド


以下リソースを作成します。

ALB
インターネット向けのALBを作成します。
HTTPSの通信はALBまでで、後続のECSについてはHTTPで通信します。
そのため、リスナーは以下のようになります。

また、リスナープロトコルをHTTPSにすると、サーバ証明書を選択できるようになるので、
ACMで発行した証明書を選択します。

続いて、ターゲットグループを作成します。
ECSのタスクにルーティングするようにしますので、
ターゲットグループ作成時に「ターゲットタイプの選択」でIPアドレスを選択する必要があります。
※この時点では具体的なIPアドレスを指定する必要はありません。
ターゲットグループとタスクの紐づけは、後続のECSのサービス作成時に実施します。

また、S3にホスティングされているWEBサービス層から、アプリケーション層への通信は、ドメイン名で実施したいので、Route53でサブドメインを作成し、AliasレコードとしてALBのサービス名と紐づけておきます。
※S3にアップロードしてある「config.js」というファイルをみて、通信先を判断するようになっていますが、詳細は割愛します。

#「connfig.js」の中身
const apiConfig = {
    baseURL: 'https://api.example.com'
  };

ECS
まずクラスターを作成します。
ここで「インフラストラクチャ」でAWS Fargateを選択します。

次にタスク定義を作成します。
ここで細かなスペックや使用するコンテナイメージを指定します。
ただ、ログについてはデフォルトでCloudWatchに保存されるため、明示的にオフにします。

最後にサービスを作成します。
タスク定義のリビジョンが作成されていた場合は、リビジョンも指定します。

また、ロードバランサーの紐づけを実施するので
先ほど作成したリスナーとターゲットグループを指定する必要があります。

「ネットワーキング」で配置するサブネットや使用するセキュリティグループを選択することができます。
後続のRDSは、アプリケーション層からの3306のみを許可するように設定したいので、
こちらで作成したセキュリティグループを、RDSにアタッチされているセキュリティグループで許可する必要があります。

ちなみに、タスク定義でのコンテナイメージの指定が誤っていたりすると、サービスの作成時にエラーが出ます。

RDS
本記事ではあまり触れることはしませんが、データベース作成後、ECSのサービスで作成したセキュリティグループからの3306のみを許可するようなセキュリティグループを設定します。

終わりに

とりあえず手を動かしてみた。という感じなので、特にECSの細かなパラメーターについてよくわかっていないことがわかりました。
今後ともAWSサービスを継続的に触っていきたいと思います。

Discussion