1+ AWSTemplateFormatVersion : ' 2010-09-09'
2+ Description : A network stack for deploying containers in AWS ECS.
3+ This stack creates a VPC with two public subnets and a loadbalancer to balance traffic between those subnets.
4+ Derived from a template at https://github.com/nathanpeck/aws-cloudformation-fargate.
5+ Resources :
6+
7+ VPC :
8+ Type : AWS::EC2::VPC
9+ Properties :
10+ CidrBlock : ' 10.0.0.0/16'
11+
12+ PublicSubnetOne :
13+ Type : AWS::EC2::Subnet
14+ Properties :
15+ AvailabilityZone :
16+ Fn::Select :
17+ - 0
18+ - Fn::GetAZs : {Ref: 'AWS::Region'}
19+ VpcId : !Ref 'VPC'
20+ CidrBlock : ' 10.0.1.0/24'
21+ MapPublicIpOnLaunch : true
22+
23+ PublicSubnetTwo :
24+ Type : AWS::EC2::Subnet
25+ Properties :
26+ AvailabilityZone :
27+ Fn::Select :
28+ - 1
29+ - Fn::GetAZs : {Ref: 'AWS::Region'}
30+ VpcId : !Ref 'VPC'
31+ CidrBlock : ' 10.0.2.0/24'
32+ MapPublicIpOnLaunch : true
33+
34+ InternetGateway :
35+ Type : AWS::EC2::InternetGateway
36+
37+ GatewayAttachement :
38+ Type : AWS::EC2::VPCGatewayAttachment
39+ Properties :
40+ VpcId : !Ref 'VPC'
41+ InternetGatewayId : !Ref 'InternetGateway'
42+
43+ PublicRouteTable :
44+ Type : AWS::EC2::RouteTable
45+ Properties :
46+ VpcId : !Ref 'VPC'
47+
48+ PublicSubnetOneRouteTableAssociation :
49+ Type : AWS::EC2::SubnetRouteTableAssociation
50+ Properties :
51+ SubnetId : !Ref PublicSubnetOne
52+ RouteTableId : !Ref PublicRouteTable
53+
54+ PublicSubnetTwoRouteTableAssociation :
55+ Type : AWS::EC2::SubnetRouteTableAssociation
56+ Properties :
57+ SubnetId : !Ref PublicSubnetTwo
58+ RouteTableId : !Ref PublicRouteTable
59+
60+ PublicRoute :
61+ Type : AWS::EC2::Route
62+ DependsOn : GatewayAttachement
63+ Properties :
64+ RouteTableId : !Ref 'PublicRouteTable'
65+ DestinationCidrBlock : ' 0.0.0.0/0'
66+ GatewayId : !Ref 'InternetGateway'
67+
68+ PublicLoadBalancerSecurityGroup :
69+ Type : AWS::EC2::SecurityGroup
70+ Properties :
71+ GroupDescription : Access to the public facing load balancer
72+ VpcId : !Ref 'VPC'
73+ SecurityGroupIngress :
74+ # Allow access to ALB from anywhere on the internet
75+ - CidrIp : 0.0.0.0/0
76+ IpProtocol : -1
77+
78+ PublicLoadBalancer :
79+ Type : AWS::ElasticLoadBalancingV2::LoadBalancer
80+ Properties :
81+ Scheme : internet-facing
82+ Subnets :
83+ # The load balancer is placed into the public subnets, so that traffic
84+ # from the internet can reach the load balancer directly via the internet gateway
85+ - !Ref PublicSubnetOne
86+ - !Ref PublicSubnetTwo
87+ SecurityGroups : [!Ref 'PublicLoadBalancerSecurityGroup']
88+
89+ DummyTargetGroupPublic :
90+ Type : AWS::ElasticLoadBalancingV2::TargetGroup
91+ Properties :
92+ HealthCheckIntervalSeconds : 6
93+ HealthCheckPath : /
94+ HealthCheckProtocol : HTTP
95+ HealthCheckTimeoutSeconds : 5
96+ HealthyThresholdCount : 2
97+ Name : " no-op"
98+ Port : 80
99+ Protocol : HTTP
100+ UnhealthyThresholdCount : 2
101+ VpcId : !Ref 'VPC'
102+
103+ PublicLoadBalancerListener :
104+ Type : AWS::ElasticLoadBalancingV2::Listener
105+ DependsOn :
106+ - PublicLoadBalancer
107+ Properties :
108+ DefaultActions :
109+ - TargetGroupArn : !Ref 'DummyTargetGroupPublic'
110+ Type : ' forward'
111+ LoadBalancerArn : !Ref 'PublicLoadBalancer'
112+ Port : 80
113+ Protocol : HTTP
114+
115+ ECSCluster :
116+ Type : AWS::ECS::Cluster
117+
118+ ECSSecurityGroup :
119+ Type : AWS::EC2::SecurityGroup
120+ Properties :
121+ GroupDescription : Access to the ECS containers
122+ VpcId : !Ref 'VPC'
123+
124+ ECSSecurityGroupIngressFromPublicALB :
125+ Type : AWS::EC2::SecurityGroupIngress
126+ Properties :
127+ Description : Ingress from the public ALB
128+ GroupId : !Ref 'ECSSecurityGroup'
129+ IpProtocol : -1
130+ SourceSecurityGroupId : !Ref 'PublicLoadBalancerSecurityGroup'
131+
132+ ECSSecurityGroupIngressFromSelf :
133+ Type : AWS::EC2::SecurityGroupIngress
134+ Properties :
135+ Description : Ingress from other containers in the same security group
136+ GroupId : !Ref 'ECSSecurityGroup'
137+ IpProtocol : -1
138+ SourceSecurityGroupId : !Ref 'ECSSecurityGroup'
139+
140+ ECSRole :
141+ Type : AWS::IAM::Role
142+ Properties :
143+ AssumeRolePolicyDocument :
144+ Statement :
145+ - Effect : Allow
146+ Principal :
147+ Service : [ecs.amazonaws.com]
148+ Action : ['sts:AssumeRole']
149+ Path : /
150+ Policies :
151+ - PolicyName : ecs-service
152+ PolicyDocument :
153+ Statement :
154+ - Effect : Allow
155+ Action :
156+ # Rules which allow ECS to attach network interfaces to instances
157+ # on your behalf in order for awsvpc networking mode to work right
158+ - ' ec2:AttachNetworkInterface'
159+ - ' ec2:CreateNetworkInterface'
160+ - ' ec2:CreateNetworkInterfacePermission'
161+ - ' ec2:DeleteNetworkInterface'
162+ - ' ec2:DeleteNetworkInterfacePermission'
163+ - ' ec2:Describe*'
164+ - ' ec2:DetachNetworkInterface'
165+
166+ # Rules which allow ECS to update load balancers on your behalf
167+ # with the information sabout how to send traffic to your containers
168+ - ' elasticloadbalancing:DeregisterInstancesFromLoadBalancer'
169+ - ' elasticloadbalancing:DeregisterTargets'
170+ - ' elasticloadbalancing:Describe*'
171+ - ' elasticloadbalancing:RegisterInstancesWithLoadBalancer'
172+ - ' elasticloadbalancing:RegisterTargets'
173+ Resource : ' *'
174+
175+ ECSTaskExecutionRole :
176+ Type : AWS::IAM::Role
177+ Properties :
178+ AssumeRolePolicyDocument :
179+ Statement :
180+ - Effect : Allow
181+ Principal :
182+ Service : [ecs-tasks.amazonaws.com]
183+ Action : ['sts:AssumeRole']
184+ Path : /
185+ Policies :
186+ - PolicyName : AmazonECSTaskExecutionRolePolicy
187+ PolicyDocument :
188+ Statement :
189+ - Effect : Allow
190+ Action :
191+ # Allow the ECS Tasks to download images from ECR
192+ - ' ecr:GetAuthorizationToken'
193+ - ' ecr:BatchCheckLayerAvailability'
194+ - ' ecr:GetDownloadUrlForLayer'
195+ - ' ecr:BatchGetImage'
196+
197+ # Allow the ECS tasks to upload logs to CloudWatch
198+ - ' logs:CreateLogStream'
199+ - ' logs:PutLogEvents'
200+ Resource : ' *'
201+
202+ Outputs :
203+ ClusterName :
204+ Description : The name of the ECS cluster
205+ Value : !Ref 'ECSCluster'
206+ Export :
207+ Name : !Join [ ':', [ !Ref 'AWS::StackName', 'ClusterName' ] ]
208+ ExternalUrl :
209+ Description : The url of the external load balancer
210+ Value : !Join ['', ['http://', !GetAtt 'PublicLoadBalancer.DNSName']]
211+ Export :
212+ Name : !Join [ ':', [ !Ref 'AWS::StackName', 'ExternalUrl' ] ]
213+ ECSRole :
214+ Description : The ARN of the ECS role
215+ Value : !GetAtt 'ECSRole.Arn'
216+ Export :
217+ Name : !Join [ ':', [ !Ref 'AWS::StackName', 'ECSRole' ] ]
218+ ECSTaskExecutionRole :
219+ Description : The ARN of the ECS role
220+ Value : !GetAtt 'ECSTaskExecutionRole.Arn'
221+ Export :
222+ Name : !Join [ ':', [ !Ref 'AWS::StackName', 'ECSTaskExecutionRole' ] ]
223+ PublicListener :
224+ Description : The ARN of the public load balancer's Listener
225+ Value : !Ref PublicLoadBalancerListener
226+ Export :
227+ Name : !Join [ ':', [ !Ref 'AWS::StackName', 'PublicListener' ] ]
228+ VPCId :
229+ Description : The ID of the VPC that this stack is deployed in
230+ Value : !Ref 'VPC'
231+ Export :
232+ Name : !Join [ ':', [ !Ref 'AWS::StackName', 'VPCId' ] ]
233+ PublicSubnetOne :
234+ Description : Public subnet one
235+ Value : !Ref 'PublicSubnetOne'
236+ Export :
237+ Name : !Join [ ':', [ !Ref 'AWS::StackName', 'PublicSubnetOne' ] ]
238+ PublicSubnetTwo :
239+ Description : Public subnet two
240+ Value : !Ref 'PublicSubnetTwo'
241+ Export :
242+ Name : !Join [ ':', [ !Ref 'AWS::StackName', 'PublicSubnetTwo' ] ]
243+ ECSSecurityGroup :
244+ Description : A security group used to allow ECS containers to receive traffic
245+ Value : !Ref 'ECSSecurityGroup'
246+ Export :
247+ Name : !Join [ ':', [ !Ref 'AWS::StackName', 'ECSSecurityGroup' ] ]
0 commit comments