はじめに
ここから先は、現在キャッチアップ中のCloudFormationを活用し、自分用のコードを書きながら進めていきます。
【補足事項】
※内容は完全に自分向けとなっています。
また、過去にTerraformを使って構築した環境を、CloudFormationで再現する形で進めています。
このプラットフォーム上に自分専用の備忘録記録を積み重ねていく予定です。あらかじめご了承いただければ幸いです。
実際にコードで行っていること
前回の続きです。
-
AWSプロバイダー設定
- 東京リージョンでリソースを構築する設定。
-
VPC作成
- CIDRブロック範囲
10.0.0.0/16
のVPCを作成。 - DNSサポートとDNSホスト名を有効化。
- CIDRブロック範囲
-
パブリックサブネット作成
- 2つのパブリックサブネットを異なるアベイラビリティゾーンで作成。
- インターネットゲートウェイを通じてインターネットにアクセス可能。
-
プライベートサブネット作成
- 4つのプライベートサブネットを異なるCIDRブロックとアベイラビリティゾーンで作成。
- NATゲートウェイを経由してインターネットにアクセス可能。
-
インターネットゲートウェイ設定
- パブリックサブネットのインターネットアクセスを提供。
-
ルートテーブルの設定
- パブリックサブネット用のルートテーブルを作成し、インターネットゲートウェイをルートに設定。
- プライベートサブネット用のルートテーブルを作成し、NATゲートウェイをルートに設定。
-
NATゲートウェイ設定
- Elastic IPを割り当てたNATゲートウェイを作成。
- プライベートサブネットのアウトバウンド通信をサポート。
-
サブネットとルートテーブルの関連付け
- 各サブネットを対応するルートテーブルに関連付け。
-
セキュリティグループ設定
- SSH(22番)とALB(443番)のインバウンド通信を許可。
- 全アウトバウンドトラフィックを許可。
-
ALBとターゲットグループの設定
- 外部公開用のALBを作成し、HTTPリクエストを処理するターゲットグループを設定(ヘルスチェックとスティッキーセッションを有効化)。
-
ECSインスタンスの登録
- プライベートサブネット内のECSインスタンスをターゲットグループに登録し、ALBを介してリクエストを転送。
-
ECSクラスターとタスク実行ロールの作成
-
ECSクラスター:
ECSサービスを実行するためのクラスターを作成。 -
タスク実行ロール:
ECRアクセスやログ送信権限を付与するIAMロール。
-
ECSクラスター:
-
ECSタスク定義の作成
-
リソース名:Fargate用のタスク(コンテナ)設定を定義。
- CPU: 256
- メモリ: 512
- コンテナ: ECRイメージを使用し、ポート1323を開放。
-
リソース名:Fargate用のタスク(コンテナ)設定を定義。
-
ECSサービスの作成
-
リソース名:ECSクラスター内でタスクを実行するサービスを作成。
- ALBとターゲットグループを使用してアクセスを管理。
- タスクをFargateで1つ実行(
desired_count = 1
)。
-
リソース名:ECSクラスター内でタスクを実行するサービスを作成。
-
ACMによるHTTPS通信の有効化
-
リソース名:ACM (AWS Certificate Manager) を利用して SSL/TLS 証明書を設定し、HTTPS 通信を暗号化。
- ユーザーがアクセスするすべてのトラフィックが HTTPS によって保護。
-
リソース名:ACM (AWS Certificate Manager) を利用して SSL/TLS 証明書を設定し、HTTPS 通信を暗号化。
-
RDSインスタンスの作成
-
リソース名:RDSインスタンスを作成。
- MySQL 8.0を使用したシングルAZのRDSインスタンスをプライベートサブネット内にデプロイ。
- プライベートサブネットを指定して、RDSインスタンスが配置可能なサブネットグループを作成
-
リソース名:RDSインスタンスを作成。
事前準備と補足事項
1. お名前.comで購入したドメインを使用してSSL証明書を取得する方法
AWS ACMとRoute53を利用してSSL証明書を取得する手順については、以下の記事をご参照ください:
2. ALBのAレコードをRoute53のホストゾーンに追加する方法
Terraformで自動デプロイ後、ALBのAレコードをRoute53に追加する手順については、以下の記事をご参照ください:
作ったコードについて
AWSTemplateFormatVersion: "2010-09-09"
Description: CloudFormation template for creating a VPC, subnets, NAT gateway, and related resources.
# 変数の定義
Parameters:
ACMCertificate:
Type: String
Default: "arn:aws:acm:ap-northeast-1:xxx:certificate/d09e0200-6c2e-49d5-a52f-15a1100f8c2a"
Description: "ARN of the ACM Certificate"
Resources:
# VPCの作成
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: "10.0.0.0/16"
InstanceTenancy: "default"
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: "CloudFormation-vpc-vpc"
# パブリックサブネット1の作成
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.0.0/20"
AvailabilityZone: "ap-northeast-1a"
Tags:
- Key: Name
Value: "CloudFormation-vpc-subnet-public1-ap-northeast-1a"
# パブリックサブネット2の作成
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.16.0/20"
AvailabilityZone: "ap-northeast-1c"
Tags:
- Key: Name
Value: "CloudFormation-vpc-subnet-public2-ap-northeast-1c"
# プライベートサブネット1の作成
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.128.0/20"
AvailabilityZone: "ap-northeast-1a"
Tags:
- Key: Name
Value: "CloudFormation-vpc-subnet-private1-ap-northeast-1a"
# プライベートサブネット2の作成
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.144.0/20"
AvailabilityZone: "ap-northeast-1c"
Tags:
- Key: Name
Value: "CloudFormation-vpc-subnet-private2-ap-northeast-1c"
# プライベートサブネット3の作成
PrivateSubnet3:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.160.0/20"
AvailabilityZone: "ap-northeast-1a"
Tags:
- Key: Name
Value: "CloudFormation-vpc-subnet-private3-ap-northeast-1a"
# プライベートサブネット4の作成
PrivateSubnet4:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.176.0/20"
AvailabilityZone: "ap-northeast-1c"
Tags:
- Key: Name
Value: "CloudFormation-vpc-subnet-private4-ap-northeast-1c"
# インターネットゲートウェイの作成
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: "CloudFormation-vpc-igw"
# VPCへのインターネットゲートウェイのアタッチ
AttachInternetGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# パブリックルートテーブルの作成
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: "CloudFormation-vpc-rtb-public"
# パブリックルートの設定
PublicRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref InternetGateway
# パブリックサブネット1をルートテーブルに関連付け
PublicRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
# パブリックサブネット2をルートテーブルに関連付け
PublicRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
# NATゲートウェイ用のElastic IPの作成
NatEIP:
Type: AWS::EC2::EIP
Properties:
Domain: "vpc"
Tags:
- Key: Name
Value: "CloudFormation-vpc-eip-ap-northeast-1a"
# NATゲートウェイの作成
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
SubnetId: !Ref PublicSubnet1
AllocationId: !GetAtt NatEIP.AllocationId
Tags:
- Key: Name
Value: "CloudFormation-vpc-nat-public1-ap-northeast-1a"
# プライベートルートテーブル1の作成
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: "CloudFormation-vpc-rtb-private1-ap-northeast-1a"
# プライベートルート1の設定
PrivateRoute1:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable1
DestinationCidrBlock: "0.0.0.0/0"
NatGatewayId: !Ref NatGateway
# プライベートサブネット1をルートテーブルに関連付け
PrivateRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable1
# プライベートルートテーブル2の作成
PrivateRouteTable2:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: "CloudFormation-vpc-rtb-private2-ap-northeast-1c"
# プライベートルート2の設定
PrivateRoute2:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable2
DestinationCidrBlock: "0.0.0.0/0"
NatGatewayId: !Ref NatGateway
# プライベートサブネット2をルートテーブルに関連付け
PrivateRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRouteTable2
# プライベートルートテーブル3の作成
PrivateRouteTable3:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: "CloudFormation-vpc-rtb-private3-ap-northeast-1a"
# プライベートルート3の設定
PrivateRoute3:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable3
DestinationCidrBlock: "0.0.0.0/0"
NatGatewayId: !Ref NatGateway
# プライベートサブネット3をルートテーブルに関連付け
PrivateRouteTableAssociation3:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet3
RouteTableId: !Ref PrivateRouteTable3
# プライベートルートテーブル4の作成
PrivateRouteTable4:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: "CloudFormation-vpc-rtb-private4-ap-northeast-1c"
# プライベートルート4の設定
PrivateRoute4:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable4
DestinationCidrBlock: "0.0.0.0/0"
NatGatewayId: !Ref NatGateway
# プライベートサブネット4をルートテーブルに関連付け
PrivateRouteTableAssociation4:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet4
RouteTableId: !Ref PrivateRouteTable4
# ECS用セキュリティグループ
ECSGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Security group for ECS instances"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: "tcp"
FromPort: 1323
ToPort: 1323
SourceSecurityGroupId: !GetAtt PublicSG.GroupId
SecurityGroupEgress:
- IpProtocol: "-1"
FromPort: 0
ToPort: 0
CidrIp: "0.0.0.0/0"
Tags:
- Key: Name
Value: "CloudFormation-private-instance-sg"
# ECSクラスターの作成
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: "my-ecs-cluster"
# ECSタスク実行ロールの作成
ECSExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: "ecs-task-execution-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: "ecs-tasks.amazonaws.com"
Action: "sts:AssumeRole"
Policies:
- PolicyName: "ecs-task-execution-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "ecr:GetAuthorizationToken"
- "ecr:GetDownloadUrlForLayer"
- "ecr:BatchGetImage"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "s3:GetObject"
Resource: "*"
# ECSタスク定義の作成
ECSTaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: "my-app-task"
NetworkMode: "awsvpc"
RequiresCompatibilities:
- "FARGATE"
Cpu: "256"
Memory: "512"
ExecutionRoleArn: !GetAtt ECSExecutionRole.Arn
ContainerDefinitions:
- Name: "my-app-repo"
Image: "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-app-repo"
PortMappings:
- ContainerPort: 1323
HostPort: 1323
Protocol: "tcp"
# ECSサービスの作成
ECSService:
Type: AWS::ECS::Service
Properties:
ServiceName: "my-ecs-service"
Cluster: !Ref ECSCluster
TaskDefinition: !Ref ECSTaskDefinition
DesiredCount: 1
LaunchType: "FARGATE"
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- !Ref PublicSubnet1
SecurityGroups:
- !GetAtt ECSGroup.GroupId
AssignPublicIp: "ENABLED"
LoadBalancers:
- TargetGroupArn: !Ref MainTargetGroup
ContainerName: "my-app-repo"
ContainerPort: 1323
DependsOn:
- HttpsListener # HttpListenerではなく、HttpsListenerを指定
# パブリック用セキュリティグループ作成
PublicSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Public security group for ALB"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: "tcp"
FromPort: 443
ToPort: 443
CidrIp: "0.0.0.0/0"
SecurityGroupEgress:
- IpProtocol: "-1"
FromPort: 0
ToPort: 0
CidrIp: "0.0.0.0/0"
Tags:
- Key: Name
Value: "CloudFormation-public-sg"
# アプリケーションロードバランサー(ALB)作成
MainALB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: "cloudformation-main-alb"
Scheme: "internet-facing"
Type: "application"
SecurityGroups:
- !GetAtt PublicSG.GroupId
Subnets:
- !Ref PublicSubnet1
- !Ref PublicSubnet2
Tags:
- Key: Name
Value: "cloudformation-main-alb"
# ターゲットグループ作成
MainTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: "cloudformation-main-target-group"
Port: 1323
Protocol: "HTTP"
VpcId: !Ref VPC
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckProtocol: "HTTP"
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 3
UnhealthyThresholdCount: 3
TargetType: "ip" # ターゲットタイプをIPに設定
Tags:
- Key: Name
Value: "cloudformation-main-target-group"
# ALBのリスナー作成 (HTTPS)
HttpsListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref MainALB
Port: 443
Protocol: "HTTPS"
Certificates:
- CertificateArn: !Ref ACMCertificate
DefaultActions:
- Type: "forward"
TargetGroupArn: !Ref MainTargetGroup
# RDS用セキュリティグループ
RDSSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Security group for RDS"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: "tcp"
FromPort: 3306
ToPort: 3306
CidrIp: "10.0.0.0/16"
SecurityGroupEgress:
- IpProtocol: "-1"
FromPort: 0
ToPort: 0
CidrIp: "0.0.0.0/0"
Tags:
- Key: Name
Value: "CloudFormation-rds-sg"
# RDS用サブネットグループ
RDSSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: "Subnet group for RDS"
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
Tags:
- Key: Name
Value: "CloudFormation-rds-subnet-group"
# RDSインスタンス
RDSInstance:
Type: AWS::RDS::DBInstance
DeletionPolicy: Delete
Properties:
AllocatedStorage: "20" # 無料利用枠に合わせたストレージ
StorageType: "gp2"
Engine: "mysql"
EngineVersion: "8.0.39"
DBInstanceClass: "db.t4g.micro" # Graviton2プロセッサを使用したインスタンス
MasterUsername: "admin"
MasterUserPassword: "mypassword123"
DBParameterGroupName: "default.mysql8.0"
DBSubnetGroupName: !Ref RDSSubnetGroup
VPCSecurityGroups:
- !GetAtt RDSSecurityGroup.GroupId
PubliclyAccessible: false
MultiAZ: false
Tags:
- Key: Name
Value: "CloudFormation-rds-instance"
DeletionProtection: false
まとめ
この記事は、自分用の備忘録としてまとめたものです。その点をご理解いただけると幸いです。
もし、この記事の内容が少しでも参考になれば嬉しく思います。
今後も同様の内容を継続して投稿していきますので、温かく見守っていただけるとありがたいです。
おまけ
お名前.comで取得したドメイン名を使用してアクセスしたところ、以下のようにブラウザで正常に表示されることを確認しました。コード化は大成功です!
また、今回作成したALBのDNS名でも、以下のように正常に表示されることを確認しています。
今回追加で実装したRDSインスタンスについても、マネジメントコンソール上で正しく作成されていることを確認しました。