AWS初心者がAWS CDKに挑戦してみた #ECS編

に公開

前回はAWS CDKで ALB+EC2+RDS を作成しました
今回はECSを作成していこうと思います
今回のコード一式はこちらに置いています
https://github.com/Peta933/webserver-ecs

構成図とリソース一覧

今回のインフラ構成は以下の通りです。

  • VPC: Public Subnet × 2 / Private Subnet × 2
  • ALB: パブリックサブネットに配置
  • ECS (Fargate): プライベートサブネットに配置し、オートスケーリングとECS Execを有効化
  • ECR: DockerImageAsset を使用してイメージを管理
  • VPCエンドポイント: NAT Gatewayを置かない代わりに、ECR等への通信用に3つ作成

ディレクトリ構造

プロジェクトの構造は、将来的な拡張を見越してConstruct(リソース単位)とStack(統合単位)に分割しています。

.
├── bin/
│   └── webserver-ecs.ts    # エントリポイント。ContextからenvConfigを選択
├── config.ts               # 環境ごとのパラメータ定義(dev/prod)
├── lib/
│   ├── stack/
│   │   └── webserver-ecs-stack.ts  # 各リソースを統合するスタック
│   └── construct/
│       ├── vpc-constructs.ts       # ネットワークリソース
│       ├── ecr-constructs.ts       # Dockerイメージアセット
│       └── ecs-constructs.ts       # ECS/ALB/Scaling/ECS Exec
├── Dockerfile              # アプリケーションのコンテナ定義
└── cdk.json                # CDKの設定ファイル

コードの解説

config.ts

config.ts にて、commonSettings に両環境共通の値をまとめつつ、dev と prod で個別の設定(NAT Gatewayの有無やスペックなど)を定義しました。 デプロイ実行時に cdk deploy -c env=dev または cdk deploy -c env=prod とコンテキストを指定することで、環境を容易に切り分けることが可能です。
https://github.com/Peta933/webserver-ecs/blob/main/config.ts#L103-L106

lib/stack/webserver-ecs-stack.ts

ECS サービスを作成する際、引数を個別に設定する手間を省くため、必要な設定をまとめたインスタンスをそのまま渡す構成としています。
以前 WordPress 環境を作成した際は多くの引数を個別に渡していましたが、今回は可読性と保守性を向上させるため、インスタンスを丸ごと渡す方式を採用しています。
https://github.com/Peta933/webserver-ecs/blob/main/lib/stack/webserver-ecs-stack.ts#L32

lib/construct/vpc-constructs.ts

開発環境(dev)などで natGateway: 0 と設定した場合は、インターネットを経由せずに以下のVPCエンドポイント経由でECRからイメージを取得するように実装しました。

  • ECR API / ECR Docker: イメージの認証とプルに必要。
  • S3 Gateway: 実際のイメージレイヤーをダウンロードするために必須。

https://github.com/Peta933/webserver-ecs/blob/main/lib/construct/vpc-constructs.ts#L25-L34

lib/construct/ecr-constructs.ts

ECR を作成するにあたり、DockerImageAsset を使用しています。
この仕組みを利用することで、CDK が自動的に専用の ECR リポジトリを作成し、docker build から push までを裏側で実行してくれます。
https://github.com/Peta933/webserver-ecs/blob/main/lib/construct/ecr-constructs.ts#L22-L23

lib/construct/ecs-constructs.ts

EcsConstruct 側のインターフェースでは、serviceConfig プロパティを通じて、ECS サービスに関する設定値とその型を一括で指定できるようにしています。
具体的には、キャパシティプロバイダーの設定やオートスケーリングの閾値、クールダウン期間などを一つの構造体として定義しています。
これにより、スタック側から設定を渡す際に入力補完が有効になり、意図しない値の混入を防ぐことができます。

ECS サービスと ALB の構築には、CDK が提供する ApplicationLoadBalancedFargateService という L3コンストラクト を利用しています。
通常、ECS を ALB 配下で動かす場合は、

  • Application Load Balancer の作成
  • ターゲットグループの設定
  • ECS サービスとの紐付け

といった複数のリソースを個別に定義する必要があります。
しかし、この L3 コンストラクトを使うことで、これらの構成を AWS のベストプラクティスに沿った形で一括して定義 することができます。
https://github.com/Peta933/webserver-ecs/blob/main/lib/construct/ecs-constructs.ts#L9-L24

番外編

コードを作成するにあたりコードの質を上げるためにESLintとPrettierを設定してみました
現状はそこまで設定してませんが、今後ちょくちょく改良していこうと思います

.prettierrc.js
設定内容はコメントに追記しています
ここらへんは今後いい感じに改良していきたいと思います
https://github.com/Peta933/webserver-ecs/blob/main/.prettierrc.js

eslint.config.mts
現状は命名規則を入れています

対象 設定
変数 PascalCase, camelCase, UPPER_CASE
型・クラス PascalCase
関数 PascalCase, camelCase

https://github.com/Peta933/webserver-ecs/blob/main/eslint.config.mts#L28-L42

Discussion