2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

背景

先日案件でCloudFormationに触れる機会があり、備忘録も兼ねて簡単なAWS環境を作成してみました。

Cloud Formationとは

AWSの各種リソースをコードで管理できるサービスのことになります。一度コード化してしまえば同様のインフラ環境を何度も繰り返し作成することができるようになります。Cloud Formationのページでテンプレート(YAMlまたはJSONで作成する必要がある)と呼ばれるテキストファイルを読み込むことで、そこに記述されているAWSリソースを自動で作成してくれます。作成されたAWSリソースの料金はかかりますが、Cloud Formation自体の利用料金はかかりません。

作成した環境

今回はパブリックサブネットにEC2が1台、プライベートサブネットにRDSが1台作成される環境を作成してみました。
実際の業務を意識して以下の点を考慮して作成しました。

  • 修正しやすいようにAWSリソースごとにyamlをなるべく分割
  • EC2への外部からのアクセスはhttp通信のみ許可
  • RDSの接続はEC2のみに制限
  • RDSのパスワードはSecrets Managerで管理

作成したyamlファイル

ファイル名 作成されるAWSリソース
vpc.yaml VPC,Internet Gateway
network.yaml Subnet,Route Table,Security Group
iamrole.yaml IAM Role
ec2.yaml EC2,Secrets Manager
rds.yaml RDS

AWS構成図

スクリーンショット 2025-07-05 12.54.10.png

vpc.yaml

AWSTemplateFormatVersion: 2010-09-09
Description: vpc

Parameters:
  Env:
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - prod
    Description: Environment for the VPC

  SystemName:
    Type: String
    Default: test
    Description: Name of the system

  VpcCidr: 
    Type: String
    Default: 10.1.0.0/16

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-vpc"

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-igw"
  
  AttachInternetGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

Outputs:
  VpcId:
    Description: The ID of the VPC
    Value: !Ref VPC
    Export:
      Name: !Sub "${AWS::StackName}-${Env}-VpcId"

  InternetGatewayId:
    Description: The ID of the Internet Gateway
    Value: !Ref InternetGateway
    Export:
      Name: !Sub "${AWS::StackName}-${Env}-InternetGatewayId"

network.yaml

AWSTemplateFormatVersion: 2010-09-09
Description: subnet, security group

Parameters:
  Env:
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - prod
    Description: Environment for the subnet and security group

  SystemName:
    Type: String
    Default: test
    Description: Name of the system

  VpcStackName:
    Type: String
    Default: test-vpc
    Description: Name of the VPC stack to import

  CidrBlockOfPublicSubnet:
    Type: String
    Default: 10.1.0.0/24
    Description: CIDR block for the public subnet

  CidrBlockOfPrivateSubnet1a:
    Type: String
    Default: 10.1.1.0/24
    Description: CIDR block for the private subnet

  CidrBlockOfPrivateSubnet1c:
    Type: String
    Default: 10.1.2.0/24
    Description: CIDR block for the private subnet

Resources:
###########################subnet############################# 
  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !ImportValue
        Fn::Sub: "${VpcStackName}-${Env}-VpcId"
      CidrBlock: !Ref CidrBlockOfPublicSubnet
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-publicsubnet"
  
  PrivateSubnet1a:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !ImportValue
        Fn::Sub: "${VpcStackName}-${Env}-VpcId"
      CidrBlock: !Ref CidrBlockOfPrivateSubnet1a
      AvailabilityZone: ap-northeast-1a
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-privatesubnet1a"

  PrivateSubnet1c:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !ImportValue
        Fn::Sub: "${VpcStackName}-${Env}-VpcId"
      CidrBlock: !Ref CidrBlockOfPrivateSubnet1c
      AvailabilityZone: ap-northeast-1c
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-privatesubnet1c"

###########################route table########################
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !ImportValue
        Fn::Sub: "${VpcStackName}-${Env}-VpcId"
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-public-routetable"
  
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !ImportValue
        Fn::Sub: "${VpcStackName}-${Env}-VpcId"
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-private-routetable"
  
  PublicRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !ImportValue
        Fn::Sub: "${VpcStackName}-${Env}-InternetGatewayId"
  
  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable
  
  PrivateSubnetRouteTableAssociation1a:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1a
      RouteTableId: !Ref PrivateRouteTable

  PrivateSubnetRouteTableAssociation1c:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1c
      RouteTableId: !Ref PrivateRouteTable

############################security group######################
  Ec2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !ImportValue
        Fn::Sub: "${VpcStackName}-${Env}-VpcId"
      GroupDescription: security group for the EC2
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-public-securitygroup"

  RdsSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !ImportValue
        Fn::Sub: "${VpcStackName}-${Env}-VpcId"
      GroupDescription: SecurityGroup for the RdsSecurityGroup
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          SourceSecurityGroupId: !Ref Ec2SecurityGroup
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-rds-securitygroup"

Outputs:
  PublicSubnetId:
    Description: The ID of the public subnet
    Value: !Ref PublicSubnet
    Export:
      Name: !Sub "${AWS::StackName}-${Env}-PublicSubnetId"

  PrivateSubnet1aId:
    Description: The ID of the private subnet 1a
    Value: !Ref PrivateSubnet1a
    Export:
      Name: !Sub "${AWS::StackName}-${Env}-PrivateSubnet1aId"

  PrivateSubnet1cId:
    Description: The ID of the private subnet 1c
    Value: !Ref PrivateSubnet1c
    Export:
      Name: !Sub "${AWS::StackName}-${Env}-PrivateSubnet1cId"

  Ec2SecurityGroupId:
    Description: The ID of the EC2 security group
    Value: !Ref Ec2SecurityGroup
    Export:
      Name: !Sub "${AWS::StackName}-${Env}-Ec2SecurityGroupId"

  RdsSecurityGroupId:
    Description: The ID of the RDS security group
    Value: !Ref RdsSecurityGroup
    Export:
      Name: !Sub "${AWS::StackName}-${Env}-RdsSecurityGroupId"

iamrole.yaml

AWSTemplateFormatVersion: 2010-09-09
Description: vpc

Parameters:
  Env:
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - prod
    Description: Environment for the VPC

  SystemName:
    Type: String
    Default: test
    Description: Name of the system

Resources:
  IamRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${SystemName}-${Env}-IamRole"
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: !Sub "${SystemName}-${Env}-RdsPolicy"
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - rds:*
                Resource: '*'
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-iamrole"

Outputs:
  IamRoleName:
    Description: The name of the IAM Role
    Value: !Ref IamRole
    Export:
      Name: !Sub ${AWS::StackName}-${Env}-IamRoleName

ec2.yaml

AWSTemplateFormatVersion: 2010-09-09
Description: ec2, keypair

Parameters:
  Env:
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - prod
    Description: Environment for the VPC

  SystemName:
    Type: String
    Default: test
    Description: Name of the system

  VpcStackName:
    Type: String
    Default: test-vpc
    Description: Name of the VPC stack to import

  NetWorkStackName:
    Type: String
    Default: test-network
    Description: Name of the network stack to import

  IamRoleStackName:
    Type: String
    Default: test-iamrole
    Description: Name of the IAM role stack to import

Resources:
  KeyPair:
    Type: AWS::EC2::KeyPair
    Properties:
      KeyName: !Sub "${SystemName}-${Env}-keypair"
      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-keypair"

  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !ImportValue 
          Fn::Sub: "${IamRoleStackName}-${Env}-IamRoleName"

  Ec2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: ami-03598bf9d15814511
      KeyName: !Ref KeyPair
      NetworkInterfaces: 
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          SubnetId: !ImportValue 
            Fn::Sub: "${NetWorkStackName}-${Env}-PublicSubnetId"
          GroupSet:
            - !ImportValue
              Fn::Sub:  "${NetWorkStackName}-${Env}-Ec2SecurityGroupId"
      IamInstanceProfile: !Ref InstanceProfile
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          sudo dnf update -y
          sudo dnf install httpd -y
          cd /var/www/html
          sudo touch index.html
          sudo echo '<html><h1>hallo world!</h1></html>' | sudo tee /var/www/html/index.html > /dev/null
          sudo systemctl start httpd
          sudo systemctl enable httpd
          sudo sudo dnf install mariadb105 -y

      Tags:
        - Key: Name
          Value: !Sub "${SystemName}-${Env}-ec2-instance"

Outputs:
  KeyPairName:
    Description: The name of the EC2 Key Pair
    Value: !Ref KeyPair
    Export:
      Name: !Sub "${AWS::StackName}-${Env}-KeyPairName"

  Ec2InstanceId:
    Description: The ID of the EC2 instance
    Value: !Ref Ec2Instance
    Export:
      Name: !Sub "${AWS::StackName}-${Env}-Ec2InstanceId"
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?