ステップ2:ECSクラスターとALBの構築
今回のステップの概要とこのカリキュラムとの関連について
このステップでは、前回構築したVPC上に、ECS on FargateクラスターとApplication Load Balancer(ALB)をAWS CDKで構築します。具体的には、コンテナを動かすためのECSクラスター、外部からのアクセスを受け付けるALB、そしてセキュリティグループとIAMロールをTypeScriptコードで記述します。
コンテナアプリケーションのインフラにとって、ECSクラスターとALBは「商品を並べる棚と、お客様を案内する受付係」のような役割を果たします。ECSクラスターは、Dockerコンテナを動かすための「棚」であり、複数のコンテナを効率的に配置・管理します。ALBは、外部からのHTTP/HTTPSリクエストを受け付け、適切なコンテナに振り分ける「受付係」です。物理的な店舗で言えば、お客様が正面玄関(ALB)から入店し、受付係が商品棚(ECSタスク)まで案内するイメージです。
従来、これらのリソースもAWSコンソールで手作業で作成していましたが、AWS CDKを使えば、VPCと同様にTypeScriptコードで記述し、自動構築できます。さらに、CDKのL2 Constructsを使用することで、複雑な設定をシンプルなコードで表現できます。
このステップで学ぶこと
- ECSクラスターのコード化とFargateの設定
- Application Load Balancerとターゲットグループの構築
- セキュリティグループによるネットワークアクセス制御
- IAMロールとタスクロールの設定
リソースの関わりと構成説明
ステップ2で作成するリソースは、コンテナアプリケーションを動かすための「実行基盤」と「ロードバランサー」を構築するものです。それぞれのリソースがインフラにどのように関わるのかを説明します。
ECS on Fargateクラスターとインフラの関わり
ECS(Elastic Container Service)「Fargateクラスター」は、Dockerコンテナを動かすための「実行基盤」のような役割を果たします。物理的な店舗で言えば、「商品を並べる棚」に相当します。Fargateは、サーバーレスなコンテナ実行環境で、EC2インスタンスを管理する必要がありません。コンテナに必要なCPUとメモリを指定するだけで、AWSが自動的にリソースを割り当て、コンテナを起動します。これにより、インフラ管理の負担を大幅に軽減し、アプリケーション開発に集中できます。
Application Load Balancer(ALB)とインフラの関わり
ALB(Application Load Balancer)「アプリケーションロードバランサー」は、外部からのHTTP/HTTPSリクエストを受け付け、複数のECSタスクに負荷を分散する「受付係」のような役割を果たします。物理的な店舗で言えば、「正面玄関の受付カウンター」に相当します。ユーザーがブラウザでWebサイトにアクセスすると、まずALBがリクエストを受け付け、健全なECSタスクに転送します。1つのタスクに障害が発生しても、ALBが自動的に他の健全なタスクにトラフィックを振り分けるため、サービスが継続します。これにより、高可用性と負荷分散を実現できます。
セキュリティグループとインフラの関わり
セキュリティグループ「仮想ファイアウォール」は、AWSリソースへのネットワークアクセスを制御する「門番」のような役割を果たします。物理的な店舗で言えば、「警備員が入退場を管理するゲート」に相当します。ALB用のセキュリティグループでは、「インターネットからのHTTP(ポート80)とHTTPS(ポート443)のアクセスのみ許可」というルールを設定し、ECSタスク用のセキュリティグループでは、「ALBからのアクセスのみ許可」というルールを設定します。これにより、外部から直接ECSタスクにアクセスすることを防ぎ、セキュリティを確保できます。
IAMロールとタスクロールとインフラの関わり
IAMロール「タスクロール」は、ECSタスクがAWSサービスにアクセスするための「権限証明書」のような役割を果たします。物理的な店舗で言えば、「従業員が倉庫にアクセスするための鍵」に相当します。例えば、コンテナアプリケーションがS3バケットからファイルを読み込んだり、DynamoDBにデータを保存したりする場合、タスクロールに適切な権限(ポリシー)をアタッチします。これにより、アクセスキーをコード内にハードコーディングする必要がなく、セキュアにAWSサービスを利用できます。
実際の手順
実際の手順では、たくさんの設定値を入力することになります。 本文中に設定値が指定されていない場合は、デフォルト値のまま作業を進めてください。
1. ECSクラスターの構築
Fargate対応のECSクラスターをCDKコードで作成します。
AWSでの役割
Amazon ECS(Elastic Container Service)は、Dockerコンテナを大規模に実行・管理するためのフルマネージドなオーケストレーションサービスです。
特徴:
- Fargateモードでは、サーバーレスにコンテナを実行でき、EC2インスタンスの管理が不要
- タスク定義でコンテナの設定(イメージ、CPU、メモリ、環境変数)を定義
- サービスでタスクの数を管理し、自動的にタスクを起動・停止
- CloudWatch Logsと統合され、コンテナのログを一元管理
オンプレミスでの対応
オンプレミス環境では「Kubernetes(K8s)、Docker Swarm」が対応します。
- Kubernetesは、コンテナオーケストレーションのデファクトスタンダード
- Docker Swarmは、Dockerネイティブのオーケストレーションツール
- ECS on Fargateはサーバーレスだが、Kubernetesではノード(サーバー)の管理が必要
1-1. ECSクラスターのCDKコード追加
lib/cdk-iac-project-stack.tsファイルを開き、ECSクラスターのコードを追加します
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
export class CdkIacProjectStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// VPCの作成(ステップ1から継続)
const vpc = new ec2.Vpc(this, 'MyVpc', {
maxAzs: 2,
natGateways: 1,
subnetConfiguration: [
{
cidrMask: 24,
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
cidrMask: 24,
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
},
],
});
// ECSクラスターの作成
const cluster = new ecs.Cluster(this, 'MyCluster', {
vpc: vpc,
clusterName: 'my-fargate-cluster',
containerInsights: true, // CloudWatch Container Insightsを有効化
});
// クラスター名を出力
new cdk.CfnOutput(this, 'ClusterName', {
value: cluster.clusterName,
description: 'ECS Cluster Name',
});
new cdk.CfnOutput(this, 'VpcId', {
value: vpc.vpcId,
description: 'VPC ID',
});
}
}【解説】ECS Fargateとは何か、なぜサーバーレスなのか
ECS Fargateは、AWSが提供するサーバーレスなコンテナ実行環境です。「サーバーレス」とは、サーバーが存在しないわけではなく、サーバーの管理をAWSが代行してくれることを意味します。従来のECS on EC2では、コンテナを動かすためにEC2インスタンスを起動し、そのインスタンスのOS更新、セキュリティパッチ適用、スケーリング設定などを自分で管理する必要がありました。
ECS Fargateでは、これらの管理作業がすべて不要になります。あなたがやるべきことは、「コンテナイメージ」「必要なCPUとメモリ」「ネットワーク設定」を指定するだけです。AWSが自動的に、コンテナを動かすための計算リソースを割り当て、コンテナが停止したら自動的にリソースを回収します。これは、物理的な店舗で言えば、「棚を設置する場所とサイズを指定するだけで、棚の組み立てや配置はすべて業者が代行してくれる」ようなものです。
Container Insightsは、ECSクラスターとタスクのメトリクス(CPU使用率、メモリ使用率、ネットワークトラフィックなど)をCloudWatchで可視化する機能です。有効化すると、ECSクラスター全体のパフォーマンスを監視でき、ボトルネックを特定しやすくなります。ただし、Container Insightsには追加料金がかかるため、本番環境では有効化し、開発環境では無効化するといった使い分けもできます。
1-2. CDKコードの検証とデプロイ
- 変更内容を確認します
cdk diff以下のような出力が表示され、ECSクラスターが作成されることを確認できます。
Stack CdkIacProjectStack
Resources
[+] AWS::ECS::Cluster MyCluster MyClusterXXXXXXXX
[+] AWS::IAM::Role MyCluster/DefaultServiceRole ...
...- ECSクラスターをデプロイします
cdk deploy --region us-east-1デプロイが完了すると、以下のような出力が表示されます。
✅ CdkIacProjectStack
Outputs:
CdkIacProjectStack.ClusterName = my-fargate-cluster
CdkIacProjectStack.VpcId = vpc-0123456789abcdef02. Application Load Balancerの構築
外部からのHTTP/HTTPSリクエストを受け付けるALBを作成します。
2-1. ALBのCDKコード追加
lib/cdk-iac-project-stack.tsに、ALBとセキュリティグループのコードを追加します
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
export class CdkIacProjectStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// VPCの作成(省略)
const vpc = new ec2.Vpc(this, 'MyVpc', {
// ... 省略 ...
});
// ECSクラスターの作成(省略)
const cluster = new ecs.Cluster(this, 'MyCluster', {
// ... 省略 ...
});
// ALB用のセキュリティグループを作成
const albSecurityGroup = new ec2.SecurityGroup(this, 'AlbSecurityGroup', {
vpc: vpc,
description: 'Security group for ALB',
allowAllOutbound: true,
});
// HTTP(ポート80)のインバウンドを許可
albSecurityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(80),
'Allow HTTP traffic from anywhere'
);
// Application Load Balancerの作成
const alb = new elbv2.ApplicationLoadBalancer(this, 'MyAlb', {
vpc: vpc,
internetFacing: true, // インターネット向け
securityGroup: albSecurityGroup,
vpcSubnets: {
subnetType: ec2.SubnetType.PUBLIC, // パブリックサブネットに配置
},
});
// ALBのDNS名を出力
new cdk.CfnOutput(this, 'AlbDnsName', {
value: alb.loadBalancerDnsName,
description: 'ALB DNS Name',
});
new cdk.CfnOutput(this, 'ClusterName', {
value: cluster.clusterName,
description: 'ECS Cluster Name',
});
new cdk.CfnOutput(this, 'VpcId', {
value: vpc.vpcId,
description: 'VPC ID',
});
}
}【解説】Application Load BalancerとClassic Load Balancerの違い
AWSには3種類のロードバランサーがあります。Application Load Balancer(ALB)、Network Load Balancer(NLB)、Classic Load Balancer(CLB)です。このカリキュラムでは、HTTP/HTTPSトラフィックに最適化されたALBを使用します。
ALBは、レイヤー7(アプリケーション層)で動作し、HTTPヘッダーやパスに基づいてルーティングできます。例えば、/api/* へのリクエストはAPIサーバーに、/static/* へのリクエストは静的コンテンツサーバーに振り分けるといった高度なルーティングが可能です。さらに、WebSocketやHTTP/2にも対応しています。
NLBは、レイヤー4(トランスポート層)で動作し、超高速かつ低遅延なトラフィック処理が可能です。TCP/UDPトラフィックに対応し、静的IPアドレスを持つことができます。ただし、HTTP/HTTPSの高度なルーティング機能は持っていません。
CLBは、旧世代のロードバランサーで、現在は新規作成が推奨されていません。レイヤー4とレイヤー7の両方に対応していますが、機能がALBやNLBより限定的です。
internetFacing: true は、ALBをインターネット向けに公開する設定です。この設定により、ALBはパブリックIPアドレスを持ち、外部からアクセス可能になります。逆に、internetFacing: false に設定すると、VPC内部からのみアクセス可能な内部向けALBになります。
2-2. ターゲットグループの作成
- ALBがトラフィックを転送するためのターゲットグループを作成します
// ... 省略(前述のコード) ...
// Application Load Balancerの作成(省略)
const alb = new elbv2.ApplicationLoadBalancer(this, 'MyAlb', {
// ... 省略 ...
});
// ターゲットグループの作成
const targetGroup = new elbv2.ApplicationTargetGroup(this, 'MyTargetGroup', {
vpc: vpc,
port: 80,
protocol: elbv2.ApplicationProtocol.HTTP,
targetType: elbv2.TargetType.IP, // Fargateタスクはタイプ「IP」
healthCheck: {
path: '/api/health',
interval: cdk.Duration.seconds(30),
timeout: cdk.Duration.seconds(5),
healthyThresholdCount: 2,
unhealthyThresholdCount: 3,
},
});
// ALBリスナーの作成(HTTP ポート80)
const listener = alb.addListener('HttpListener', {
port: 80,
protocol: elbv2.ApplicationProtocol.HTTP,
defaultAction: elbv2.ListenerAction.forward([targetGroup]),
});
// ALBのDNS名を出力
new cdk.CfnOutput(this, 'AlbDnsName', {
value: alb.loadBalancerDnsName,
description: 'ALB DNS Name',
});
// ... 省略(以降のコード) ...【解説】ターゲットグループとヘルスチェックの仕組み
ターゲットグループは、ALBがトラフィックを転送する「宛先のグループ」です。ECSの場合、ターゲットは「ECSタスク(コンテナ)」です。ALBは、ターゲットグループに登録されたタスクに、ラウンドロビン方式でリクエストを振り分けます。
targetType: elbv2.TargetType.IP は、Fargateタスクを対象とする設定です。FargateタスクにはENI(Elastic Network Interface)が自動的にアタッチされ、プライベートIPアドレスが割り当てられます。ALBは、このIPアドレスに直接トラフィックを転送します。EC2インスタンス上でECSを動かす場合は、targetType: elbv2.TargetType.INSTANCE を使用します。
ヘルスチェックは、ターゲット(タスク)が正常に動作しているかを定期的に確認する仕組みです。ALBは、指定されたパス(例:/api/health)にHTTPリクエストを送信し、ステータスコード200が返ってくれば「正常」と判断します。もし、タスクがエラーを返したり、応答がない場合は「異常」と判断し、そのタスクへのトラフィック転送を停止します。
interval: cdk.Duration.seconds(30) は、ヘルスチェックを30秒ごとに実行する設定です。timeout: cdk.Duration.seconds(5) は、ヘルスチェックのタイムアウト時間で、5秒以内に応答がなければ失敗と判断します。healthyThresholdCount: 2 は、2回連続で成功すれば正常と判断し、unhealthyThresholdCount: 3 は、3回連続で失敗すれば異常と判断する設定です。
ヘルスチェックの設定を適切に調整することで、タスクの障害を素早く検出し、トラフィックを健全なタスクに振り向けることができます。ただし、ヘルスチェックの頻度を高くしすぎると、タスクへの負荷が増えるため、バランスを考慮する必要があります。
2-3. ALBのデプロイと確認
- 変更内容を確認します
cdk diff --region us-east-1- ALBとターゲットグループをデプロイします
cdk deploy --region us-east-1デプロイが完了すると、ALBのDNS名が出力されます。
✅ CdkIacProjectStack
Outputs:
CdkIacProjectStack.AlbDnsName = CdkIac-MyAlb-XXXXXXXXXXXX.us-east-1.elb.amazonaws.com
CdkIacProjectStack.ClusterName = my-fargate-cluster
CdkIacProjectStack.VpcId = vpc-0123456789abcdef0- AWSコンソールでALBを確認します
- EC2ダッシュボードを開き、左メニューから「ロードバランサ―」を選択
- 「CdkIac-MyAlb-XXXXXXXXXXXX」という名前のALBが作成されていることを確認
- ALBの「リスナーとルール」タブをクリックし、リスナー(HTTP:80)とターゲットグループが設定されていることを確認
【解説】ALBのDNS名とRoute 53によるカスタムドメイン設定
ALBをデプロイすると、xxx.elb.amazonaws.com という長いDNS名が自動的に割り当てられます。このDNS名を使って、ブラウザからALBにアクセスできます。ただし、この名前は覚えにくく、ユーザーに提供するには不便です。
本番環境では、Route 53でカスタムドメイン(例:app.example.com)を設定し、ALBのDNS名にCNAMEレコードで紐付けます。これにより、ユーザーは覚えやすいドメイン名でアプリケーションにアクセスできます。
さらに、AWS Certificate Manager(ACM)でSSL/TLS証明書を発行し、ALBでHTTPS通信を有効化することで、セキュアな通信を実現できます。CDKでは、以下のようにACM証明書をALBリスナーに設定できます。
const certificate = acm.Certificate.fromCertificateArn(
this,
'Certificate',
'arn:aws:acm:us-east-1:123456789012:certificate/xxxxx'
);
alb.addListener('HttpsListener', {
port: 443,
protocol: elbv2.ApplicationProtocol.HTTPS,
certificates: [certificate],
defaultAction: elbv2.ListenerAction.forward([targetGroup]),
});このカリキュラムでは、HTTPのみで学習を進めますが、本番環境ではHTTPSを必ず有効化してください。
3. セキュリティグループとIAMロールの設定
ECSタスク用のセキュリティグループとIAMロールを作成します。
3-1. ECSタスク用セキュリティグループの作成
lib/cdk-iac-project-stack.tsに、ECSタスク用のセキュリティグループを追加します
// ... 省略(前述のコード) ...
// ALB用のセキュリティグループを作成(省略)
const albSecurityGroup = new ec2.SecurityGroup(this, 'AlbSecurityGroup', {
// ... 省略 ...
});
// ECSタスク用のセキュリティグループを作成
const ecsSecurityGroup = new ec2.SecurityGroup(this, 'EcsSecurityGroup', {
vpc: vpc,
description: 'Security group for ECS tasks',
allowAllOutbound: true, // 外部へのアクセスを許可(APIコールやパッケージダウンロードに必要)
});
// ALBからのアクセスのみ許可
ecsSecurityGroup.addIngressRule(
albSecurityGroup,
ec2.Port.tcp(80),
'Allow traffic from ALB'
);
// ... 省略(以降のコード) ...【解説】セキュリティグループのステートフルな動作
セキュリティグループは、ステートフルな仮想ファイアウォールです。「ステートフル」とは、確立された接続(コネクション)を追跡し、送信したトラフィックに対する応答を自動的に許可する仕組みです。例えば、ECSタスクからインターネットにHTTPリクエストを送信する場合、アウトバウンドルールで許可されていれば、そのリクエストに対するレスポンスは自動的に許可されます。インバウンドルールでレスポンスを明示的に許可する必要はありません。これは、「このリクエストはECSタスク自身が送信したものだから、その応答は安全」とセキュリティグループが判断するためです。
このステップで設定したセキュリティグループのルールを整理すると、以下のようになります。
ALB用セキュリティグループ:
- インバウンド: インターネット(0.0.0.0/0)からのHTTP(ポート80)を許可
- アウトバウンド: すべての宛先へのすべてのトラフィックを許可(デフォルト)
ECSタスク用セキュリティグループ:
- インバウンド: ALBからのHTTP(ポート80)を許可
- アウトバウンド: すべての宛先へのすべてのトラフィックを許可
この設定により、外部からの直接的なECSタスクへのアクセスは遮断され、ALBを経由したアクセスのみが許可されます。これは、物理的な店舗で言えば、「お客様は正面玄関(ALB)からしか入店できず、裏口(ECSタスクへの直接アクセス)は従業員専用で鍵がかかっている」という状態です。
セキュリティグループは、最小権限の原則に従って設定することが重要です。必要最小限のポートと送信元のみを許可し、不要な通信はすべて遮断します。例えば、データベースへのアクセスは、アプリケーションサーバーからのみ許可し、インターネットからの直接アクセスは遮断します。
3-2. IAMロールの作成
lib/cdk-iac-project-stack.tsに、ECSタスク実行ロールとタスクロールを追加します
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import * as iam from 'aws-cdk-lib/aws-iam';
export class CdkIacProjectStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// ... 省略 ...
// ALBリスナーの作成(HTTP ポート80)
const listener = alb.addListener('HttpListener', {
// ... 省略 ...
});
// ECSタスク実行ロールの作成
const taskExecutionRole = new iam.Role(this, 'TaskExecutionRole', {
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonECSTaskExecutionRolePolicy'),
],
});
// ECSタスクロールの作成(アプリケーションがAWSサービスにアクセスするための権限)
const taskRole = new iam.Role(this, 'TaskRole', {
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
});
// タスクロールにS3読み取り権限を追加(例)
taskRole.addToPolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['s3:GetObject', 's3:ListBucket'],
resources: ['*'],
})
);
// ALBのDNS名を出力
new cdk.CfnOutput(this, 'AlbDnsName', {
// ... 省略(以降のコード) ...【解説】タスク実行ロールとタスクロールの違い
ECSでは、2種類のIAMロールを使用します。「タスク実行ロール」と「タスクロール」です。この2つの違いを理解することは、ECSのセキュリティ設計において非常に重要です。
**タスク実行ロール(Task Execution Role)**は、ECSサービス自体がコンテナを起動・管理するために使用するロールです。具体的には、ECRからコンテナイメージをプル(ダウンロード)する権限、CloudWatch Logsにログを書き込む権限、Secrets Managerから環境変数を取得する権限などが含まれます。このロールは、コンテナ起動前に使用され、コンテナ内のアプリケーションからは直接アクセスできません。
**タスクロール(Task Role)**は、コンテナ内で動作するアプリケーションがAWSサービスにアクセスするために使用するロールです。例えば、アプリケーションがS3バケットからファイルを読み込んだり、DynamoDBにデータを保存したり、SESでメールを送信したりする場合、タスクロールに適切な権限をアタッチします。このロールは、コンテナ内のアプリケーションから使用され、AWSのSDKが自動的にこのロールの一時認証情報を取得します。
例えるなら、タスク実行ロールは「建築作業員が建物を建てるための権限」、タスクロールは「建物の中で働く従業員が設備を使用するための権限」です。建築作業員は、建物を建てるための工具や材料にアクセスできますが、建物内の設備(オフィス機器など)にはアクセスできません。逆に、従業員は建物内の設備を使用できますが、建物を建てるための工具にはアクセスできません。
セキュリティのベストプラクティスとして、タスクロールには最小権限の原則を適用します。例えば、S3へのアクセスが必要な場合、すべてのS3バケットへのアクセスを許可する s3:* ではなく、特定のバケットにのみアクセスを許可する arn:aws:s3:::my-bucket/* のように、リソースを限定します。
3-3. セキュリティグループとIAMロールのデプロイ
- 変更内容を確認します
cdk diff --region us-east-1- デプロイします
cdk deploy --region us-east-1- AWSコンソールでセキュリティグループとIAMロールを確認します
- VPCダッシュボードの「セキュリティグループ」でECS用セキュリティグループを確認
- IAMダッシュボードの「ロール」の検索欄に「TaskExecutionRole」または「TaskRole」と入力して、タスク実行ロールとタスクロールが存在することを確認
このステップで何をしたのか
このステップでは、ECS on FargateクラスターとApplication Load Balancerを構築しました。具体的には、Fargateで動作するECSクラスター、外部からのHTTPリクエストを受け付けるALB、ターゲットグループとヘルスチェック設定、セキュリティグループによるネットワークアクセス制御、そしてタスク実行ロールとタスクロールによる権限管理を行いました。
このインフラでどのような影響があるのか
この構成により、コンテナアプリケーションを動かすための「実行基盤」と「ロードバランサー」が完成しました。ECSクラスターにより、サーバーレスにコンテナを実行できる環境が整い、ALBにより、外部からのトラフィックを受け付け、複数のコンテナに負荷を分散できるようになりました。
これは、物理的な店舗で言えば、「商品を並べる棚(ECSクラスター)」と「お客様を案内する受付カウンター(ALB)」が完成した状態です。次のステップでは、実際のコンテナアプリケーション(Next.js)を作成し、このECS環境にデプロイして、ブラウザからアクセスできるようにします。
技術比較まとめ表
| 技術領域 | AWS | オンプレミス |
|---|---|---|
| コンテナオーケストレーション | Amazon ECS on Fargate サーバーレス、EC2管理不要、AWSフルマネージド | Kubernetes、Docker Swarm ノード(サーバー)管理が必要、自社でクラスター構築 |
| ロードバランサー | Application Load Balancer レイヤー7、HTTP/HTTPS最適化、自動スケーリング、マネージドサービス | Nginx、HAProxy、F5 自社で構築・管理、スケーリング設定を手動で実施 |
| ネットワークセキュリティ | セキュリティグループ ステートフル、ソフトウェア定義、即座に変更可能 | ファイアウォール、iptables ハードウェアファイアウォールの設定、変更に時間がかかる |
| 権限管理 | IAMロール(タスクロール) 一時認証情報、自動ローテーション、アクセスキー不要 | アクセスキー、API トークン 手動でローテーション、キー漏洩リスク |
| ヘルスチェック | ALBのヘルスチェック 自動的に異常タスクを検出、トラフィックを健全なタスクに振り分け | 手動監視、外部監視ツール Nagios、Zabbixなどで監視、手動でサーバー切り離し |
| デプロイ時間 | cdk deploy で3〜5分 ECS、ALB、セキュリティグループ、IAMロールを自動構築 | 数時間〜数日 ロードバランサー設定、Kubernetes構築、ファイアウォール設定を手動で実施 |
学習において重要な技術的違い
1. サーバーレスコンテナ実行環境の違い
- AWS:ECS Fargateで、EC2インスタンスの管理が不要。コンテナのCPU・メモリを指定するだけで自動的にリソースが割り当てられる
- オンプレミス:Kubernetesのノード(サーバー)を手動で構築・管理する必要がある。OS更新、セキュリティパッチ、ノードのスケーリングをすべて自社で実施
2. ロードバランサーの管理とスケーリング
- AWS:ALBはマネージドサービスで、トラフィック量に応じて自動的にスケーリング。障害時の自動復旧、SSL/TLS終端、ヘルスチェック機能を標準搭載
- オンプレミス:NginxやHAProxyを手動で構築し、冗長化設定(KeepAlived等)、スケーリング設定、SSL証明書管理をすべて自社で実施
3. ネットワークセキュリティの柔軟性
- AWS:セキュリティグループはソフトウェア定義のファイアウォールで、CDKコードで管理可能。変更は即座に反映され、ロールバックも容易
- オンプレミス:ハードウェアファイアウォールやiptablesの設定変更には、ネットワーク機器へのログイン、設定ファイルの編集、テスト、適用という手順が必要。変更に数時間〜数日かかる
4. 権限管理とセキュリティ
- AWS:IAMロールで一時認証情報を使用し、アクセスキーをコードに埋め込む必要がない。ロールの権限変更は即座に反映され、CloudTrailで監査ログを記録
- オンプレミス:APIキーやアクセストークンを環境変数や設定ファイルで管理する必要があり、キー漏洩のリスクが高い。ローテーションは手動で実施
実践チェック:CDKコードと実行結果で証明しよう
下記のチェック項目について、実際にCDKコードを記述し、cdk deploy で構築できていることを確認し、各項目ごとに該当画面のスクリーンショットを撮影して提出してください。
-
ECSクラスターのCDKコードが正しく記述され、
my-fargate-clusterという名前のクラスターが作成されている -
Container Insightsが有効化されており、CloudWatchでECSメトリクスを確認できる
-
ALB用のセキュリティグループが作成され、インターネット(0.0.0.0/0)からのHTTP(ポート80)が許可されている
-
Application Load Balancerが作成され、パブリックサブネットに配置されている
-
ALBのDNS名(
xxx.elb.amazonaws.com)がcdk deployの出力に表示されている -
ターゲットグループが作成され、ヘルスチェックパス
/api/health、間隔30秒が設定されている -
ALBリスナー(HTTP:80)が作成され、ターゲットグループにトラフィックを転送する設定になっている
-
ECSタスク用のセキュリティグループが作成され、ALBからのHTTP(ポート80)のみが許可されている
-
タスク実行ロールが作成され、
AmazonECSTaskExecutionRolePolicyマネージドポリシーがアタッチされている -
タスクロールが作成され、S3読み取り権限(例として追加)が設定されている
提出方法: 各項目ごとにスクリーンショットを撮影し、まとめて提出してください。 ファイル名やコメントで「どの項目か」が分かるようにしてください。 CDKコードのスクリーンショットでは、ECS、ALB、セキュリティグループ、IAMロールの部分が見えるようにしてください。
構成図による理解度チェック
ステップ1の構成図に、このステップで作成したリソースを追記して、現在のインフラ構成を完成させましょう。
なぜ構成図を更新するのか?
ステップ2では、VPCの上にECSクラスター、ALB、セキュリティグループ、IAMロールという多くのリソースを追加しました。これらのリソースがどのように連携し、トラフィックがどのように流れるのかを視覚的に理解することが重要です。
構成図を更新することで、「外部からのHTTPリクエストがALBに到達し、ALBがターゲットグループを通じてECSタスクに転送する」という一連の流れを確認できます。また、「セキュリティグループがALBとECSタスクの間のアクセスを制御している」という関係性も明確になります。
- トラフィックフローの理解: 外部 → ALB → ターゲットグループ → ECSタスクという流れを視覚化する
- セキュリティ境界の理解: セキュリティグループがどのように通信を制御しているかを確認する
- リソース間の関係性: ECSクラスター、ALB、ターゲットグループ、IAMロールがどのように連携しているかを理解する
構成図の書き方
ステップ1で作成した構成図をベースに、以下のリソースを追記してみましょう。
- ECSクラスター: VPC内のプライベートサブネットに配置(まだタスクは配置されていないので、クラスターのアイコンのみ)
- Application Load Balancer: VPC内のパブリックサブネットに配置
- ターゲットグループ: ALBとECSタスクの間に配置(ステップ3でタスクを追加するため、現時点では空)
- セキュリティグループ: ALB用とECS用のセキュリティグループをそれぞれ表示し、通信経路を矢印で示す
- 通信経路: インターネット → IGW → ALB → ターゲットグループ → ECSタスク(次ステップで追加)
💡 ヒント: セキュリティグループは、ファイアウォールのアイコンで表現し、許可されている通信のポート番号(80)を記載すると分かりやすいです。IAMロールは、鍵のアイコンで表現し、タスク実行ロールとタスクロールを区別して記載しましょう。
理解度チェック:なぜ?を考えてみよう
AWSの各リソースや設計には、必ず”理由”や”目的”があります。 下記の「なぜ?」という問いに自分なりの言葉で答えてみましょう。 仕組みや設計意図を自分で説明できることが、真の理解につながります。 ぜひ、単なる暗記ではなく「なぜそうなっているのか?」を意識して考えてみてください。
Q. ECS on FargateとECS on EC2の違いは何ですか?どのような場合にFargateを選び、どのような場合にEC2を選ぶべきですか?
Q. ALBのヘルスチェックで、healthyThresholdCount: 2 と unhealthyThresholdCount: 3 を設定した理由は何ですか?これらの値を変更すると、どのような影響がありますか?
Q. セキュリティグループで、ECSタスク用セキュリティグループのインバウンドルールに「ALBからのアクセスのみ許可」と設定しました。なぜ「すべてのIPアドレス(0.0.0.0/0)からのアクセスを許可」としないのですか?
Q. タスク実行ロールとタスクロールの2つのIAMロールを分けている理由は何ですか?1つのロールにまとめてはいけないのですか?
Q. ALBを internetFacing: true でインターネット向けに公開し、パブリックサブネットに配置しました。一方、ECSタスクはプライベートサブネットに配置します(次ステップ)。なぜこのような構成にするのですか?
今回のステップで利用したAWSサービス名一覧
- Amazon ECS:Dockerコンテナを大規模に実行・管理するフルマネージドなオーケストレーションサービス
- AWS Fargate:サーバーレスなコンテナ実行環境、EC2インスタンス管理が不要
- Application Load Balancer:レイヤー7のロードバランサー、HTTP/HTTPSトラフィックに最適化
- セキュリティグループ:ステートフルな仮想ファイアウォール、インバウンド・アウトバウンドルールで通信を制御
- IAMロール:AWSリソースがAWSサービスにアクセスするための権限、一時認証情報を使用
- CloudWatch Container Insights:ECSクラスターとタスクのメトリクスを可視化する監視機能