Description: > This template deploys an ECS cluster to the provided VPC and subnets Parameters: EnvironmentName: Description: An environment name that will be prefixed to resource names Type: String Default: DevOpsGuru InstanceType: Description: Which instance type should we use to build the ECS cluster? Type: String Default: m5zn.large ECSAMI: Description: ECS-Optimized AMI ID Type: AWS::SSM::Parameter::Value Default: /aws/service/ecs/optimized-ami/amazon-linux/recommended/image_id ImageUrl: Type: String Description: The url of the docker image present in ECR Mappings: SubnetConfig: VPC: CIDR: '10.0.0.0/16' PublicOne: CIDR: '10.0.0.0/24' PublicTwo: CIDR: '10.0.1.0/24' Resources: VPC: Type: AWS::EC2::VPC Properties: EnableDnsSupport: true EnableDnsHostnames: true CidrBlock: !FindInMap ['SubnetConfig', 'VPC', 'CIDR'] PublicSubnetOne: Type: AWS::EC2::Subnet Properties: AvailabilityZone: Fn::Select: - 0 - Fn::GetAZs: {Ref: 'AWS::Region'} VpcId: !Ref 'VPC' CidrBlock: !FindInMap ['SubnetConfig', 'PublicOne', 'CIDR'] MapPublicIpOnLaunch: true PublicSubnetTwo: Type: AWS::EC2::Subnet Properties: AvailabilityZone: Fn::Select: - 1 - Fn::GetAZs: {Ref: 'AWS::Region'} VpcId: !Ref 'VPC' CidrBlock: !FindInMap ['SubnetConfig', 'PublicTwo', 'CIDR'] MapPublicIpOnLaunch: true InternetGateway: Type: AWS::EC2::InternetGateway GatewayAttachement: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref 'VPC' InternetGatewayId: !Ref 'InternetGateway' PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' PublicRoute: Type: AWS::EC2::Route DependsOn: GatewayAttachement Properties: RouteTableId: !Ref 'PublicRouteTable' DestinationCidrBlock: '0.0.0.0/0' GatewayId: !Ref 'InternetGateway' PublicSubnetOneRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnetOne RouteTableId: !Ref PublicRouteTable PublicSubnetTwoRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnetTwo RouteTableId: !Ref PublicRouteTable ECSCluster: Type: AWS::ECS::Cluster Properties: ClusterName: !Ref EnvironmentName ClusterSettings: - Name: containerInsights Value: enabled EcsHostSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Access to the ECS hosts that run containers VpcId: !Ref 'VPC' ECSAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: VPCZoneIdentifier: - !Ref PublicSubnetOne - !Ref PublicSubnetTwo LaunchConfigurationName: !Ref 'ContainerInstances' MinSize: 5 MaxSize: 6 DesiredCapacity: 5 CreationPolicy: ResourceSignal: Timeout: PT15M UpdatePolicy: AutoScalingReplacingUpdate: WillReplace: 'true' ContainerInstances: Type: AWS::AutoScaling::LaunchConfiguration Properties: ImageId: !Ref 'ECSAMI' SecurityGroups: [!Ref 'EcsHostSecurityGroup'] InstanceType: !Ref 'InstanceType' IamInstanceProfile: !Ref 'ECSInstanceProfile' UserData: Fn::Base64: !Sub | #!/bin/bash -xe echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config yum install -y aws-cfn-bootstrap yum install -y https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region} AutoscalingRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: [application-autoscaling.amazonaws.com] Action: ['sts:AssumeRole'] Path: / Policies: - PolicyName: service-autoscaling PolicyDocument: Statement: - Effect: Allow Action: - 'application-autoscaling:*' - 'cloudwatch:DescribeAlarms' - 'cloudwatch:PutMetricAlarm' - 'ecs:DescribeServices' - 'ecs:UpdateService' Resource: '*' Service: Type: AWS::ECS::Service Properties: Cluster: !Ref ECSCluster LaunchType: EC2 ServiceName: Test SchedulingStrategy: REPLICA DesiredCount: 2 TaskDefinition: !Ref TaskDefinition PlacementConstraints: - Type: distinctInstance TaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - "EC2" ContainerDefinitions: - Name: blog CPU: 1024 Essential: true Image: !Ref 'ImageUrl' Memory: 128 Environment: - Name: BRICKWALL_HIT_DAYS Value: 5 Name: SPEED_OF_TIME_SECONDS Value: 1 Name: TOTAL_MEMORY_GB Value: 7.5 MemoryReservation: 7372 Memory: 8192 PortMappings: - ContainerPort: 80 HostPort: 80 protocol: tcp - ContainerPort: 8080 HostPort: 8080 protocol: tcp ECSRole: Type: AWS::IAM::Role Properties: Path: / RoleName: !Sub ${EnvironmentName}-ECSRole-${AWS::Region} AssumeRolePolicyDocument: | { "Statement": [{ "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" } }] } ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy Policies: - PolicyName: ecs-service PolicyDocument: | { "Statement": [{ "Effect": "Allow", "Action": [ "ecs:CreateCluster", "ecs:DeregisterContainerInstance", "ecs:DiscoverPollEndpoint", "ecs:Poll", "ecs:RegisterContainerInstance", "ecs:StartTelemetrySession", "ecs:Submit*", "ecr:BatchCheckLayerAvailability", "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer", "ecr:GetAuthorizationToken" ], "Resource": "*" }] } ECSInstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: / Roles: - !Ref ECSRole Outputs: Cluster: Description: A reference to the ECS cluster Value: !Ref ECSCluster