ECSをCloudformationで構築する

## 目的: できるだけ、最小限のコードでECSを作成します。

ECS用のAMI

- https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/retrieve-ecs-optimized_AMI.html

今回はパブリックIPアドレスを付与しない

- EcsInstanceLcで`AssociatePublicIpAddress`を`false`にしています。

ネットワーク周り

- VPCやサブネットは事前に作成されていることを前提とします。


ECS作成用のyamlファイル

```ECS.yaml
---
AWSTemplateFormatVersion: '2010-09-09'
Description: ''
Parameters:
  ECSAMI:
      Description: AMI ID
      Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
      Default: /aws/service/ecs/optimized-ami/amazon-linux/recommended/image_id
  EcsInstanceType:
    Type: String
    Description: EC2 instance type
    Default: 't2.medium'
  AsgMaxSize:
    Type: Number
    Description: Maximum size of ECS Auto Scaling Group
    Default: 1
  VpcId:
    Type: String
    Description: VPC ID for EC2
    Default: '<VPCのID>'
  Subnet1:
    Type: String
    Description: Subnet IDs for VPC
    Default: '<Subnet ID1>'
  Subnet2:
    Type: String
    Description: Subnet IDs for VPC
    Default: '<Subnet ID2>'
Resources:
  # create container registory
  ECR:
    Type: AWS::ECR::Repository
    Properties: 
      RepositoryName: ecs

  # ECS task用のRoleの作成
  TaskRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ecs-tasks.amazonaws.com
            Action:
                - sts:AssumeRole
      ManagedPolicyArns:
        - !Sub arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
      Path: /
      RoleName: { "Fn::Join" : ["-", ["ecs-task", { "Ref" : "AWS::Region" }]] }

  # EC2用のroleの作成
  EC2Role:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: [ec2.amazonaws.com]
          Action: ['sts:AssumeRole']
      Path: /
      Policies:
      - PolicyName: ecs-service
        PolicyDocument:
          Statement:
          - Effect: Allow
            Action:
              - 'ecs:CreateCluster'
              - 'ecs:DeregisterContainerInstance'
              - 'ecs:DiscoverPollEndpoint'
              - 'ecs:Poll'
              - 'ecs:RegisterContainerInstance'
              - 'ecs:StartTelemetrySession'
              - 'ecs:Submit*'
              - 'logs:CreateLogStream'
              - 'logs:PutLogEvents'
              - 'ecr:GetAuthorizationToken'
              - 'ecr:BatchGetImage'
              - 'ecr:GetDownloadUrlForLayer'
            Resource: '*'

  # EC2用のprofileの作成
  EC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles: [!Ref 'EC2Role']
      InstanceProfileName: ec2-profile

  # ECS用のProfileの作成
  ECSInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles: [ !Ref TaskRole ]
      InstanceProfileName: ecs-profile

  # EC2用のセキュリティグループの作成
  SecurityGroupForEc2:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: ecs
      GroupDescription: ECS Allowed Ports
      VpcId: !Ref VpcId
      Tags:
      - Key: Name
        Value: ecs

  # 80ポートを開ける
  SGIngressHttpIpv4:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SecurityGroupForEc2
      Description: '' 
      IpProtocol: tcp
      FromPort: '80'
      ToPort: '80'
      CidrIp: 0.0.0.0/0

  # cloudwatch log
  CloudwatchLogsGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: ecs

  # create ECS Cluster
  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: 'ecs'

  # launch container Instance ECS Instance Launch Config
  EcsInstanceLc:
    Type: AWS::AutoScaling::LaunchConfiguration
    Properties:
      ImageId: !Ref ECSAMI
      SecurityGroups: [ !Ref SecurityGroupForEc2 ]
      InstanceType: !Ref EcsInstanceType
      IamInstanceProfile: !Ref EC2InstanceProfile
      AssociatePublicIpAddress: 'false'
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config

  # create ECS Instance Auto scaling group
  EcsInstanceAsg:
    Type: AWS::AutoScaling::AutoScalingGroup
    DependsOn: SecurityGroupForEc2
    Properties:
      VPCZoneIdentifier: [ !Ref Subnet1, !Ref Subnet2 ]
      LaunchConfigurationName: !Ref EcsInstanceLc
      MinSize: '0'
      MaxSize: !Ref AsgMaxSize
      DesiredCapacity: !Ref AsgMaxSize
      Tags:
      - Key: Name
        Value: 'ecs'
        PropagateAtLaunch: true
    UpdatePolicy:
      AutoScalingReplacingUpdate:
        WillReplace: 'true'
```