AWSTemplateFormatVersion: 2010-09-09 Description: Creating ECS service Mappings: AWSRegionToAMI: ap-south-1: AMI: ami-00491f6f eu-west-3: AMI: ami-9aef59e7 eu-west-2: AMI: ami-67cbd003 eu-west-1: AMI: ami-1d46df64 ap-northeast-2: AMI: ami-c212b2ac ap-northeast-1: AMI: ami-872c4ae1 sa-east-1: AMI: ami-af521fc3 ca-central-1: AMI: ami-435bde27 ap-southeast-1: AMI: ami-910d72ed ap-southeast-2: AMI: ami-58bb443a eu-central-1: AMI: ami-509a053f us-east-1: AMI: ami-28456852 us-east-2: AMI: ami-ce1c36ab us-west-1: AMI: ami-74262414 us-west-2: AMI: ami-decc7fa6 Resources: VPC: Type: 'AWS::EC2::VPC' Properties: CidrBlock: 10.0.0.0/24 PrivateSubnet1: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC CidrBlock: 10.0.0.0/26 AvailabilityZone: Fn::Select: - 0 - Fn::GetAZs: "" PrivateSubnet2: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC CidrBlock: 10.0.0.64/26 AvailabilityZone: Fn::Select: - 1 - Fn::GetAZs: "" PublicSubnet1: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC MapPublicIpOnLaunch: true CidrBlock: 10.0.0.128/26 AvailabilityZone: Fn::Select: - 0 - Fn::GetAZs: "" PublicSubnet2: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC MapPublicIpOnLaunch: true CidrBlock: 10.0.0.192/26 AvailabilityZone: Fn::Select: - 1 - Fn::GetAZs: "" InternetGateway: Type: 'AWS::EC2::InternetGateway' GatewayAttachment: Type: 'AWS::EC2::VPCGatewayAttachment' Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref VPC RouteIGW: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway NAT1: Type: AWS::EC2::NatGateway Properties: AllocationId: Fn::GetAtt: - EIP1 - AllocationId SubnetId: !Ref PublicSubnet1 EIP1: Type: AWS::EC2::EIP Properties: Domain: vpc Route1: Type: AWS::EC2::Route Properties: RouteTableId: Ref: PrivateRouteTable1 DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: Ref: NAT1 NAT2: Type: AWS::EC2::NatGateway Properties: AllocationId: Fn::GetAtt: - EIP2 - AllocationId SubnetId: !Ref PublicSubnet2 EIP2: Type: AWS::EC2::EIP Properties: Domain: vpc Route2: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable2 DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NAT2 PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC PrivateRouteTable1: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC PrivateRouteTable2: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC RouteTableAssociation1: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1 RouteTableId: !Ref PublicRouteTable RouteTableAssociation2: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet2 RouteTableId: !Ref PublicRouteTable RouteTableAssociation3: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet1 RouteTableId: !Ref PrivateRouteTable1 RouteTableAssociation4: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet2 RouteTableId: !Ref PrivateRouteTable2 ECSCluster: Type: AWS::ECS::Cluster ALBPublic: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: internet-facing SecurityGroups: - !GetAtt SecurityGroupPublic.GroupId Subnets: - !Ref PublicSubnet1 - !Ref PublicSubnet2 ALBPrivate: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: internal SecurityGroups: - !GetAtt SecurityGroupWebapp.GroupId Subnets: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 SecurityGroupPublic: Type: AWS::EC2::SecurityGroup Properties: GroupName: ALBPublic GroupDescription: AllowWebTraffic VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 SecurityGroupWebapp: Type: AWS::EC2::SecurityGroup Properties: GroupName: WebAppSecurityGroup GroupDescription: WebAppSecurityGroupRules VpcId: !Ref VPC IngressRuleWebapp: Type: AWS::EC2::SecurityGroupIngress Properties: IpProtocol: tcp FromPort: 8080 ToPort: 8080 SourceSecurityGroupId: !GetAtt SecurityGroupPublic.GroupId GroupId: !GetAtt SecurityGroupWebapp.GroupId IngressRuleWebapp001: Type: AWS::EC2::SecurityGroupIngress Properties: IpProtocol: tcp FromPort: 8081 ToPort: 8082 SourceSecurityGroupId: !GetAtt SecurityGroupWebapp.GroupId GroupId: !GetAtt SecurityGroupWebapp.GroupId PublicECSHostSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: VpcId: !Ref VPC GroupDescription: Access to the ECS hosts and the tasks/containers that run on them SecurityGroupIngress: # Only allow inbound access to ECS from the ELB - SourceSecurityGroupId: !Ref SecurityGroupPublic IpProtocol: -1 PrivateECSHostSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: VpcId: !Ref VPC GroupDescription: Access to the ECS hosts and the tasks/containers that run on them SecurityGroupIngress: # Only allow inbound access to ECS from the ELB - SourceSecurityGroupId: !Ref SecurityGroupWebapp IpProtocol: -1 ECSRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: ec2.amazonaws.com ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: / Roles: - !Ref ECSRole PrivateAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: VPCZoneIdentifier: [!Ref 'PrivateSubnet1'] LaunchConfigurationName: !Ref PrivateLaunchConfiguration MinSize: 1 MaxSize: 1 DesiredCapacity: 1 Tags: - Key: Name Value: !Sub ${AWS::StackName} - ECS Host PropagateAtLaunch: true CreationPolicy: ResourceSignal: Timeout: PT15M UpdatePolicy: AutoScalingRollingUpdate: MinInstancesInService: 1 MaxBatchSize: 1 PauseTime: PT15M WaitOnResourceSignals: true PrivateLaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Metadata: AWS::CloudFormation::Init: config: commands: 01_add_instance_to_cluster: command: !Sub echo ECS_CLUSTER=${ECSCluster} > /etc/ecs/ecs.config files: "/etc/cfn/cfn-hup.conf": mode: 000400 owner: root group: root content: !Sub | [main] stack=${AWS::StackId} region=${AWS::Region} "/etc/cfn/hooks.d/cfn-auto-reloader.conf": content: !Sub | [cfn-auto-reloader-hook] triggers=post.update path=Resources.ContainerInstances.Metadata.AWS::CloudFormation::Init action=/opt/aws/bin/cfn-init -v --region ${AWS::Region} --stack ${AWS::StackName} --resource LaunchConfiguration services: sysvinit: cfn-hup: enabled: true ensureRunning: true files: - /etc/cfn/cfn-hup.conf - /etc/cfn/hooks.d/cfn-auto-reloader.conf Properties: ImageId: !FindInMap [ AWSRegionToAMI, !Ref "AWS::Region", AMI ] InstanceType: m4.large IamInstanceProfile: !Ref InstanceProfile SecurityGroups: - !Ref PrivateECSHostSecurityGroup UserData: "Fn::Base64": !Sub | #!/bin/bash yum install -y aws-cfn-bootstrap /opt/aws/bin/cfn-init -v --region ${AWS::Region} --stack ${AWS::StackName} --resource PrivateLaunchConfiguration /opt/aws/bin/cfn-signal -e $? --region ${AWS::Region} --stack ${AWS::StackName} --resource PrivateAutoScalingGroup PublicAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: VPCZoneIdentifier: [!Ref 'PublicSubnet1'] LaunchConfigurationName: !Ref PublicLaunchConfiguration MinSize: 1 MaxSize: 1 DesiredCapacity: 1 Tags: - Key: Name Value: !Sub ${AWS::StackName} - ECS Host PropagateAtLaunch: true CreationPolicy: ResourceSignal: Timeout: PT15M UpdatePolicy: AutoScalingRollingUpdate: MinInstancesInService: 1 MaxBatchSize: 1 PauseTime: PT15M WaitOnResourceSignals: true PublicLaunchConfiguration: Type: AWS::AutoScaling::LaunchConfiguration Metadata: AWS::CloudFormation::Init: config: commands: 01_add_instance_to_cluster: command: !Sub echo ECS_CLUSTER=${ECSCluster} > /etc/ecs/ecs.config files: "/etc/cfn/cfn-hup.conf": mode: 000400 owner: root group: root content: !Sub | [main] stack=${AWS::StackId} region=${AWS::Region} "/etc/cfn/hooks.d/cfn-auto-reloader.conf": content: !Sub | [cfn-auto-reloader-hook] triggers=post.update path=Resources.ContainerInstances.Metadata.AWS::CloudFormation::Init action=/opt/aws/bin/cfn-init -v --region ${AWS::Region} --stack ${AWS::StackName} --resource LaunchConfiguration services: sysvinit: cfn-hup: enabled: true ensureRunning: true files: - /etc/cfn/cfn-hup.conf - /etc/cfn/hooks.d/cfn-auto-reloader.conf Properties: ImageId: !FindInMap [ AWSRegionToAMI, !Ref "AWS::Region", AMI ] InstanceType: m4.xlarge IamInstanceProfile: !Ref InstanceProfile SecurityGroups: - !Ref PublicECSHostSecurityGroup UserData: "Fn::Base64": !Sub | #!/bin/bash yum install -y aws-cfn-bootstrap /opt/aws/bin/cfn-init -v --region ${AWS::Region} --stack ${AWS::StackName} --resource PublicLaunchConfiguration /opt/aws/bin/cfn-signal -e $? --region ${AWS::Region} --stack ${AWS::StackName} --resource PublicAutoScalingGroup Outputs: ECSCluster: Value: !Ref ECSCluster VPC: Value: !Ref VPC PrivateSubnet1: Value: !Ref PrivateSubnet1 PrivateSubnet2: Value: !Ref PrivateSubnet2 PublicSubnet1: Value: !Ref PublicSubnet1 PublicSubnet2: Value: !Ref PublicSubnet2 ALBPublic: Value: !Ref ALBPublic ALBPrivate: Value: !Ref ALBPrivate ALBPublicCNAME: Value: !GetAtt ALBPublic.DNSName ALBPrivateCNAME: Value: !GetAtt ALBPrivate.DNSName SecurityGroupWebapp: Value: !GetAtt SecurityGroupWebapp.GroupId PrivateECSHostSecurityGroup: Value: !Ref PrivateECSHostSecurityGroup PublicECSHostSecurityGroup: Value: !Ref PrivateECSHostSecurityGroup