Created
January 8, 2018 17:43
-
-
Save sunds/ddf4047bbc4f67281261054c1c306105 to your computer and use it in GitHub Desktop.
AWS Fargate ECS cloudformation templete
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Sample CloudFormation template for AWS Fargate. | |
# | |
# This template builds a new VPC with two public subnets plus an internet gateway and associated security groups. | |
# It adds an application load balancer with SSL using a certificate of your specification (Use AWS certificate manager to issue) | |
# It then configures an ECS service running a docker image. This example used the AWS ECS sample application (a small PHP app). | |
# You would replace that one with yours. | |
# | |
# Before you start: | |
# | |
# 1) Have ECR (AWS container registry) created and have your image loaded there. | |
# 2) Optionally have a certificate generated for your site and its ARN ready | |
# 3) Determine the CIDR and subnets you'd like to use for your new VPC. | |
# | |
# Example: | |
# aws cloudformation deploy --stack-name mystack | |
# --template-file templates/environment.yaml | |
# --parameter-overrides Name=dev-vpc VpcCIDR=10.20.0.0/16 Subnet1CIDR=10.20.1.0/24 Subnet2CIDR=10.20.2.0/24 Certificate=arn:aws:acm:us-east-1:AWSACCOUNT:certificate/UUID | |
# --capabilities CAPABILITY_IAM | |
# | |
Description: > | |
A complete environment using AWS ECS Fargate | |
A VPC with two public subnets, internet gateway, and application load balancer | |
Parameters: | |
Name: | |
Type: String | |
VpcCIDR: | |
Type: String | |
Subnet1CIDR: | |
Type: String | |
Subnet2CIDR: | |
Type: String | |
Repository: | |
Type: String | |
Default: my-service | |
InstanceCount: | |
Type: Number | |
Default: 1 | |
Certificate: | |
Type: String | |
Resources: | |
VPC: | |
Type: AWS::EC2::VPC | |
Properties: | |
CidrBlock: !Ref VpcCIDR | |
Tags: | |
- Key: Name | |
Value: !Ref Name | |
InternetGateway: | |
Type: AWS::EC2::InternetGateway | |
Properties: | |
Tags: | |
- Key: Name | |
Value: !Ref Name | |
InternetGatewayAttachment: | |
Type: AWS::EC2::VPCGatewayAttachment | |
Properties: | |
InternetGatewayId: !Ref InternetGateway | |
VpcId: !Ref VPC | |
Subnet1: | |
Type: AWS::EC2::Subnet | |
Properties: | |
VpcId: !Ref VPC | |
AvailabilityZone: !Select [ 0, !GetAZs ] | |
MapPublicIpOnLaunch: true | |
CidrBlock: !Ref Subnet1CIDR | |
Tags: | |
- Key: Name | |
Value: !Sub ${Name} (Public) | |
Subnet2: | |
Type: AWS::EC2::Subnet | |
Properties: | |
VpcId: !Ref VPC | |
AvailabilityZone: !Select [ 1, !GetAZs ] | |
MapPublicIpOnLaunch: true | |
CidrBlock: !Ref Subnet2CIDR | |
Tags: | |
- Key: Name | |
Value: !Sub ${Name} (Public) | |
RouteTable: | |
Type: AWS::EC2::RouteTable | |
Properties: | |
VpcId: !Ref VPC | |
Tags: | |
- Key: Name | |
Value: !Ref Name | |
DefaultRoute: | |
Type: AWS::EC2::Route | |
Properties: | |
RouteTableId: !Ref RouteTable | |
DestinationCidrBlock: 0.0.0.0/0 | |
GatewayId: !Ref InternetGateway | |
Subnet1RouteTableAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
Properties: | |
RouteTableId: !Ref RouteTable | |
SubnetId: !Ref Subnet1 | |
Subnet2RouteTableAssociation: | |
Type: AWS::EC2::SubnetRouteTableAssociation | |
Properties: | |
RouteTableId: !Ref RouteTable | |
SubnetId: !Ref Subnet2 | |
VPCSecurityGroup: | |
Type: "AWS::EC2::SecurityGroup" | |
Properties: | |
GroupDescription: !Sub ${AWS::StackName}-ingress | |
SecurityGroupIngress: | |
- CidrIp: "0.0.0.0/0" | |
IpProtocol: "TCP" | |
FromPort: 443 | |
ToPort: 443 | |
- CidrIp: "0.0.0.0/0" | |
IpProtocol: "TCP" | |
FromPort: 80 | |
ToPort: 80 | |
VpcId: !Ref VPC | |
LoadBalancer: | |
Type: AWS::ElasticLoadBalancingV2::LoadBalancer | |
Properties: | |
Name: !Ref Name | |
Subnets: | |
- !Ref Subnet1 | |
- !Ref Subnet2 | |
SecurityGroups: | |
- !Ref VPCSecurityGroup | |
LoadBalancerListener: | |
Type: AWS::ElasticLoadBalancingV2::Listener | |
Properties: | |
LoadBalancerArn: !Ref LoadBalancer | |
Port: 443 | |
Protocol: HTTPS | |
DefaultActions: | |
- Type: forward | |
TargetGroupArn: !Ref TargetGroup | |
Certificates: | |
- CertificateArn: !Ref Certificate | |
SslPolicy: ELBSecurityPolicy-TLS-1-2-2017-01 | |
Cluster: | |
Type: AWS::ECS::Cluster | |
Properties: | |
ClusterName: !Ref AWS::StackName | |
TargetGroup: | |
Type: AWS::ElasticLoadBalancingV2::TargetGroup | |
Properties: | |
VpcId: !Ref VPC | |
TargetType: ip | |
Port: 80 | |
Protocol: HTTP | |
TargetGroupAttributes: | |
- Key: deregistration_delay.timeout_seconds | |
Value: 30 | |
Tags: | |
- Key: Image | |
Value: latest | |
- Key: Name | |
Value: !Ref Name | |
ListenerRule: | |
Type: AWS::ElasticLoadBalancingV2::ListenerRule | |
Properties: | |
Actions: | |
- Type: forward | |
TargetGroupArn: !Ref TargetGroup | |
Conditions: | |
- Field: path-pattern | |
Values: | |
- "*" | |
ListenerArn: !Ref LoadBalancerListener | |
Priority: 1 | |
TaskIamRole: | |
Type: AWS::IAM::Role | |
Properties: | |
Path: / | |
AssumeRolePolicyDocument: | | |
{ | |
"Statement": [{ | |
"Effect": "Allow", | |
"Principal": { "Service": [ "ecs-tasks.amazonaws.com" ]}, | |
"Action": [ "sts:AssumeRole" ] | |
}] | |
} | |
ManagedPolicyArns: | |
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy | |
ECSSecurityGroup: | |
Type: AWS::EC2::SecurityGroup | |
Properties: | |
GroupDescription: !Sub ${AWS::StackName} | |
SecurityGroupIngress: | |
- SourceSecurityGroupId: !Ref VPCSecurityGroup | |
IpProtocol: -1 | |
VpcId: !Ref VPC | |
Service: | |
Type: AWS::ECS::Service | |
DependsOn: | |
- LoadBalancerListener | |
Properties: | |
Cluster: !Ref Cluster | |
DesiredCount: !Ref InstanceCount | |
LaunchType: FARGATE | |
TaskDefinition: !Ref TaskDefinition | |
DeploymentConfiguration: | |
MinimumHealthyPercent: 0 | |
LoadBalancers: | |
- ContainerName: !Ref Repository | |
ContainerPort: 80 | |
TargetGroupArn: !Ref TargetGroup | |
NetworkConfiguration: | |
AwsvpcConfiguration: | |
AssignPublicIp: ENABLED | |
SecurityGroups: | |
- !GetAtt ECSSecurityGroup.GroupId | |
Subnets: | |
- !Ref Subnet1 | |
- !Ref Subnet2 | |
TaskDefinition: | |
Type: AWS::ECS::TaskDefinition | |
Properties: | |
Cpu: 256 | |
Memory: 512 | |
NetworkMode: awsvpc | |
RequiresCompatibilities: | |
- FARGATE | |
ExecutionRoleArn: !GetAtt TaskIamRole.Arn | |
TaskRoleArn: !GetAtt TaskIamRole.Arn | |
ContainerDefinitions: | |
- Name: !Ref Repository | |
Image: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${Repository}:latest | |
EntryPoint: | |
- /usr/sbin/apache2 | |
- -D | |
- FOREGROUND | |
Essential: true | |
Memory: 512 | |
PortMappings: | |
- ContainerPort: 80 | |
Environment: | |
- Name: Tag | |
Value: latest | |
LogConfiguration: | |
LogDriver: awslogs | |
Options: | |
awslogs-group: !Ref LogGroup | |
awslogs-region: us-east-1 | |
awslogs-stream-prefix: !Sub ${AWS::StackName} | |
LogGroup: | |
Type: AWS::Logs::LogGroup | |
Properties: | |
LogGroupName: !Sub ${AWS::StackName} | |
RetentionInDays: 30 | |
Outputs: | |
Subnet1: | |
Value: !Ref Subnet1 | |
Subnet2: | |
Value: !Ref Subnet2 | |
VpcId: | |
Value: !Ref VPC | |
ServiceUrl: | |
Description: URL of the load balancer for the sample service. | |
Value: !Sub http://${LoadBalancer.DNSName} | |
SecurityGroup: | |
Value: !Ref VPCSecurityGroup | |
LoadBalancerArn: | |
Value: !Ref LoadBalancer |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note that AssignPublicIp must be ENABLED in this configuration. Internet gateways only perform 1-to-1 NAT. Any container wanting to reach the internet must have a public IP assigned in order for the return traffic to be routable. Security groups prevent general access to the containers.
An alternative would be to set up public and provide subnets with AWS NAT instances if your deployment needs this complexity.