ECSで複数のサービスを動かすとき、最初からサブネット分離を設計しておかないと、後からセキュリティグループの設定変更が積み重なり、構成が複雑化する。設計の初期段階でVPCとサブネットの分離方針を固めておくことが、後の運用コストを左右する。
この記事では、AWSでマイクロサービスアーキテクチャを組むときのVPCサブネット分離設計と、ECS Fargateを使った実践的な構成パターンを解説します。想定環境はAWS(Amazon Linux 2023)で、ECS Fargateによるコンテナ構成を前提とします。
この記事のポイント
・サービス境界ごとにサブネット分離しSGで通信経路を明示的に制限する
・ECS FargateタスクはプライベートサブネットへデプロイしNATで外部と通信する
・サービス間通信はService ConnectまたはALB(内部)で制御できる
・VPC CIDRはFargateタスク数を考慮しサブネットは/24以上を確保する
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜマイクロサービスにはVPCサブネット分離が必要か
マイクロサービスアーキテクチャでは、API・決済・通知・認証など各機能を独立したサービスとして分割する。これをAWS上で構成するとき、全サービスを同一サブネットに配置してしまうと次の問題が生じる。・障害の横断:あるサービスのセキュリティグループを誤設定すると、同一サブネット内の他サービスに影響が及びやすい
・アクセス制御の複雑化:どのサービスがどのサービスと通信してよいかをSGで細かく制御しにくくなる
・規制対応の困難:決済系・個人情報系サービスをPCI DSSなどのセキュリティゾーンに分離できない
サービス境界に合わせてサブネットを分離し、セキュリティグループでインバウンド・アウトバウンドを明示的に制御することで、これらの問題を回避できる。初期設計での方針決定が、後からの変更コストを大きく左右する。
VPCサブネット分離の設計パターン
1. サービス境界に合わせたサブネット設計
マイクロサービスのサブネット分離には、主に2つのアプローチがある。アプローチA:機能レイヤーで分ける(標準構成)
・パブリックサブネット:ALB(ロードバランサー)のみ配置
・アプリケーション用プライベートサブネット:ECSタスク全般を配置
・データ層プライベートサブネット:RDS・ElastiCacheなどを配置
アプローチB:サービスドメインで分ける(規制対応が必要な場合)
・api-subnet:APIゲートウェイ系ECSサービスを配置
・payment-subnet:決済処理サービス(PCI DSS対応が必要な場合に分離)
・notification-subnet:通知系サービスを配置
中規模構成ではアプローチAが実装しやすい。決済や個人情報処理など規制対応が必要なサービスがある場合は、アプローチAを基本にしつつ対象サービスだけ別サブネットに切り出すハイブリッドが現実的な選択になる。
マルチAZ構成ではAZごとにサブネットを作成する。以下は6サブネット構成の例。
# VPC CIDR: 10.0.0.0/16 # パブリックサブネット(ALBおよびNAT Gateway配置) ap-northeast-1a: 10.0.1.0/24 ap-northeast-1c: 10.0.2.0/24 # アプリケーションサブネット・プライベート(ECSタスク配置) ap-northeast-1a: 10.0.10.0/24 ap-northeast-1c: 10.0.11.0/24 # データ層サブネット・プライベート(RDS・ElastiCache配置) ap-northeast-1a: 10.0.20.0/24 ap-northeast-1c: 10.0.21.0/24 # 将来の拡張用予備帯域: 10.0.30.0/24 ~ 10.0.39.0/24
2. セキュリティグループで通信経路を絞る
サブネット分離だけでは不十分で、セキュリティグループで通信の許可ルールを明示的に定義することが重要。マイクロサービス構成での基本ルールは次のとおり。・ALB-SG:インターネット(0.0.0.0/0)からの443/80番ポートを許可
・ECS-SG(APIサービス):ALB-SGからのポート8080のみ許可。アウトバウンドは決済SGとDB-SGのみ許可
・ECS-SG(決済サービス):API-SGからのポート8081のみ許可
・DB-SG:ECS-SGからのポート3306のみ許可
IPアドレスではなくSG自体をソースとして指定することで、ECSタスクのIPアドレスが変わっても設定変更が不要になる。FargateではタスクごとにENIが割り当てられIPが変わるため、このSGをソース指定にするルールは特に重要。
3. サービス間通信にALBを挟む構成
ECSサービス同士の通信には、内部向けALB(Internet-Facing=false)またはECS Service Connectの2択がある。・内部ALB:HTTP/HTTPSで柔軟なルーティングが可能。ECS以外のサービスとも連携できる
・ECS Service Connect:ECSサービスレベルで直接設定できる軽量な選択肢。追加コストが低い
3サービス以下の小規模構成ならService Connect、5サービス以上やECS以外のサービスと混在する場合は内部ALBが管理しやすい。
ECSでマイクロサービスを実装する構成
1. タスク定義とECSサービスの設計方針
ECSでマイクロサービスを実装するときのタスク定義の基本方針をまとめる。・1タスク1マイクロサービスの原則:APIコンテナと決済コンテナを同一タスクにまとめない。障害範囲を局所化し、スケーリング単位を独立させるため
・コンテナのポートはサービスごとに固定:API=8080、決済=8081のように番号を分けておくとSGのルール管理がしやすい
・環境変数はSSM Parameter Storeから取得:接続先URLや認証情報をタスク定義にハードコードせず、実行時に取得する
タスク定義はJSONまたはTerraformのHCLで管理し、バージョン管理に含めることで環境差分をコードで追跡できる。
2. Fargateとプライベートサブネットの組み合わせ
ECS Fargateのタスクはプライベートサブネットへ配置し、外部への通信はNAT Gatewayを経由させる。この構成によって、ECSタスクに直接インターネットからアクセスできないように制限できる。プライベートサブネット上のFargateタスクがAWS APIに接続するには、NAT Gateway経由かVPCエンドポイント(ECR・SSM・S3等)の設定が必要。VPCエンドポイントを設定するとNAT Gatewayのデータ転送コストを削減できる。
AWSのEC2やAmazon Linux環境でのLinuxサーバー基礎を合わせて学ぶ場合は、AWS(Amazon Linux)入門も参照してください。
以下はAWS CLIでECSサービスをプライベートサブネットに作成するコマンド例(出力例は環境により異なります)。
# ECSサービスをプライベートサブネットへ作成するコマンド例 aws ecs create-service --cluster my-cluster --service-name api-service --task-definition api-task:1 --desired-count 2 --launch-type FARGATE --network-configuration "awsvpcConfiguration={ subnets=[subnet-0abc1234,subnet-0def5678], securityGroups=[sg-0api12345], assignPublicIp=DISABLED }"
{ "service": { "serviceArn": "arn:aws:ecs:ap-northeast-1:123456789012:service/my-cluster/api-service", "serviceName": "api-service", "status": "ACTIVE", "desiredCount": 2, "runningCount": 0 } }
3. Service ConnectによるサービスDNS解決
ECS Service Connectを使うと、サービス名でDNS解決が可能になる。同一名前空間内のサービスから `http://api:8080` のように名前で接続でき、IPアドレス管理が不要になる。# ECSサービスのService Connect設定例(JSON形式) "serviceConnectConfiguration": { "enabled": true, "namespace": "my-app.local", "services": [ { "portName": "api-port", "clientAliases": [ { "port": 8080, "dnsName": "api" } ] } ] }
実践例:3サービス構成のVPC設計
1. VPC CIDRとサブネット割り当て例
APIサービス・決済サービス・通知サービスの3マイクロサービス構成を例にとる。| レイヤー | サブネット名 | CIDR | 配置するリソース |
|---|---|---|---|
| パブリック | public-1a | 10.0.1.0/24 | 外部ALB、NAT Gateway |
| パブリック | public-1c | 10.0.2.0/24 | 外部ALB、NAT Gateway |
| アプリ(プライベート) | app-1a | 10.0.10.0/24 | API・決済・通知ECSタスク |
| アプリ(プライベート) | app-1c | 10.0.11.0/24 | API・決済・通知ECSタスク |
| データ(プライベート) | data-1a | 10.0.20.0/24 | RDS・ElastiCache |
| データ(プライベート) | data-1c | 10.0.21.0/24 | RDS・ElastiCache |
2. セキュリティグループの設定例
APIサービス用SGを作成し、ALBからの通信のみを許可する設定例。# APIサービス用SGの作成 aws ec2 create-security-group --group-name api-sg --description "API Service Security Group" --vpc-id vpc-0abc1234 # ALB-SGからのみポート8080のインバウンドを許可 aws ec2 authorize-security-group-ingress --group-id sg-0api12345 --protocol tcp --port 8080 --source-group sg-0alb12345
設計でよくある失敗パターンと対策
・サブネットのCIDRを小さく切りすぎる:/28(14ホスト)や/27(30ホスト)では、ECSタスクのスケールアウト時にIPアドレスが枯渇する。FargateはタスクごとにENIを割り当てるため、タスク数×2以上のIPを確保できる/24以上が安全・全サービスを同一SGにまとめる:サービスごとに独立したSGを作ることが原則。共通SGを使うとルール変更が全サービスに波及する
・NAT GatewayをAZ共有にする:冗長構成のため、AZごとにNAT Gatewayを配置する。シングルNATにするとそのNAT Gatewayが停止したとき、他のAZのタスクも外部通信ができなくなる
・VPCエンドポイントを設定せずNATコストが膨らむ:FargateタスクがECRからイメージを取得するたびにNAT Gatewayのデータ転送コストが発生する。ECR・S3・SSMのVPCエンドポイントを設定するとコストを大幅に削減できる
本記事のまとめ
| 設計ポイント | 推奨方針 |
|---|---|
| VPCサブネット分離 | パブリック・アプリ・データの3層分離が基本 |
| サブネットのCIDR | Fargateタスク数を考慮して/24以上を確保 |
| セキュリティグループ | サービスごとに個別SG、SGをソースに指定 |
| ECSタスク配置 | プライベートサブネット+NAT Gateway(AZごと配置) |
| サービス間通信 | 小規模はService Connect、大規模は内部ALB |
| コスト最適化 | ECR・S3・SSMのVPCエンドポイントを設定 |
AWSのAmazon Linux環境でのLinuxサーバー設計と運用スキルをハンズオンで学べます。
>> AWS(Amazon Linux)入門ガイドを見る
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:AWSサーバーレスアーキテクチャの冗長設計をStep Functionsで実現する方法|エラー処理の設計
- この記事の属するカテゴリ:AWS(Amazon Linux)へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます