329 lines
12 KiB
YAML
329 lines
12 KiB
YAML
AWSTemplateFormatVersion: '2010-09-09'
|
|
Description: The baseline resources used to create a Fargate environment
|
|
to launch containerized applications in.
|
|
Parameters:
|
|
EnvironmentName:
|
|
Type: String
|
|
Default: production
|
|
Description: A name for the environment that this cloudformation will be part of.
|
|
Mappings:
|
|
# Hard values for the subnet masks. These masks define
|
|
# the range of internal IP addresses that can be assigned.
|
|
# The VPC can have all IP's from 10.0.0.0 to 10.0.255.255
|
|
# There are two subnets which cover the ranges:
|
|
#
|
|
# 10.0.0.0 - 10.0.0.255
|
|
# 10.0.1.0 - 10.0.1.255
|
|
#
|
|
# If you need more IP addresses (perhaps you have so many
|
|
# instances that you run out) then you can customize these
|
|
# ranges to add more
|
|
SubnetConfig:
|
|
VPC:
|
|
CIDR: '10.0.0.0/16'
|
|
PublicOne:
|
|
CIDR: '10.0.0.0/24'
|
|
PublicTwo:
|
|
CIDR: '10.0.1.0/24'
|
|
Resources:
|
|
# VPC in which containers will be networked.
|
|
# It has two public subnets
|
|
# We distribute the subnets across the first two available subnets
|
|
# for the region, for high availability.
|
|
VPC:
|
|
Type: AWS::EC2::VPC
|
|
Properties:
|
|
EnableDnsSupport: true
|
|
EnableDnsHostnames: true
|
|
CidrBlock: !FindInMap ['SubnetConfig', 'VPC', 'CIDR']
|
|
|
|
# Two public subnets, where containers can have public IP addresses
|
|
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
|
|
|
|
# Setup networking resources for the public subnets. Containers
|
|
# in the public subnets have public IP addresses and the routing table
|
|
# sends network traffic via the internet gateway.
|
|
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
|
|
|
|
# ECS Resources
|
|
ECSCluster:
|
|
Type: AWS::ECS::Cluster
|
|
|
|
# A security group for the containers we will run in Fargate.
|
|
# Two rules, allowing network traffic from a public facing load
|
|
# balancer and from other members of the security group.
|
|
#
|
|
# Remove any of the following ingress rules that are not needed.
|
|
# If you want to make direct requests to a container using its
|
|
# public IP address you'll need to add a security group rule
|
|
# to allow traffic from all IP addresses.
|
|
FargateContainerSecurityGroup:
|
|
Type: AWS::EC2::SecurityGroup
|
|
Properties:
|
|
GroupDescription: Access to the Fargate containers
|
|
VpcId: !Ref 'VPC'
|
|
EcsSecurityGroupIngressFromPublicALB:
|
|
Type: AWS::EC2::SecurityGroupIngress
|
|
Properties:
|
|
Description: Ingress from the public ALB
|
|
GroupId: !Ref 'FargateContainerSecurityGroup'
|
|
IpProtocol: -1
|
|
SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG'
|
|
EcsSecurityGroupIngressFromSelf:
|
|
Type: AWS::EC2::SecurityGroupIngress
|
|
Properties:
|
|
Description: Ingress from other containers in the same security group
|
|
GroupId: !Ref 'FargateContainerSecurityGroup'
|
|
IpProtocol: -1
|
|
SourceSecurityGroupId: !Ref 'FargateContainerSecurityGroup'
|
|
|
|
# Load balancers for getting traffic to containers.
|
|
# This sample template creates one load balancer:
|
|
#
|
|
# - One public load balancer, hosted in public subnets that is accessible
|
|
# to the public, and is intended to route traffic to one or more public
|
|
# facing services.
|
|
|
|
# A public facing load balancer, this is used for accepting traffic from the public
|
|
# internet and directing it to public facing microservices
|
|
PublicLoadBalancerSG:
|
|
Type: AWS::EC2::SecurityGroup
|
|
Properties:
|
|
GroupDescription: Access to the public facing load balancer
|
|
VpcId: !Ref 'VPC'
|
|
SecurityGroupIngress:
|
|
# Allow access to ALB from anywhere on the internet
|
|
- CidrIp: 0.0.0.0/0
|
|
IpProtocol: -1
|
|
PublicLoadBalancer:
|
|
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
|
|
Properties:
|
|
Scheme: internet-facing
|
|
LoadBalancerAttributes:
|
|
- Key: idle_timeout.timeout_seconds
|
|
Value: '30'
|
|
Subnets:
|
|
# The load balancer is placed into the public subnets, so that traffic
|
|
# from the internet can reach the load balancer directly via the internet gateway
|
|
- !Ref PublicSubnetOne
|
|
- !Ref PublicSubnetTwo
|
|
SecurityGroups: [!Ref 'PublicLoadBalancerSG']
|
|
# A dummy target group is used to setup the ALB to just drop traffic
|
|
# initially, before any real service target groups have been added.
|
|
DummyTargetGroupPublic:
|
|
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
|
Properties:
|
|
HealthCheckIntervalSeconds: 6
|
|
HealthCheckPath: /
|
|
HealthCheckProtocol: HTTP
|
|
HealthCheckTimeoutSeconds: 5
|
|
HealthyThresholdCount: 2
|
|
Name: !Join ['-', [!Ref 'EnvironmentName', 'drop-1']]
|
|
Port: 80
|
|
Protocol: HTTP
|
|
UnhealthyThresholdCount: 2
|
|
VpcId: !Ref 'VPC'
|
|
PublicLoadBalancerListener:
|
|
Type: AWS::ElasticLoadBalancingV2::Listener
|
|
DependsOn:
|
|
- PublicLoadBalancer
|
|
Properties:
|
|
DefaultActions:
|
|
- TargetGroupArn: !Ref 'DummyTargetGroupPublic'
|
|
Type: 'forward'
|
|
LoadBalancerArn: !Ref 'PublicLoadBalancer'
|
|
Port: 80
|
|
Protocol: HTTP
|
|
|
|
# This is an IAM role which authorizes ECS to manage resources on your
|
|
# account on your behalf, such as updating your load balancer with the
|
|
# details of where your containers are, so that traffic can reach your
|
|
# containers.
|
|
ECSRole:
|
|
Type: AWS::IAM::Role
|
|
Properties:
|
|
AssumeRolePolicyDocument:
|
|
Statement:
|
|
- Effect: Allow
|
|
Principal:
|
|
Service: [ecs.amazonaws.com]
|
|
Action: ['sts:AssumeRole']
|
|
Path: /
|
|
Policies:
|
|
- PolicyName: ecs-service
|
|
PolicyDocument:
|
|
Statement:
|
|
- Effect: Allow
|
|
Action:
|
|
# Rules which allow ECS to attach network interfaces to instances
|
|
# on your behalf in order for awsvpc networking mode to work right
|
|
- 'ec2:AttachNetworkInterface'
|
|
- 'ec2:CreateNetworkInterface'
|
|
- 'ec2:CreateNetworkInterfacePermission'
|
|
- 'ec2:DeleteNetworkInterface'
|
|
- 'ec2:DeleteNetworkInterfacePermission'
|
|
- 'ec2:Describe*'
|
|
- 'ec2:DetachNetworkInterface'
|
|
|
|
# Rules which allow ECS to update load balancers on your behalf
|
|
# with the information sabout how to send traffic to your containers
|
|
- 'elasticloadbalancing:DeregisterInstancesFromLoadBalancer'
|
|
- 'elasticloadbalancing:DeregisterTargets'
|
|
- 'elasticloadbalancing:Describe*'
|
|
- 'elasticloadbalancing:RegisterInstancesWithLoadBalancer'
|
|
- 'elasticloadbalancing:RegisterTargets'
|
|
Resource: '*'
|
|
|
|
# This is a role which is used by the ECS tasks themselves.
|
|
ECSTaskExecutionRole:
|
|
Type: AWS::IAM::Role
|
|
Properties:
|
|
AssumeRolePolicyDocument:
|
|
Statement:
|
|
- Effect: Allow
|
|
Principal:
|
|
Service: [ecs-tasks.amazonaws.com]
|
|
Action: ['sts:AssumeRole']
|
|
Path: /
|
|
Policies:
|
|
- PolicyName: AmazonECSTaskExecutionRolePolicy
|
|
PolicyDocument:
|
|
Statement:
|
|
- Effect: Allow
|
|
Action:
|
|
# Allow the ECS Tasks to download images from ECR
|
|
- 'ecr:GetAuthorizationToken'
|
|
- 'ecr:BatchCheckLayerAvailability'
|
|
- 'ecr:GetDownloadUrlForLayer'
|
|
- 'ecr:BatchGetImage'
|
|
|
|
# Allow the ECS tasks to upload logs to CloudWatch
|
|
- 'logs:CreateLogStream'
|
|
- 'logs:PutLogEvents'
|
|
Resource: '*'
|
|
|
|
# A role used by AWS Autoscaling to get the stats for a Fargate
|
|
# service, and update it to increase or decrease the number of containers
|
|
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: '*'
|
|
|
|
# These are the values output by the CloudFormation template. Be careful
|
|
# about changing any of them, because of them are exported with specific
|
|
# names so that the other task related CF templates can use them.
|
|
Outputs:
|
|
ClusterName:
|
|
Description: The name of the ECS cluster
|
|
Value: !Ref 'ECSCluster'
|
|
Export:
|
|
Name: !Join [ ':', [ !Ref 'EnvironmentName', 'ClusterName' ] ]
|
|
ExternalUrl:
|
|
Description: The url of the external load balancer
|
|
Value: !Join ['', ['http://', !GetAtt 'PublicLoadBalancer.DNSName']]
|
|
Export:
|
|
Name: !Join [ ':', [ !Ref 'EnvironmentName', 'ExternalUrl' ] ]
|
|
ECSRole:
|
|
Description: The ARN of the ECS role
|
|
Value: !GetAtt 'ECSRole.Arn'
|
|
Export:
|
|
Name: !Join [ ':', [ !Ref 'EnvironmentName', 'ECSRole' ] ]
|
|
ECSTaskExecutionRole:
|
|
Description: The ARN of the ECS role
|
|
Value: !GetAtt 'ECSTaskExecutionRole.Arn'
|
|
Export:
|
|
Name: !Join [ ':', [ !Ref 'EnvironmentName', 'ECSTaskExecutionRole' ] ]
|
|
AutoscalingRole:
|
|
Description: The ARN of the ECS role
|
|
Value: !GetAtt 'ECSTaskExecutionRole.Arn'
|
|
Export:
|
|
Name: !Join [ ':', [ !Ref 'EnvironmentName', 'AutoscalingRole' ] ]
|
|
PublicListener:
|
|
Description: The ARN of the public load balancer's Listener
|
|
Value: !Ref PublicLoadBalancerListener
|
|
Export:
|
|
Name: !Join [ ':', [ !Ref 'EnvironmentName', 'PublicListener' ] ]
|
|
VPCId:
|
|
Description: The ID of the VPC that this stack is deployed in
|
|
Value: !Ref 'VPC'
|
|
Export:
|
|
Name: !Join [ ':', [ !Ref 'EnvironmentName', 'VPCId' ] ]
|
|
PublicSubnetOne:
|
|
Description: Public subnet one
|
|
Value: !Ref 'PublicSubnetOne'
|
|
Export:
|
|
Name: !Join [ ':', [ !Ref 'EnvironmentName', 'PublicSubnetOne' ] ]
|
|
PublicSubnetTwo:
|
|
Description: Public subnet two
|
|
Value: !Ref 'PublicSubnetTwo'
|
|
Export:
|
|
Name: !Join [ ':', [ !Ref 'EnvironmentName', 'PublicSubnetTwo' ] ]
|
|
FargateContainerSecurityGroup:
|
|
Description: A security group used to allow Fargate containers to receive traffic
|
|
Value: !Ref 'FargateContainerSecurityGroup'
|
|
Export:
|
|
Name: !Join [ ':', [ !Ref 'EnvironmentName', 'FargateContainerSecurityGroup' ] ]
|