CDK を使って ALB + Fargate を構築する
公開日
2025年4月27日
更新日
2025年4月27日
12
分で読める
AWS
コンテナ化とサーバーレス化を活用することで、サービスアーキテクチャにおける運用作業を大幅に簡素化できます。本記事では、AWS CDK (v2) を用いて Fargate 上にサーバーレスサービスをデプロイする方法を紹介します。
1. プロジェクト構成の概要
開始前に、AWS CDK がインストールされ、TypeScript プロジェクトが初期化されているものとします。ディレクトリ構成の一例は以下のとおりです。
my-cdk-project/
├── bin/
│ └── my-cdk-project.ts // CDK アプリケーションのエントリーポイント
├── lib/
│ └── server-stack.ts // これから作成する Stack
├── package.json
└── tsconfig.json
2. CDK コアコード
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecr from 'aws-cdk-lib/aws-ecr';
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';
import * as log from 'aws-cdk-lib/aws-logs';
import { Construct } from 'constructs';
export class ServerStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// 1. 既存の VPC とセキュリティグループをインポート
const albSg = ec2.SecurityGroup.fromSecurityGroupId(this, 'alb-sg', 'alb-sg-id');
const ecsSg = ec2.SecurityGroup.fromSecurityGroupId(this, 'ecs-sg', 'ecs-sg-id');
const vpc = ec2.Vpc.fromLookup(this, 'vpc', { vpcId: 'vpc-id' });
const albSubnetA = ec2.Subnet.fromSubnetId(this, 'alb-subnet-a', 'alb-subnet-a-id');
const albSubnetC = ec2.Subnet.fromSubnetId(this, 'alb-subnet-c', 'alb-subnet-c-id');
const ecsSubnetA = ec2.Subnet.fromSubnetId(this, 'ecs-subnet-a', 'ecs-subnet-a-id');
const ecsSubnetC = ec2.Subnet.fromSubnetId(this, 'ecs-subnet-c', 'ecs-subnet-c-id');
// 2. 既存の IAM ロールをインポート
const taskRole = iam.Role.fromRoleArn(this, 'task-role', 'task-role-arn', {
mutable: false,
});
const taskExecutionRole = iam.Role.fromRoleArn(this, 'task-execution-role', 'task-execution-role-arn', {
mutable: false,
});
// 3. ECS クラスターを作成
const cluster = new ecs.Cluster(this, 'ecs-cluster', {
vpc: vpc,
clusterName: 'ecs-cluster',
});
// 4. Fargate タスク定義を作成
const taskDefinition = new ecs.FargateTaskDefinition(this, 'task-definition', {
taskRole: taskRole,
executionRole: taskExecutionRole,
cpu: 512,
memoryLimitMiB: 1024,
});
// 5. ECR リポジトリをインポート
const repository = ecr.Repository.fromRepositoryArn(this, 'ecr-repository', 'ecr-arn');
// 6. CloudWatch Logs のロググループを作成
const logGroup = new log.LogGroup(this, 'server-log', {
logGroupName: '/aws/server-log',
retention: log.RetentionDays.THREE_YEARS,
});
// 7. コンテナイメージを構成
taskDefinition.addContainer('task', {
image: ecs.ContainerImage.fromEcrRepository(repository, 'xxxxx'),
logging: ecs.LogDriver.awsLogs({
logGroup: logGroup,
streamPrefix: 'api',
}),
portMappings: [{ containerPort: 80 }],
environment: {
NODE_ENV: 'it',
},
readonlyRootFilesystem: true,
});
// 8. Fargate サービスをデプロイ
const service = new ecs.FargateService(this, 'service', {
serviceName: 'server_name',
cluster: cluster,
taskDefinition: taskDefinition,
securityGroups: [ecsSg],
vpcSubnets: { subnets: [ecsSubnetA, ecsSubnetC] },
});
// 9. アプリケーションロードバランサー (ALB) を作成
const alb = new elbv2.ApplicationLoadBalancer(this, `alb`, {
loadBalancerName: 'alb',
securityGroup: albSg,
vpc: vpc,
vpcSubnets: { subnets: [albSubnetA, albSubnetC] },
});
// 10. ターゲットグループとヘルスチェックを作成
const targetGroup = new elbv2.ApplicationTargetGroup(this, 'alb-tg', {
targetGroupName: '',
vpc: vpc,
port: 80,
protocol: elbv2.ApplicationProtocol.HTTP,
targetType: elbv2.TargetType.IP,
crossZoneEnabled: true,
healthCheck: {
path: '/health',
healthyHttpCodes: '200',
},
targets: [service],
});
// 11. リスナーとルーティングルールを追加
const listener = alb.addListener('alb-listener', {
port: 80,
protocol: elbv2.ApplicationProtocol.HTTP,
open: false,
defaultAction: elbv2.ListenerAction.fixedResponse(404, { contentType: 'application/json' }),
});
new elbv2.CfnListenerRule(this, 'server-rule', {
listenerArn: listener.listenerArn,
priority: 1,
conditions: [
{
field: 'path-pattern',
values: ['/api/*'], // このパスに一致するリクエストのみ Fargate に転送
},
],
actions: [{ type: 'forward', targetGroupArn: targetGroup.targetGroupArn }],
});
}
}
3. まとめ
上記の例を使えば、既存の VPC、サブネット、セキュリティグループ、IAM ロール、ECR リポジトリ、ロググループを再利用し、CDK のコマンド一発でスタック全体をデプロイできます。
- 高可用性:マルチ AZ ロードバランシング + Fargate サーバーレス
- セキュリティ:詳細なセキュリティグループ設定、コンテナのルートファイルシステムを読み取り専用化
- 可観測性:CloudWatch Logs によるリアルタイムログ取得
さらに HTTPS 対応、自動スケーリング、ブルー/グリーンデプロイなどの本番環境向け機能を追加して拡張可能です。コメント欄で皆さんの最適化アイデアをぜひ共有してください!