[AWS CloudFormation] ECS + Fargate

AWSTemplateFormatVersion: "2010-09-09"
Description:
  Fargate for ECS Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          default: "InternetALB Configuration"
        Parameters:
          - InternetALBName
          - TargetGroupName
      - Label:
          default: "Fargate for ECS Configuration"
        Parameters:
          - ECSClusterName
          - ECSTaskName
          - ECSTaskCPUUnit
          - ECSTaskMemory
          - ECSContainerName
          - ECSImageName
          - ECSServiceName
          - ECSTaskDesiredCount

    ParameterLabels:
      IneternetALBName:
        default: "InternetALBName"
      TargetGroupName:
        default: "TargetGroupName"
      ECSClusterName:
        default: "ECSClusterName"
      ECSTaskName:
        default: "ECSTaskName"
      ECSTaskCPUUnit:
        default: "ECSTaskCPUUnit"
      ECSTaskMemory:
        default: "ECSTaskMemory"
      ECSContainerName:
        default: "ECSContainerName"
      ECSImageName:
        default: "ECSImageName"
      ECSServiceName:
        default: "ECSServiceName"
      ECSTaskDesiredCount:
        default: "ECSTaskDesiredCount"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

#InternetALB
  InternetALBName:
    Type: String
    Default: "alb"

#TargetGroupName
  TargetGroupName:
    Type: String
    Default: "tg"

#ECSClusterName
  ECSClusterName:
    Type: String
    Default: "cluster"

#ECSTaskName
  ECSTaskName:
    Type: String
    Default: "task"

#ECSTaskCPUUnit
  ECSTaskCPUUnit:
    AllowedValues: [256, 512, 1024, 2048, 4096]
    Type: String
    Default: "256"

#ECSTaskMemory
  ECSTaskMemory:
    AllowedValues: [ 256, 512, 1024, 2048, 4096 ]
    Type: String
    Default: "512"

#ECSContainerName
  ECSContainerName:
    Type: String
    Default: "container"

#ECSImageName
  ECSImageName:
    Type: String
    Default: ""

#ECSServiceName
  ECSServiceName:
    Type: String
    Default: "service"

#ECSTaskDesiredCount
  ECSTaskDesiredCount:
    Type: Number
    Default: 1

Resources:
# ------------------------------------------------------------#
#  SecurityGroup for ALB
# ------------------------------------------------------------#
  ALBSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      GroupName: !Sub "${PJPrefix}-alb-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-alb-sg"

# Rule
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: "0.0.0.0/0"

        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: "0.0.0.0/0"

# ------------------------------------------------------------#
#  SecurityGroup for ECS Service
# ------------------------------------------------------------#
  ECSSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      GroupName: !Sub "${PJPrefix}-ecs-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-ecs-sg"

# Rule
  ECSSecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    Properties:
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      SourceSecurityGroupId: !GetAtt [ ALBSecurityGroup, GroupId ]
      GroupId: !GetAtt [ ECSSecurityGroup, GroupId ]

# ------------------------------------------------------------#
#  Target Group
# ------------------------------------------------------------#
  TargetGroup:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc"}
      Name: !Sub "${PJPrefix}-${TargetGroupName}"
      Protocol: HTTP
      Port: 80
      TargetType: ip


# ------------------------------------------------------------#
#  Internet ALB
# ------------------------------------------------------------#
  InternetALB:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties:
      Name: !Sub "${PJPrefix}-${InternetALBName}"
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-${InternetALBName}"
      Scheme: "internet-facing"
      LoadBalancerAttributes:
        - Key: "deletion_protection.enabled"
          Value: false
        - Key: "idle_timeout.timeout_seconds"
          Value: 60
      SecurityGroups:
        - !Ref ALBSecurityGroup
      Subnets:
        - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
        - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }

  ALBListener:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref TargetGroup
          Type: forward
      LoadBalancerArn: !Ref InternetALB
      Port: 80
      Protocol: HTTP

# ------------------------------------------------------------#
# ECS Cluster
# ------------------------------------------------------------# 
  ECSCluster:
    Type: "AWS::ECS::Cluster"
    Properties:
      ClusterName: !Sub "${PJPrefix}-${ECSClusterName}"

# ------------------------------------------------------------#
#  ECS LogGroup
# ------------------------------------------------------------#
  ECSLogGroup:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Sub "/ecs/logs/${PJPrefix}-ecs-group"

# ------------------------------------------------------------#
#  ECS TaskDefinition
# ------------------------------------------------------------#
  ECSTaskDefinition:
    Type: "AWS::ECS::TaskDefinition"
    Properties:
      Cpu: !Ref ECSTaskCPUUnit
      ExecutionRoleArn: !Sub "arn:aws:iam::${AWS::AccountId}:role/ecsTaskExecutionRole"
      Family: !Sub "${PJPrefix}-${ECSTaskName}"
      Memory: !Ref ECSTaskMemory
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE

#ContainerDefinitions
      ContainerDefinitions:
        - Name: !Sub "${PJPrefix}-${ECSContainerName}"
          Image: !Ref ECSImageName
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Ref ECSLogGroup
              awslogs-region: !Ref "AWS::Region"
              awslogs-stream-prefix: !Ref PJPrefix
          MemoryReservation: 128
          PortMappings:
            - HostPort: 80
              Protocol: tcp
              ContainerPort: 80

# ------------------------------------------------------------#
#  ECS Service
# ------------------------------------------------------------#
  ECSService:
    Type: AWS::ECS::Service
    DependsOn: ALBListener
    Properties:
      Cluster: !Ref ECSCluster
      DesiredCount: !Ref ECSTaskDesiredCount
      LaunchType: FARGATE
      LoadBalancers:
        -
          TargetGroupArn: !Ref TargetGroup
          ContainerPort: 80
          ContainerName: !Sub "${PJPrefix}-${ECSContainerName}"
      NetworkConfiguration:
       AwsvpcConfiguration:
           AssignPublicIp: ENABLED
           SecurityGroups:
             - !Ref ECSSecurityGroup
           Subnets:
             - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
             - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }
      ServiceName: !Sub "${PJPrefix}-${ECSServiceName}"
      TaskDefinition: !Ref ECSTaskDefinition

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
#InternetALB
  ALBDNSName:
    Value: !GetAtt InternetALB.DNSName
    Export:
      Name: !Sub "${PJPrefix}-${InternetALBName}-dnsname"

#ECSClusterName
  ECSClusterName:
    Value: !Sub "${PJPrefix}-${ECSClusterName}"
    Export:
      Name: !Sub "${PJPrefix}-${ECSClusterName}-name"

#ECSClusterARN
  ECSClusterARN:
    Value: !GetAtt ECSCluster.Arn
    Export:
      Name: !Sub "${PJPrefix}-${ECSClusterName}-arn"

#ECSLogGroup
  ECSLogGroupName:
    Value: !Sub "/ecs/logs/${PJPrefix}-ecs-group"
    Export:
      Name: !Sub "${PJPrefix}-ecs-group-name"

うおおおおおおおおおお
なんかcloudformation理解してきたああああああああああああああ

[AWS CloudFormation] ALB + EC2 1台

AWSTemplateFormatVersion: "2010-09-09"
Description:
  ALB and EC2 Instance Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          default: "InternetALB Configuration"
        Parameters:
          - InternetALBName
      - Label:
          default: "EC2Instance Configuration"
        Parameters:
          - KeyPairName
          - EC2InstanceName
          - EC2InstanceAMI
          - EC2InstanceInstanceType
          - EC2InstanceVolumeType
          - EC2InstanceVolumeSize
          - SSHAccessSourceIP

    ParameterLabels:
      IneternetALBName:
        default: "InternetALBName"
      KeyPairName:
        default: "KeyPiarName"
      EC2InstanceName:
        default: "EC2 Name"
      EC2InstanceAMI:
        default: "EC2 AMI"
      EC2InstanceInstanceType:
        default: "EC2 InstanceType"
      EC2InstanceVolumeType:
        default: "EC2 VolumeType"
      EC2InstanceVolumeSize:
        default: "EC2 VolumeSize"
      SSHAccessSourceIP:
        default: "SSH AccessSourceIP"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String
#InternetALB
  InternetALBName:
    Type: String
    Default: "web"


#EC2Instance
  KeyPairName:
    Type: AWS::EC2::KeyPair::KeyName
    Default: ""
  EC2InstanceName:
    Type: String
    Default: "web"
  EC2InstanceAMI:
    Type: String
    Default: ""
  EC2InstanceInstanceType:
    Type: String
    Default: "t2.micro"
  EC2InstanceVolumeType:
    Type: String
    Default: "gp2"
  EC2InstanceVolumeSize:
    Type: String
    Default: "30"
  SSHAccessSourceIP:
    Type: String

Resources:
# ------------------------------------------------------------#
#  IAM Role for EC2
# ------------------------------------------------------------# 
  EC2IAMRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Sub "${PJPrefix}-${EC2InstanceName}-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - "ec2.amazonaws.com"
            Action:
              - "sts:AssumeRole"

      Path: "/"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
        - "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess"

  EC2InstanceProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Path: "/"
      Roles:
        - Ref: EC2IAMRole
      InstanceProfileName: !Sub "${PJPrefix}-${EC2InstanceName}-profile"

# ------------------------------------------------------------#
#  EC2Instance AZ:A
# ------------------------------------------------------------#
  EC2Instance:
    Type: "AWS::EC2::Instance"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-${EC2InstanceName}-01"
      ImageId: !Ref EC2InstanceAMI
      InstanceType: !Ref EC2InstanceInstanceType
      KeyName: !Ref KeyPairName
      IamInstanceProfile: !Ref EC2InstanceProfile
      DisableApiTermination: false
      EbsOptimized: false
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeType: !Ref EC2InstanceVolumeType
            VolumeSize: !Ref EC2InstanceVolumeSize
      SecurityGroupIds:
        - !Ref ManagedSecurityGroup
        - !Ref WebSecurityGroup
      SubnetId: {"Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a"}
      UserData: !Base64 | 
        #! /bin/bash
        yum update -y


# ------------------------------------------------------------#
#  SecurityGroup for Managed
# ------------------------------------------------------------#
  ManagedSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: {"Fn::ImportValue": !Sub "${PJPrefix}-vpc"}
      GroupName: !Sub "${PJPrefix}-managed-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-managed-sg"

# Rule
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref SSHAccessSourceIP

# ------------------------------------------------------------#
#  SecurityGroup for ALB
# ------------------------------------------------------------#
  ALBSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      GroupName: !Sub "${PJPrefix}-alb-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-alb-sg"

# Rule
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: "0.0.0.0/0"

        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: "0.0.0.0/0"

# ------------------------------------------------------------#
#  SecurityGroup for Web
# ------------------------------------------------------------#
  WebSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      GroupName: !Sub "${PJPrefix}-web-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-web-sg"

# Rule
  WebSecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    Properties:
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      SourceSecurityGroupId: !GetAtt [ ALBSecurityGroup, GroupId ]
      GroupId: !GetAtt [ WebSecurityGroup, GroupId ]

# ------------------------------------------------------------#
#  ElasticIP
# ------------------------------------------------------------# 
  ElasticIP:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: vpc

  ElasticIPAssociate:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt ElasticIP.AllocationId
      InstanceId: !Ref EC2Instance

# ------------------------------------------------------------#
#  Target Group
# ------------------------------------------------------------#
  TargetGroup:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc"}
      Name: !Sub "${PJPrefix}-${InternetALBName}-tg"
      Protocol: HTTP
      Port: 80
      HealthCheckProtocol: HTTP
      HealthCheckPath: "/"
      HealthCheckPort: "traffic-port"
      HealthyThresholdCount: 2
      HealthCheckTimeoutSeconds: 5
      HealthCheckIntervalSeconds: 10
      Matcher:
        HttpCode: 200
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-${InternetALBName}-tg"
      TargetGroupAttributes:
        - Key: "deregistration_delay.timeout_seconds"
          Value: 300
        - Key: "stickiness.enabled"
          Value: false
        - Key: "stickiness.type"
          Value: lb_cookie
        - Key: "stickiness.lb_cookie.duration_seconds"
          Value: 86400
      Targets:
        - Id: !Ref EC2Instance
          Port: 80


# ------------------------------------------------------------#
#  Internet ALB
# ------------------------------------------------------------#
  InternetALB:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties:
      Name: !Sub "${PJPrefix}-${InternetALBName}-alb"
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-${InternetALBName}-alb"
      Scheme: "internet-facing"
      LoadBalancerAttributes:
        - Key: "deletion_protection.enabled"
          Value: false
        - Key: "idle_timeout.timeout_seconds"
          Value: 60
      SecurityGroups:
        - !Ref ALBSecurityGroup
      Subnets:
        - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
        - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }

  ALBListener:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref TargetGroup
          Type: forward
      LoadBalancerArn: !Ref InternetALB
      Port: 80
      Protocol: HTTP

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
#InternetALB
  ALBDNSName:
    Value: !GetAtt InternetALB.DNSName
    Export:
      Name: !Sub "${PJPrefix}-${InternetALBName}-alb-dnsname"

#EC2Instance
  EC2InstanceID:
    Value: !Ref EC2Instance
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-id"

  EC2InstancePrivateIp:
    Value: !GetAtt EC2Instance.PrivateIp
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-private-ip"

  EC2InstanceEIP:
    Value: !GetAtt EC2Instance.PublicIp
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-eip"

  EC2InstanceRoleName:
    Value: !Sub "${PJPrefix}-${EC2InstanceName}-role"
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-role-name"


ALBでEC2 1台で行けるってことは2台でもいけそうやな

[AWS CloudFormation] MySQLのRDSを構築する

AWSTemplateFormatVersion: "2010-09-09"
Description:
  RDS for MySQL Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          default: "RDS Configuration"
        Parameters:
          - DBInstanceName
          - MySQLMajorVersion
          - MySQLMinorVersion
          - DBInstanceClass
          - DBInstanceStorageSize
          - DBInstanceStorageType
          - DBName
          - DBMasterUserName
          - DBPassword
          - MultiAZ

    ParameterLabels:
      DBInstanceName:
        default: "DBInstanceName"
      MySQLMajorVersion:
        default: "MySQLMajorVersion"
      MySQLMinorVersion:
        default: "MySQLMinorVersion"
      DBInstanceClass:
        default: "DBInstanceClass"
      DBInstanceStorageSize:
        default: "DBInstanceStorageSize"
      DBInstanceStorageType:
        default: "DBInstanceStorageType"
      DBName:
        default: "DBName"
      DBMasterUserName:
        default: "DBUserName"
      DBPassword:
        default: "DBPassword"
      MultiAZ:
        default: "MultiAZ"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

  DBInstanceName:
    Type: String
    Default: "rds"
  MySQLMajorVersion:
    Type: String
    Default: "8.0"
    AllowedValues: ["5.7","8.0"]
  MySQLMinorVersion:
    Type: String
    Default: "28"
  DBInstanceClass:
    Type: String
    Default: "db.t3.micro"
  DBInstanceStorageSize:
    Type: String
    Default: "30"
  DBInstanceStorageSize:
    Type: String
    Default: "30"
  DBInstanceStorageType:
    Type: String
    Default: "gp2"
  DBName:
    Type: String
    Default: "db"
  DBMasterUserName:
    Type: String
    Default: "dbuser"
    NoEcho: true
    MinLength: 1
    MaxLength: 16
    AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*"
    ConstraintDescription: "must begin with a letter and contain only alphanumeric characters."
  DBPassword:
    Default: "password"
    NoEcho: true
    Type: String
    MinLength: 8
    MaxLength: 41
    AllowedPattern: "[a-zA-Z0-9]*"
    ConstraintDescription: "must begin with a letter and contain only alphanumeric characters."
  MultiAZ:
    Default: "false"
    Type: String
    AllowedValues: ["true", "false"]

Resources:
# ------------------------------------------------------------#
#  DBInstance MySQL
# ------------------------------------------------------------#
  DBInstance:
    Type: "AWS::RDS::DBInstance"
    Properties:
      DBInstanceIdentifier: !Sub "${PJPrefix}-${DBInstanceName}"
      Engine: MySQL
      EngineVersion: !Sub "${MySQLMajorVersion}.${MySQLMinorVersion}"
      DBInstanceClass: !Ref DBInstanceClass
      AllocatedStorage: !Ref DBInstanceStorageSize
      StorageType: !Ref DBInstanceStorageType
      DBName: !Ref DBName
      MasterUsername: !Ref DBMasterUserName
      MasterUserPassword: !Ref DBPassword
      DBSubnetGroupName: !Ref DBSubnetGroup
      PubliclyAccessible: false
      MultiAZ: !Ref MultiAZ
      PreferredBackupWindow: "18:00-18:30"
      PreferredMaintenanceWindow: "sat:19:00-sat:19:30"
      AutoMinorVersionUpgrade: false
      DBParameterGroupName: !Ref DBParameterGroup
      VPCSecurityGroups:
        - !Ref RDSSecurityGroup
      CopyTagsToSnapshot: true
      BackupRetentionPeriod: 7
      Tags:
        - Key: "Name"
          Value: !Ref DBInstanceName
    DeletionPolicy: "Delete"

# ------------------------------------------------------------#
#  DBParameterGroup
# ------------------------------------------------------------#
  DBParameterGroup:
    Type: "AWS::RDS::DBParameterGroup"
    Properties:
      Family: !Sub "MySQL${MySQLMajorVersion}"
      Description: !Sub "${PJPrefix}-${DBInstanceName}-param"

# ------------------------------------------------------------#
#  SecurityGroup for RDS (MySQL)
# ------------------------------------------------------------#
  RDSSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      GroupName: !Sub "${PJPrefix}-${DBInstanceName}-sg"
      GroupDescription: "-"
      Tags: 
        - Key: "Name"
          Value: !Sub "${PJPrefix}-${DBInstanceName}-sg"
# Rule
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          CidrIp: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc-cidr" }


# ------------------------------------------------------------#
#  DBSubnetGroup
# ------------------------------------------------------------#
  DBSubnetGroup:
    Type: "AWS::RDS::DBSubnetGroup"
    Properties:
      DBSubnetGroupName: !Sub "${PJPrefix}-${DBInstanceName}-subnet"
      DBSubnetGroupDescription: "-"
      SubnetIds:
        - { "Fn::ImportValue": !Sub "${PJPrefix}-private-subnet-a" }
        - { "Fn::ImportValue": !Sub "${PJPrefix}-private-subnet-c" }

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
#DBInstance
  DBInstanceID:
    Value: !Ref DBInstance
    Export:
      Name: !Sub "${PJPrefix}-${DBInstanceName}-id"

  DBInstanceEndpoint:
    Value: !GetAtt DBInstance.Endpoint.Address
    Export:
      Name: !Sub "${PJPrefix}-${DBInstanceName}-endpoint"

  DBName:
    Value: !Ref DBName
    Export:
      Name: !Sub "${PJPrefix}-${DBInstanceName}-dbname"

これはヤバいわ
なかなかやりおる

[AWS CloudFormation] ELB + EC2(1台)を構築する

CloudFormationでEC2だけだったのにELBを追加する。EC2は1台で、subnetは指定
amiはami-07b4f72c4c356c19dを入力

AWSTemplateFormatVersion: "2010-09-09"
Description:
  ELB and EC2 Instance Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          default: "InternetELB Configuration"
        Parameters:
          - InternetELBName
      - Label:
          default: "EC2Instance Configuration"
        Parameters:
          - KeyPairName
          - EC2InstanceName
          - EC2InstanceAMI
          - EC2InstanceInstanceType
          - EC2InstanceVolumeType
          - EC2InstanceVolumeSize
          - SSHAccessSourceIP

    ParameterLabels:
      IneternetELBName:
        default: "InternetELBName"
      KeyPairName:
        default: "KeyPiarName"
      EC2InstanceName:
        default: "EC2 Name"
      EC2InstanceAMI:
        default: "EC2 AMI"
      EC2InstanceInstanceType:
        default: "EC2 InstanceType"
      EC2InstanceVolumeType:
        default: "EC2 VolumeType"
      EC2InstanceVolumeSize:
        default: "EC2 VolumeSize"
      SSHAccessSourceIP:
        default: "SSH AccessSourceIP"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String
#InternetELB
  InternetELBName:
    Type: String
    Default: "web"


#EC2Instance
  KeyPairName:
    Type: AWS::EC2::KeyPair::KeyName
    Default: ""
  EC2InstanceName:
    Type: String
    Default: "ec2-01"
  EC2InstanceAMI:
    Type: String
    Default: ""
  EC2InstanceInstanceType:
    Type: String
    Default: "t2.micro"
  EC2InstanceVolumeType:
    Type: String
    Default: "gp2"
  EC2InstanceVolumeSize:
    Type: String
    Default: "30"
  SSHAccessSourceIP:
    Type: String

Resources:
# ------------------------------------------------------------#
#  IAM Role for EC2
# ------------------------------------------------------------# 
  EC2IAMRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Sub "${PJPrefix}-${EC2InstanceName}-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - "ec2.amazonaws.com"
            Action:
              - "sts:AssumeRole"

      Path: "/"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
        - "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess"

  EC2InstanceProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Path: "/"
      Roles:
        - Ref: EC2IAMRole
      InstanceProfileName: !Sub "${PJPrefix}-${EC2InstanceName}-profile"

# ------------------------------------------------------------#
#  EC2Instance AZ:A
# ------------------------------------------------------------#
  EC2Instance:
    Type: "AWS::EC2::Instance"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-${EC2InstanceName}-01"
      ImageId: !Ref EC2InstanceAMI
      InstanceType: !Ref EC2InstanceInstanceType
      KeyName: !Ref KeyPairName
      IamInstanceProfile: !Ref EC2InstanceProfile
      DisableApiTermination: false
      EbsOptimized: false
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeType: !Ref EC2InstanceVolumeType
            VolumeSize: !Ref EC2InstanceVolumeSize
      SecurityGroupIds:
        - !Ref ManagedSecurityGroup
        - !Ref WebSecurityGroup
      SubnetId: {"Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a"}
      UserData: !Base64 | 
        #! /bin/bash
        yum update -y


# ------------------------------------------------------------#
#  SecurityGroup for Managed
# ------------------------------------------------------------#
  ManagedSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: {"Fn::ImportValue": !Sub "${PJPrefix}-vpc"}
      GroupName: !Sub "${PJPrefix}-managed-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-managed-sg"

# Rule
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref SSHAccessSourceIP

# ------------------------------------------------------------#
#  SecurityGroup for ELB
# ------------------------------------------------------------#
  ELBSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      GroupName: !Sub "${PJPrefix}-elb-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-elb-sg"

# Rule
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: "0.0.0.0/0"

        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: "0.0.0.0/0"

# ------------------------------------------------------------#
#  SecurityGroup for Web
# ------------------------------------------------------------#
  WebSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      GroupName: !Sub "${PJPrefix}-web-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-web-sg"

# Rule
  WebSecurityGroupIngress:
    Type: "AWS::EC2::SecurityGroupIngress"
    Properties:
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      SourceSecurityGroupId: !GetAtt [ ELBSecurityGroup, GroupId ]
      GroupId: !GetAtt [ WebSecurityGroup, GroupId ]

# ------------------------------------------------------------#
#  ElasticIP
# ------------------------------------------------------------# 
  ElasticIP:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: vpc

  ElasticIPAssociate:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt ElasticIP.AllocationId
      InstanceId: !Ref EC2Instance

# ------------------------------------------------------------#
#  InternetELB
# ------------------------------------------------------------#
  InternetELB:
    Type: "AWS::ElasticLoadBalancing::LoadBalancer"
    Properties:
      LoadBalancerName: !Sub "${PJPrefix}-${InternetELBName}-elb"
      Scheme: "internet-facing"
      CrossZone: true
      HealthCheck:
        Target: "TCP:80"
        HealthyThreshold: 2
        UnhealthyThreshold: 2
        Interval: 30
        Timeout: 5
      ConnectionDrainingPolicy:
        Enabled: true
        Timeout: 300
      Listeners:
        - LoadBalancerPort: 80
          InstancePort: 80
          Protocol: HTTP
      Instances:
        - !Ref EC2Instance
      SecurityGroups:
        - !Ref ELBSecurityGroup
      Subnets:
        - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
        - { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
#InternetELB
  ELBDNSName:
    Value: !GetAtt InternetELB.DNSName
    Export:
      Name: !Sub "${PJPrefix}-${InternetELBName}-elb-dnsname"

#EC2Instance
  EC2InstanceID:
    Value: !Ref EC2Instance
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-id"

  EC2InstancePrivateIp:
    Value: !GetAtt EC2Instance.PrivateIp
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-private-ip"

  EC2InstanceEIP:
    Value: !GetAtt EC2Instance.PublicIp
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-eip"

  EC2InstanceRoleName:
    Value: !Sub "${PJPrefix}-${EC2InstanceName}-role"
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-role-name"


SSHログインして動作確認
$ sudo yum install httpd
$ sudo systemctl start httpd
$ sudo systemctl status httpd
$ sudo systemctl enable httpd
$ sudo systemctl is-enabled httpd
$ httpd -v

なるほど、少しずつCloudFormationの威力を理解してきた。

[AWS CloudFormation] EC2を構築する

CloudFormationでEC2を立てる
Security Groupは今の所SSHのみ

AWSTemplateFormatVersion: "2010-09-09"
Description:
  EC2 Instance Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          default: "EC2Instance Configuration"
        Parameters:
          - KeyPairName
          - EC2InstanceName
          - EC2InstanceAMI
          - EC2InstanceInstanceType
          - EC2InstanceVolumeType
          - EC2InstanceVolumeSize
          - EC2InstanceSubnet
          - SSHAccessSourceIP

    ParameterLabels:
      KeyPairName:
        default: "KeyPiarName"
      EC2InstanceName:
        default: "EC2 Name"
      EC2InstanceAMI:
        default: "EC2 AMI"
      EC2InstanceInstanceType:
        default: "EC2 InstanceType"
      EC2InstanceVolumeType:
        default: "EC2 VolumeType"
      EC2InstanceVolumeSize:
        default: "EC2 VolumeSize"
      EC2InstanceSubnet:
        default: "EC2 Subnet"
      SSHAccessSourceIP:
        default: "SSH AccessSourceIP"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

#EC2Instance
  KeyPairName:
    Type: AWS::EC2::KeyPair::KeyName
    Default: ""
  EC2InstanceName:
    Type: String
    Default: "ec2-01"
  EC2InstanceAMI:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
  EC2InstanceInstanceType:
    Type: String
    Default: "t2.micro"
  EC2InstanceVolumeType:
    Type: String
    Default: "gp2"
  EC2InstanceVolumeSize:
    Type: String
    Default: "30"
  EC2InstanceSubnet:
    Type: String
    Default: "public-subnet-a"
    AllowedValues: [ public-subnet-a, public-subnet-c ]
  SSHAccessSourceIP:
    Type: String

Resources:
# ------------------------------------------------------------#
#  IAM Role for EC2
# ------------------------------------------------------------# 
  EC2IAMRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Sub "${PJPrefix}-${EC2InstanceName}-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - "ec2.amazonaws.com"
            Action:
              - "sts:AssumeRole"

      Path: "/"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
        - "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess"

  EC2InstanceProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Path: "/"
      Roles:
        - Ref: EC2IAMRole
      InstanceProfileName: !Sub "${PJPrefix}-${EC2InstanceName}-profile"

# ------------------------------------------------------------#
#  EC2Instance
# ------------------------------------------------------------#
  EC2Instance:
    Type: "AWS::EC2::Instance"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-${EC2InstanceName}"
      ImageId: !Ref EC2InstanceAMI
      InstanceType: !Ref EC2InstanceInstanceType
      KeyName: !Ref KeyPairName
      IamInstanceProfile: !Ref EC2InstanceProfile
      DisableApiTermination: false
      EbsOptimized: false
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeType: !Ref EC2InstanceVolumeType
            VolumeSize: !Ref EC2InstanceVolumeSize
      SecurityGroupIds:
        - !Ref ManagedSecurityGroup
      SubnetId: {"Fn::ImportValue": !Sub "${PJPrefix}-${EC2InstanceSubnet}"}
      UserData: !Base64 | 
        #! /bin/bash
        yum update -y


# ------------------------------------------------------------#
#  SecurityGroup for Managed
# ------------------------------------------------------------#
  ManagedSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: {"Fn::ImportValue": !Sub "${PJPrefix}-vpc"}
      GroupName: !Sub "${PJPrefix}-managed-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-managed-sg"

# Rule
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref SSHAccessSourceIP

# ------------------------------------------------------------#
#  ElasticIP
# ------------------------------------------------------------# 
  ElasticIP:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: vpc

  ElasticIPAssociate:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt ElasticIP.AllocationId
      InstanceId: !Ref EC2Instance

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
#EC2Instance
  EC2InstanceID:
    Value: !Ref EC2Instance
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-id"

  EC2InstancePrivateIp:
    Value: !GetAtt EC2Instance.PrivateIp
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-private-ip"

  EC2InstanceEIP:
    Value: !GetAtt EC2Instance.PublicIp
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-eip"

  EC2InstanceRoleName:
    Value: !Sub "${PJPrefix}-${EC2InstanceName}-role"
    Export:
      Name: !Sub "${PJPrefix}-${EC2InstanceName}-role-name"

うおおおおおおおおおおお
まじか…. CloudFormationでEC2までくると、ど素人は脱出した感がある。

[AWS CloudFormation] VPCフローログ -> CloudWatch

CloudWatchとはAWSで提供されているモニタリングサービス
カスタムメトリクスという機能を利用することで、モニタリングを統合できる

– セットアップ不要で使用できる
– 異常な状態を検知して、自動復旧
– メトリクスに応じてアラート通知やアクションを設定できる
– 監視対象はEC2, EBSなど

### CloudWatchのサービス
「CloudWatch」: CPU, メモリなどを監視。メール、再起動、AutoScaleなどできる
「CloudWatch Logs」: 各種ログ
「CloudWatch Events」: APIイベントをトリガーにアクションを実行

AWSTemplateFormatVersion: "2010-09-09"
Description:
  VPCFlowLogs Settings

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          default: "VPCFlowLogs Configuration (Destination Type is CloudWatchLogs)"
        Parameters:
          - Filter
          - RetentionInDays

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

  Filter:
    Type: String
    Default: ALL
    AllowedValues: [ ALL, ACCEPT, REJECT ]

  RetentionInDays:
    AllowedValues: [ 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653 ]
    Type: Number
    Default: 30

Resources:
# ------------------------------------------------------------#
#  IAM Role for VPCFlowLogs
# ------------------------------------------------------------# 
# VPCFlowLogsIAMRole:
  VPCFlowLogsIAMRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Sub "${PJPrefix}-vpcflowlogs-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - "vpc-flow-logs.amazonaws.com"
            Action:
              - "sts:AssumeRole"

      Policies:
      - PolicyName: !Sub "${PJPrefix}-vpcflowlogs-policy"
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
              - "logs:CreateLogGroup"
              - "logs:CreateLogStream"
              - "logs:PutLogEvents"
              - "logs:DescribeLogGroups"
              - "logs:DescribeLogStreams"
              Resource: "*"

# ------------------------------------------------------------#
#  LogGroup
# ------------------------------------------------------------#
  LogGroup:
    Type: "AWS::Logs::LogGroup"
    Properties:
      LogGroupName: !Sub "${PJPrefix}-vpcflowlogs-group"
      RetentionInDays: !Ref RetentionInDays

# ------------------------------------------------------------#
#  VPCFlowLogs
# ------------------------------------------------------------# 
  VPCFlowLogs:
    Type: "AWS::EC2::FlowLog"
    Properties:
      DeliverLogsPermissionArn: !GetAtt VPCFlowLogsIAMRole.Arn
      LogGroupName: !Ref LogGroup
      ResourceId: { "Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      ResourceType: "VPC"
      TrafficType: !Ref Filter

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
#LogGroup
  LogGroupName:
    Value: !Sub "${PJPrefix}-vpcflowlogs-group"
    Export:
      Name: !Sub "${PJPrefix}-vpcflowlogs-group-name"
  LogGroupARN:
    Value: !GetAtt LogGroup.Arn
    Export:
      Name: !Sub "${PJPrefix}-vpcflowlogs-group-arn"

なるほど、監視はmakerelではなく、cloudwatchを使うのね。

[AWS CloudFormation] VPCフローログ → S3

VPCフローログとは、VPCのネットワークインターフェイスとの間で行き来するIPトラフィックに関する情報をキャプチャできるようにする機能

AWSTemplateFormatVersion: "2010-09-09"
Description:
  VPCFlowLogs Settings (Destination Type is S3)

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix

      - Label:
          default: "VPCFlowLogs Configuration (Destination Type is S3)"
        Parameters:
          - Filter

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

  Filter:
    Type: String
    Default: ALL
    AllowedValues: [ ALL, ACCEPT, REJECT ]

Resources:
# ------------------------------------------------------------#
#  S3 Bucket for VPCFlowLogs
# ------------------------------------------------------------#  
# FlowLogsBucket
  FlowLogsBucket:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName: !Sub "${PJPrefix}-vpcflowlogs" 

# ------------------------------------------------------------#
#  VPCFlowLogs
# ------------------------------------------------------------# 
  VPCFlowLogs:
    Type: "AWS::EC2::FlowLog"
    DependsOn: FlowLogsBucket
    Properties:
      LogDestination: !Sub "arn:aws:s3:::${FlowLogsBucket}"
      LogDestinationType: s3
      ResourceId: {"Fn::ImportValue": !Sub "${PJPrefix}-vpc" }
      ResourceType: "VPC"
      TrafficType: !Ref Filter

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
# FlowLogsBucket
  FlowLogsBucket:
    Value: !Ref FlowLogsBucket
    Export:
      Name: !Sub "${PJPrefix}-vpcflowlogs"

Object can be publicになるのが気になるが、割と簡単に出来る。

[AWS CloudFormation] NatGateway

AWSTemplateFormatVersion: "2010-09-09"
Description:
  NAT Gateway Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix

      - Label:
          default: "NATGateway Configuration"
        Parameters:
          - NATGatewayACreate
          - NATGatewayCCreate

    ParameterLabels:
      NATGatewayACreate:
        default: "NATGatewayACreate"
      NATGatewayACreate:
        default: "NATGatewayCCreate"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

  NATGatewayACreate:
    Default: true
    Type: String
    AllowedValues:
      - true
      - false

  NATGatewayCCreate:
    Default: true
    Type: String
    AllowedValues:
      - true
      - false

# ------------------------------------------------------------#
# Conditions
# ------------------------------------------------------------# 
Conditions:
  IsCreateNATGatewayA: !Equals [ !Ref NATGatewayACreate, true ]
  IsCreateNATGatewayAfalse: !Equals [ !Ref NATGatewayACreate, false ]

  IsCreateNATGatewayC: !Equals [ !Ref NATGatewayCCreate, true ]
  IsCreateNATGatewayCfalse: !Equals [ !Ref NATGatewayCCreate, false ]

# ------------------------------------------------------------#
#  NAT Gateway AZ:A
# ------------------------------------------------------------#
Resources:
# NATGatewayA Create
  NATGatewayA:
    Type: "AWS::EC2::NatGateway"
    Condition: IsCreateNATGatewayA
    Properties:
      AllocationId: !GetAtt NATGatewayAEIP.AllocationId
      SubnetId: { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-a" }
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-natgw-a"

# NATGateway For EIP Create
  NATGatewayAEIP:
    Type: "AWS::EC2::EIP"
    Condition: IsCreateNATGatewayA
    Properties:
      Domain: vpc

# PrivateRouteA Update
  PrivateRouteA:
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayA
    Properties:
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-a"}
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayA

# PrivateRouteC Update (NATGatewayC NO Create)
  PrivateRouteC2:
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayCfalse
    Properties:
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-c"}
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayA  


# ------------------------------------------------------------#
#  NAT Gateway AZ:C
# ------------------------------------------------------------#
# NATGatewayC Create
  NATGatewayC:
    Type: "AWS::EC2::NatGateway"
    Condition: IsCreateNATGatewayC
    Properties:
      AllocationId: !GetAtt NATGatewayCEIP.AllocationId
      SubnetId: { "Fn::ImportValue": !Sub "${PJPrefix}-public-subnet-c" }
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-natgw-c"

# NATGateway For EIP Create
  NATGatewayCEIP:
    Type: "AWS::EC2::EIP"
    Condition: IsCreateNATGatewayC
    Properties:
      Domain: vpc

# PrivateRouteC Update
  PrivateRouteA:
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayC
    Properties:
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-c"}
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayC

# PrivateRouteA Update (NATGatewayA NO Create)
  PrivateRouteA2:
    Type: "AWS::EC2::Route"
    Condition: IsCreateNATGatewayAfalse
    Properties:
      RouteTableId: { "Fn::ImportValue": !Sub "${PJPrefix}-private-route-a"}
      DestinationCidrBlock: "0.0.0.0/0"
      NatGatewayId: !Ref NATGatewayC

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
# NATGateway EIP
  NATGatewayAEIP:
    Condition: IsCreateNATGatewayA
    Value: !Ref NATGatewayAEIP
    Export:
      Name: !Sub "${PJPrefix}-natgw-a-eip"

  NATGatewayCEIP:
    Condition: IsCreateNATGatewayC
    Value: !Ref NATGatewayCEIP
    Export:
      Name: !Sub "${PJPrefix}-natgw-c-eip"

うーん、慣れてる人なら良いが、エラーになるとトラブルシューティングが結構大変
で、エラーの原因が単純なスペルミスだったりする

CloudFormationでVPCを作ろう

### !Ref
Parametersセクションで指定したパラメータの参照
Resourcesセクションで指定したリソースの参照

### !Sub
文字列の一部として使うときは!Sub

vpc-01.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description:
  VPC and Subnet Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          default: "Network Configuration"
        Parameters:
          - VPCCIDR
          - PublicSubnetACIDR
          - PublicSubnetCCIDR
          - PrivateSubnetACIDR
          - PrivateSubnetCCIDR
    ParameterLabels:
      VPCCIDR:
        default: "VPC CIDR"
      PublicSubnetACIDR:
        default: "PublicSubnetA CIDR"
      PublicSubnetCCIDR:
        default: "PublicSubnetC CIDR"
      PrivateSubnetACIDR:
        default: "PrivateSubnetA CIDR"
      PrivateSubnetCCIDR:
        default: "PrivateSubnetC CIDR"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String

  VPCCIDR:
    Type: String
    Default: "10.1.0.0/16"

  PublicSubnetACIDR:
    Type: String
    Default: "10.1.10.0/24"

  PublicSubnetCCIDR:
    Type: String
    Default: "10.1.20.0/24"

  PrivateSubnetACIDR:
    Type: String
    Default: "10.1.100.0/24"

  PrivateSubnetCCIDR:
    Type: String
    Default: "10.1.200.0/24"

Resources:
# ------------------------------------------------------------#
#  VPC
# ------------------------------------------------------------#
# VPC Create
  VPC:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: !Ref VPCCIDR
      EnableDnsSupport: "true"
      EnableDnsHostnames: "true"
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-vpc"

# InternetGateway Create
  InternetGateway:
    Type: "AWS::EC2::InternetGateway"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-igw"

# IGW Attach
  InternetGatewayAttachment:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

# ------------------------------------------------------------#
#  Subnet
# ------------------------------------------------------------#          
# Public SubnetA Create
  PublicSubnetA:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: !Ref PublicSubnetACIDR
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-public-subnet-a"

# Public SubnetC Create
  PublicSubnetC:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1c"
      CidrBlock: !Ref PublicSubnetCCIDR
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-public-subnet-c"

# Private SubnetA Create
  PrivateSubnetA:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: !Ref PrivateSubnetACIDR
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-private-subnet-a"

# Private SubnetC Create
  PrivateSubnetC:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1c"
      CidrBlock: !Ref PrivateSubnetCCIDR
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-private-subnet-c"

# ------------------------------------------------------------#
#  RouteTable
# ------------------------------------------------------------#   
# Public RouteTableA Create
  PublicRouteTableA:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-public-route-a"

# Public RouteTableA Create
  PublicRouteTableC:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-public-route-c"

# Private RouteTableA Create
  PrivateRouteTableA:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-private-route-a"

# Private RouteTableA Create
  PrivateRouteTableC:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-private-route-c"

# ------------------------------------------------------------#
# Routing
# ------------------------------------------------------------# 
# PublicRouteA Create
  PublicRouteA:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PublicRouteTableA
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway

# PublicRouteC Create
  PublicRouteC:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PublicRouteTableC
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway

# ------------------------------------------------------------#
# RouteTable Associate
# ------------------------------------------------------------# 
# PublicRouteTable Associate SubnetA
  PublicSubnetARouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnetA
      RouteTableId: !Ref PublicRouteTableA

# PublicRouteTable Associate SubnetC
  PublicSubnetCRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnetC
      RouteTableId: !Ref PublicRouteTableC

# PrivateRouteTable Associate SubnetA
  PrivateSubnetARouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PrivateSubnetA
      RouteTableId: !Ref PrivateRouteTableA

# PrivateRouteTable Associate SubnetC
  PrivateSubnetCRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PrivateSubnetC
      RouteTableId: !Ref PrivateRouteTableC

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
# VPC
  VPC:
    Value: !Ref VPC
    Export:
      Name: !Sub "${PJPrefix}-vpc"

  VPCCIDR:
    Value: !Ref VPCCIDR
    Export:
      Name: !Sub "${PJPrefix}-vpc-cidr"

# Subnet
  PublicSubnetA:
    Value: !Ref PublicSubnetA
    Export:
      Name: !Sub "${PJPrefix}-public-subnet-a"

  PublicSubnetACIDR:
    Value: !Ref PublicSubnetACIDR
    Export:
      Name: !Sub "${PJPrefix}-public-subnet-a-cidr"

  PublicSubnetC:
    Value: !Ref PublicSubnetC
    Export:
      Name: !Sub "${PJPrefix}-public-subnet-c"

  PublicSubnetCCIDR:
    Value: !Ref PublicSubnetCCIDR
    Export:
      Name: !Sub "${PJPrefix}-public-subnet-c-cidr"

  PrivateSubnetA:
    Value: !Ref PrivateSubnetA
    Export:
      Name: !Sub "${PJPrefix}-private-subnet-a"

  PrivateSubnetACIDR:
    Value: !Ref PrivateSubnetACIDR
    Export:
      Name: !Sub "${PJPrefix}-private-subnet-a-cidr"

  PrivateSubnetC:
    Value: !Ref PrivateSubnetC
    Export:
      Name: !Sub "${PJPrefix}-private-subnet-c"

  PrivateSubnetCCIDR:
    Value: !Ref PrivateSubnetCCIDR
    Export:
      Name: !Sub "${PJPrefix}-private-subnet-c-cidr"


# Route
  PublicRouteTableA:
    Value: !Ref PublicRouteTableA
    Export:
      Name: !Sub "${PJPrefix}-public-route-a"

  PublicRouteTableC:
    Value: !Ref PublicRouteTableC
    Export:
      Name: !Sub "${PJPrefix}-public-route-c"

  PrivateRouteTableA:
    Value: !Ref PrivateRouteTableA
    Export:
      Name: !Sub "${PJPrefix}-priate-route-a"

  PrivateRouteTableC:
    Value: !Ref PrivateRouteTableC
    Export:
      Name: !Sub "${PJPrefix}-priate-route-c"

!Ref, !Subの使い方やcloudformationについて大分理解が進んだ

CloudFormation: SecurityGroup

AWSTemplateFormatVersion: "2010-09-09"
Description: sg-create
Resources:
  SG1:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: "test-create"
      GroupName: "security-group01"
      VpcId: "vpc-xxxxxxxxxxxxx"
      Tags:
        - Key: "Name"
          Value: "secg-01"
      SecurityGroupIngress:
        - IpProtocol:tcp
          FromPort:22
          ToPort:22
          CidrIp: "xxx.xxx.xxx.xxx/xx"

これ、全部やるの??