CloudFormationでAP+DB 2層構成(VPC設計)を自動デプロイする手順【踏み台SSH / コンソール版との比較付き】

AWS Basic
スポンサーリンク
スポンサーリンク

はじめに

「コンソールで20ステップかかったVPC設計をコードで再現したい」——それを実現するのが AWS CloudFormation です。

この記事では、template.yaml 1ファイルにVPC・サブネット・ルートテーブル・セキュリティグループ・EC2(2台)を定義し、コマンド1本でAP+DB 2層構成を一括構築するハンズオンを紹介します。コンソール版(AWSコンソール版ハンズオン)と全く同じ構成を、CloudFormationで自動化します。

ローカル環境(VSCode)
  └── template.yaml + AWS CLI
        ↓ スタック作成(コマンド1本)
AWS環境
  └── VPC(10.0.0.0/16)
        ├── インターネットゲートウェイ
        │
        ├── [パブリックサブネット 10.0.1.0/24]
        │     ├── パブリックルートテーブル(0.0.0.0/0 → IGW)
        │     └── APサーバEC2(Apache / パブリックIP あり)
        │
        └── [プライベートサブネット 10.0.2.0/24]
              ├── プライベートルートテーブル(VPC内のみ)
              ├── S3 VPC Gateway Endpoint(dnf用・無料)
              └── DBサーバEC2(MariaDB / パブリックIP なし)

このハンズオンで体験できること:

  • VPC・サブネット・IGW・ルートテーブルを template.yaml 1ファイルで定義する方法
  • S3 VPC Gateway Endpoint の DependsOn による起動順序制御
  • SubnetId でEC2の配置サブネットを明示する方法
  • aws cloudformation create-stack コマンド1本での17リソース一括デプロイ
  • delete-stack による複雑な依存関係を持つVPCリソースの一括削除

このハンズオンの特徴:

  • コンソール版では20ステップ以上・30〜40分かかった作業が、コマンド1本(8〜12分)で完了
  • delete-stack 1本でVPC・サブネット・IGW・RTの依存関係を自動解決して削除

-->

スポンサーリンク

CloudFormation vs コンソール:どれだけ違うか

比較項目CloudFormationコンソール(手動)
VPC・IGW・サブネット・RTの設定template.yaml に定義済み6画面・20ステップ以上
S3 VPC Endpoint作成template.yaml に定義済み画面でポチポチ
EC2×2台の起動コマンド1本(並列作成)2回インスタンス起動操作
全体のデプロイコマンド1本(8〜12分)20ステップ以上(30〜40分)
削除(依存関係あり)delete-stack 1本(自動解決)8ステップ・手動管理
再現性高い(同じ構成を何度でも再現可能)低い(手順漏れのリスク大)
バージョン管理Gitで管理可能不可

スポンサーリンク

キーワード解説

用語意味
CloudFormationAWSが提供するIaC(Infrastructure as Code)サービス
スタックCloudFormationが管理するリソースのまとまり。今回は17リソースを1スタックで管理
DependsOnCloudFormationでリソースの作成順序を明示するプロパティ
SubnetIdEC2インスタンスを特定のサブネットに配置するプロパティ
S3 VPC Gateway EndpointプライベートサブネットからS3にアクセスするための無料エンドポイント
!Select [0, !GetAZs '']リージョン内の最初のAZを自動取得するCloudFormation関数

前提条件

ツール確認コマンド最低バージョン目安
AWS CLI v2aws --version2.x
Gitgit --version2.x
VSCode--

AWS認証確認:

aws sts get-caller-identity

template.yaml の全文

以下が今回使用する template.yaml の全文です(17リソース)。プロジェクトフォルダ(ec2-2tier-web/)直下に配置します。

⚠️ コピー前に確認: Default: '123.456.78.901/32' の箇所はダミーIPです。このまま使うとスタック作成は成功しますが、SSHもWebもアクセスできません。--parameters でIPを上書きするか(推奨)、Defaultを自分のIPに書き換えてから使ってください。

AWSTemplateFormatVersion: '2010-09-09'
Description: 'EC2 2-tier Architecture (AP + DB) with VPC public/private subnet separation (Phase 1-4)'

Parameters:
  KeyName:
    Type: String
    Default: 'my-ec2-2tier-key'
    Description: Name of an existing EC2 KeyPair

  MyIP:
    Type: String
    Default: '123.456.78.901/32'
    Description: Your IP address to allow SSH and HTTP access (CIDR format e.g. 203.0.113.1/32)

Resources:

  # VPC and Network
  # ============================================================

  # VPC: isolated network space for this hands-on
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: 'my-vpc'

  # Internet Gateway: connects the VPC to the internet
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: 'my-igw'

  # Attach Internet Gateway to VPC
  IGWAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  # Public Subnet: AP server goes here (internet accessible)
  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: !Select [0, !GetAZs '']
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: 'my-public-subnet'

  # Private Subnet: DB server goes here (no direct internet access)
  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: !Select [0, !GetAZs '']
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: 'my-private-subnet'

  # Public Route Table: routes internet traffic via Internet Gateway
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: 'my-public-rt'

  # Default route for public subnet: all traffic -> Internet Gateway
  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: IGWAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  # Associate public subnet with public route table
  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  # Private Route Table: no internet route (local traffic only)
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: 'my-private-rt'

  # Associate private subnet with private route table
  PrivateSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateRouteTable

  # S3 VPC Gateway Endpoint: allows private subnet to reach S3 (for dnf package downloads)
  # Gateway endpoints are FREE - no hourly charge
  S3VPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPC
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
      VpcEndpointType: Gateway
      RouteTableIds:
        - !Ref PrivateRouteTable

  # ============================================================
  # IAM
  # ============================================================

  # IAM Role: allows EC2 to use Session Manager
  EC2Role:
    Type: AWS::IAM::Role
    Properties:
      RoleName: 'my-ec2-2tier-role'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      Tags:
        - Key: Name
          Value: 'my-ec2-2tier-role'

  EC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: 'my-ec2-2tier-profile'
      Roles:
        - !Ref EC2Role

  # ============================================================
  # Security Groups
  # ============================================================

  # AP Server Security Group: SSH and HTTP from MyIP
  APSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: 'my AP server SG (public subnet)'
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref MyIP
          Description: SSH from my IP
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref MyIP
          Description: HTTP from my IP
      Tags:
        - Key: Name
          Value: 'my-ap-sg'

  # DB Server Security Group: MySQL from AP SG only, SSH from AP SG (via bastion)
  DBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: 'my DB server SG (private subnet)'
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          SourceSecurityGroupId: !GetAtt APSecurityGroup.GroupId
          Description: SSH from AP server only (bastion access)
        - IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          SourceSecurityGroupId: !GetAtt APSecurityGroup.GroupId
          Description: MySQL from AP server only (SG-to-SG control)
      Tags:
        - Key: Name
          Value: 'my-db-sg'

  # ============================================================
  # EC2 Instances
  # ============================================================

  # AP Server: Apache in public subnet
  APInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64}}'
      InstanceType: t2.micro
      KeyName: !Ref KeyName
      SubnetId: !Ref PublicSubnet
      SecurityGroupIds:
        - !GetAtt APSecurityGroup.GroupId
      IamInstanceProfile: !Ref EC2InstanceProfile
      UserData:
        Fn::Base64: |
          #!/bin/bash
          dnf update -y
          dnf install -y httpd
          systemctl start httpd
          systemctl enable httpd
          cat > /var/www/html/index.html << 'HTMLEOF'
          <!DOCTYPE html>
          <html>
          <head><meta charset="UTF-8"><title>AP Server - Phase 1-4</title></head>
          <body>
          <h1>AP Server (Public Subnet)</h1>
          <p>This AP server is in the PUBLIC subnet and can reach the DB server in the PRIVATE subnet.</p>
          </body>
          </html>
          HTMLEOF
      Tags:
        - Key: Name
          Value: 'my-ap-instance'

  # DB Server: MariaDB in private subnet (no public IP)
  DBInstance:
    Type: AWS::EC2::Instance
    DependsOn:
      - S3VPCEndpoint
      - PrivateSubnetRouteTableAssociation
    Properties:
      ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64}}'
      InstanceType: t2.micro
      KeyName: !Ref KeyName
      SubnetId: !Ref PrivateSubnet
      SecurityGroupIds:
        - !GetAtt DBSecurityGroup.GroupId
      IamInstanceProfile: !Ref EC2InstanceProfile
      UserData:
        Fn::Base64: |
          #!/bin/bash
          dnf update -y
          dnf install -y mariadb105-server mariadb105
          systemctl start mariadb
          systemctl enable mariadb
          sudo mysql -u root << 'SQLEOF'
          SET PASSWORD FOR root@localhost = PASSWORD('Admin1234!');
          CREATE USER IF NOT EXISTS 'handson'@'%' IDENTIFIED BY 'Handson1234!';
          GRANT ALL PRIVILEGES ON *.* TO 'handson'@'%' WITH GRANT OPTION;
          CREATE DATABASE IF NOT EXISTS sampledb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
          FLUSH PRIVILEGES;
          SQLEOF
      Tags:
        - Key: Name
          Value: 'my-db-instance'

Outputs:
  VPCId:
    Description: VPC ID
    Value: !Ref VPC

  APPublicIP:
    Description: AP server public IP (open in browser or SSH)
    Value: !GetAtt APInstance.PublicIp

  DBPrivateIP:
    Description: DB server private IP (connect via AP server bastion)
    Value: !GetAtt DBInstance.PrivateIp

  WebsiteURL:
    Description: AP server website URL
    Value: !Sub 'http://${APInstance.PublicIp}'

  APSSHCommand:
    Description: SSH command to AP server
    Value: !Sub 'ssh -i C:\Users\username\.ssh\${KeyName}.pem ec2-user@${APInstance.PublicIp}'

  DBSSHCommand:
    Description: SSH command to DB server (run this FROM the AP server)
    Value: !Sub 'ssh -i ~/.ssh/${KeyName}.pem ec2-user@${DBInstance.PrivateIp}'

  MySQLConnectCommand:
    Description: MySQL connect command (run this FROM the AP server)
    Value: !Sub 'mysql -h ${DBInstance.PrivateIp} -u handson -pHandson1234! sampledb'

template.yaml の重要ポイント:

1. VpcId を指定した SecurityGroup

カスタムVPCを使う場合は VpcId を明示します。VpcId を指定することで !GetAtt APSecurityGroup.GroupId が確実にSG IDを返します。

APSecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    VpcId: !Ref VPC      # ← カスタムVPCを指定(必須)

DBSecurityGroup:
  SecurityGroupIngress:
    - SourceSecurityGroupId: !GetAtt APSecurityGroup.GroupId  # ← !Refではなく!GetAtt

2. S3 VPC Gateway Endpoint(無料)

プライベートサブネットのEC2は直接インターネットに出られませんが、Amazon Linux 2023のパッケージリポジトリはS3上にあります。S3 VPC Gateway EndpointをプライベートルートテーブルにアタッチするとS3経由で dnf install が動作します。

S3VPCEndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    VpcEndpointType: Gateway     # Gatewayタイプは無料
    ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
    RouteTableIds:
      - !Ref PrivateRouteTable   # プライベートRTにS3ルートが追加される

3. DBInstance の DependsOn

DBサーバEC2のUserDataが dnf install を実行するとき、S3 VPC Endpointが有効になっている必要があります。

DBInstance:
  DependsOn:
    - S3VPCEndpoint
    - PrivateSubnetRouteTableAssociation

4. SubnetId でサブネットを指定

EC2インスタンスがどのサブネットに配置されるかを明示します。

APInstance:
  SubnetId: !Ref PublicSubnet   # パブリックサブネットに配置

DBInstance:
  SubnetId: !Ref PrivateSubnet  # プライベートサブネットに配置

構築されるリソース一覧(17個):

#リソース論理ID
1VPCVPC
2インターネットゲートウェイInternetGateway
3IGW-VPCアタッチIGWAttachment
4パブリックサブネットPublicSubnet
5プライベートサブネットPrivateSubnet
6パブリックルートテーブルPublicRouteTable
7パブリックルート(→IGW)PublicRoute
8パブリックRT関連付けPublicSubnetRouteTableAssociation
9プライベートルートテーブルPrivateRouteTable
10プライベートRT関連付けPrivateSubnetRouteTableAssociation
11S3 VPC Gateway EndpointS3VPCEndpoint
12IAMロールEC2Role
13インスタンスプロファイルEC2InstanceProfile
14APサーバSGAPSecurityGroup
15DBサーバSGDBSecurityGroup
16APサーバEC2APInstance
17DBサーバEC2DBInstance

作業順序

⓪ 自分のIPアドレスを確認する
      ↓
① キーペアを作成する(コンソールで実施)
      ↓
② プロジェクトフォルダに移動する
      ↓
③ スタックを作成する(aws cloudformation create-stack)
      ↓
④ 作成完了・Outputsを確認する
      ↓
⑤ 動作確認(Web・踏み台SSH・MySQL接続)
      ↓
⑥ スタックを削除する(aws cloudformation delete-stack)

⓪ 自分のIPアドレスを確認する

curl https://checkip.amazonaws.com

控えておく情報: 自分のIPアドレス(例: 203.0.113.1


① キーペアの作成(コンソールで実施)

キーペアのみコンソールで作成します。

AWSコンソール → EC2 → キーペア → 「キーペアを作成」

設定項目
名前my-ec2-2tier-key
キーペアのタイプRSA
プライベートキーファイル形式.pem
C:\Users\ユーザー名\.ssh\my-ec2-2tier-key.pem

② プロジェクトフォルダに移動する

cd C:\my-aws\aws-learning-projects\ec2-2tier-web
dir template.yaml

③ スタックの作成

203.0.113.1 は⓪で確認した自分のIPアドレスに置き換えてください。

aws cloudformation create-stack ^
  --stack-name my-ec2-2tier-stack ^
  --template-body file://template.yaml ^
  --region ap-northeast-1 ^
  --capabilities CAPABILITY_NAMED_IAM ^
  --parameters ^
    ParameterKey=KeyName,ParameterValue=my-ec2-2tier-key ^
    ParameterKey=MyIP,ParameterValue=203.0.113.1/32

各オプションの説明:

オプション意味
--stack-name my-ec2-2tier-stackスタック名(英字始まり)
--template-body file://template.yaml使用するテンプレートファイル
--region ap-northeast-1デプロイ先リージョン(東京)
--capabilities CAPABILITY_NAMED_IAM名前付きIAMロール作成の明示的な許可
--parameters ...テンプレートのParametersに渡す値

成功するとStackIdが表示されます。

{
    "StackId": "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/my-ec2-2tier-stack/xxxxx"
}


④ 作成完了・Outputsの確認

スタック作成完了まで約8〜12分かかります(VPCリソース×10個 + EC2×2台 + MariaDBインストールの時間)。

作成状況の確認

aws cloudformation describe-stacks ^
  --stack-name my-ec2-2tier-stack ^
  --query "Stacks[0].StackStatus" ^
  --output text
ステータス意味
CREATE_IN_PROGRESS作成中(しばらく待つ)
CREATE_COMPLETE作成完了
CREATE_FAILED作成失敗(トラブルシューティングを参照)
ROLLBACK_COMPLETE失敗してロールバック完了

Outputs の確認

aws cloudformation describe-stacks ^
  --stack-name my-ec2-2tier-stack ^
  --query "Stacks[0].Outputs" ^
  --output table

以下のような出力が表示されます。

--------------------------------------------------------------------------------------
|                                  DescribeStacks                                    |
+--------------------+---------------------------------------------------------------+
|  OutputKey         |  OutputValue                                                  |
+--------------------+---------------------------------------------------------------+
|  VPCId             |  vpc-xxxxxxxxxx                                              |
|  APPublicIP        |  x.x.x.x                                                    |
|  DBPrivateIP       |  10.0.2.xxx   ← APサーバからの接続に使用                    |
|  WebsiteURL        |  http://x.x.x.x                                             |
|  APSSHCommand      |  ssh -i ...pem ec2-user@x.x.x.x                            |
|  DBSSHCommand      |  ssh -i ~/.ssh/...pem ec2-user@10.0.2.xxx                  |
|  MySQLConnectCommand| mysql -h 10.0.2.xxx -u handson -pHandson1234! sampledb     |
+--------------------+---------------------------------------------------------------+

控えておく情報:

  • APPublicIP: APサーバのパブリックIP
  • DBPrivateIP: DBサーバのプライベートIP(10.0.2.xxx 形式)
  • APSSHCommand: APサーバへのSSHコマンド
  • DBSSHCommand: APサーバからDBサーバへのSSHコマンド
  • MySQLConnectCommand: APサーバから実行するMySQL接続コマンド


⑤ 動作確認

5-1. APサーバのWeb確認

WebsiteURL をブラウザで開きます。AP Server (Public Subnet) が表示されれば成功です。

5-2. APサーバへのSSH接続

APSSHCommand を実行します(パスを実際のパスに修正します)。

ssh -i C:\Users\ユーザー名\.ssh\my-ec2-2tier-key.pem ec2-user@(APPublicIP)

5-3. キーペアをAPサーバにコピーする(踏み台SSH準備)

ローカルPCの別ターミナルで実行します:

scp -i C:\Users\ユーザー名\.ssh\my-ec2-2tier-key.pem ^
  C:\Users\ユーザー名\.ssh\my-ec2-2tier-key.pem ^
  ec2-user@(APPublicIP):~/.ssh/

APサーバのSSHセッションでパーミッションを設定します。

chmod 400 ~/.ssh/my-ec2-2tier-key.pem

5-4. APサーバ経由でDBサーバにSSH接続(踏み台接続)

APサーバのSSHセッションから実行します:

ssh -i ~/.ssh/my-ec2-2tier-key.pem ec2-user@(DBPrivateIP)

[ec2-user@ip-10-0-2-xxx ~]$ が表示されれば踏み台接続成功です。

# DBサーバ上でMariaDBの状態を確認
sudo systemctl status mariadb

# MariaDBに接続
mysql -u root -pAdmin1234! -e "SHOW DATABASES;"

exit

5-5. APサーバからMySQLに接続(AP→DB通信確認)

APサーバのSSHセッションに戻り、MySQLConnectCommand をそのまま実行します。

# mysqlクライアントをインストール
sudo dnf install -y mariadb105

# OutputsのMySQLConnectCommandをそのまま使う
mysql -h (DBPrivateIP) -u handson -pHandson1234! sampledb
CREATE TABLE IF NOT EXISTS messages (id INT AUTO_INCREMENT PRIMARY KEY, text VARCHAR(100));
INSERT INTO messages (text) VALUES ('Hello from AP server!');
SELECT * FROM messages;
EXIT;
exit


⑥ スタックの削除

課金を止めるために、ハンズオン完了後は必ず削除してください。

CloudFormationはVPC・サブネット・IGW・RT・SG・EC2の依存関係を自動解決して正しい順序で削除します。

aws cloudformation delete-stack ^
  --stack-name my-ec2-2tier-stack ^
  --region ap-northeast-1

削除完了まで約8〜12分かかります。

aws cloudformation describe-stacks ^
  --stack-name my-ec2-2tier-stack ^
  --query "Stacks[0].StackStatus" ^
  --output text
ステータス意味
DELETE_IN_PROGRESS削除中(しばらく待つ)
DELETE_FAILED削除失敗(トラブルシューティングを参照)

削除完了の確認(以下のエラーが表示されれば削除完了)。

aws cloudformation describe-stacks ^
  --stack-name my-ec2-2tier-stack ^
  --region ap-northeast-1
An error occurred (ValidationError) when calling the DescribeStacks operation:
Stack with id my-ec2-2tier-stack does not exist

キーペアは手動で削除します。

EC2 → キーペア → my-ec2-2tier-key → 「削除」


コンソール版との比較

コンソール版で20ステップ以上かかった作業が、CloudFormationでは template.yaml に定義されています。

CFnの記述コンソールでやること
VPCVPC → VPCを作成
InternetGateway + IGWAttachmentIGWを作成 → VPCにアタッチ(2ステップ)
PublicSubnet + PrivateSubnetサブネットを2つ作成
PublicRouteTable + PublicRoute + PublicSubnetRouteTableAssociationパブリックRTを作成・ルート追加・サブネット関連付け(3ステップ)
PrivateRouteTable + PrivateSubnetRouteTableAssociationプライベートRTを作成・サブネット関連付け(2ステップ)
S3VPCEndpointVPCエンドポイントを作成
APSecurityGroup + DBSecurityGroupSGを2つ作成(APサーバSG → DBサーバSGの順)
APInstance + DBInstanceEC2を2回起動(各5〜10分)
delete-stack8ステップの手動削除(依存関係を手動管理)

トラブルシューティング

症状原因対処
CREATE_FAILED になるキーペアが存在しないコンソールでキーペアを確認・作成
CREATE_FAILED になる同名のIAMロールが既に存在するIAMコンソールでロールを削除してから再実行
stackName failed to satisfy regular expressionスタック名が数字始まりCloudFormationのスタック名は英字で始まる必要がある
Unable to load paramfile エラーtemplate.yaml に日本語が含まれているtemplate.yaml のコメントは英語のみで記述する
DBサーバのMariaDBが起動していないS3 VPC EndpointのRouteTableへの反映が遅延DBサーバに踏み台接続して sudo dnf install -y mariadb105-server を手動実行
APサーバからDBにSSH接続できないDBサーバSGのSSHソースが正しくないCloudFormationのイベントログで CREATE_FAILED を確認
DELETE_FAILED になるVPC内のリソースが残っているコンソールで my-vpc 内の残存リソースを確認して手動削除

まとめ

今回のハンズオンで実現できたこと:

確認項目内容
VPCリソースのIaC化VPC・IGW・サブネット・RT 10リソースを template.yaml 1ファイルで定義
S3 VPC EndpointDependsOn でDBサーバEC2の起動前にEndpointが有効になることを保証
一括デプロイcreate-stack 1本で17リソースを8〜12分で構築
依存関係の自動解決delete-stack 1本でVPC内のリソースを正しい順序で自動削除
Outputs活用DBPrivateIPMySQLConnectCommand が自動生成されるため手動でコマンドを組み立てる必要なし

CloudFormationのメリットを実感できたポイント

  • コンソール版では20ステップ以上・30〜40分かかった作業がコマンド1本(8〜12分)で完了
  • VPC・サブネット・RT・SGの複雑な削除順序をCloudFormationが自動管理
  • template.yaml をGitで管理することで、ネットワーク設計の変更履歴が残せる

コンソール版と比較してみる

CloudFormationが裏で何をやっているか、同じ構成をAWSコンソールのみで構築する手順をまとめました。VPCリソースの作成・削除順序や依存関係を視覚的に確認できます。

AWSコンソールでVPC設計からAP+DB 2層構成を構築する手順


関連記事

-->

コメント