Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
093b9b27a6 | ||
|
8c6ee60e36 | ||
|
f97fa7a455 | ||
|
a9206d7479 | ||
|
4422db5072 | ||
|
5967945d58 | ||
|
c58432972c | ||
|
6a638b4d6a | ||
|
96f8ef8be8 | ||
|
e95b14892f | ||
|
c7e6b9d252 | ||
|
f3f350409c | ||
|
b3ee2880d9 |
571
aws-ecs-ec2/cluster.yaml
Normal file
571
aws-ecs-ec2/cluster.yaml
Normal file
@@ -0,0 +1,571 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Description: A stack for deploying containerized applications onto a cluster of EC2
|
||||
hosts using Elastic Container Service. This stack runs containers on
|
||||
hosts that are in a private VPC subnet. Outbound network traffic from the
|
||||
hosts must go out through a NAT gateway. There are two load balancers, one
|
||||
inside the public subnet, which can be used to send traffic to the
|
||||
containers in the private subnet, and one in the private subnet, which can
|
||||
be used for private internal traffic between internal services.
|
||||
Parameters:
|
||||
DesiredCapacity:
|
||||
Type: Number
|
||||
Default: '3'
|
||||
Description: Number of EC2 instances to launch in your ECS cluster.
|
||||
MaxSize:
|
||||
Type: Number
|
||||
Default: '6'
|
||||
Description: Maximum number of EC2 instances that can be launched in your ECS cluster.
|
||||
ECSAMI:
|
||||
Description: AMI ID
|
||||
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
|
||||
Default: /aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id
|
||||
InstanceType:
|
||||
Description: EC2 instance type
|
||||
Type: String
|
||||
Default: c4.xlarge
|
||||
AllowedValues: [t2.micro, t2.small, t2.medium, t2.large, m3.medium, m3.large,
|
||||
m3.xlarge, m3.2xlarge, m4.large, m4.xlarge, m4.2xlarge, m4.4xlarge, m4.10xlarge,
|
||||
c4.large, c4.xlarge, c4.2xlarge, c4.4xlarge, c4.8xlarge, c3.large, c3.xlarge,
|
||||
c3.2xlarge, c3.4xlarge, c3.8xlarge, r3.large, r3.xlarge, r3.2xlarge, r3.4xlarge,
|
||||
r3.8xlarge, i2.xlarge, i2.2xlarge, i2.4xlarge, i2.8xlarge]
|
||||
ConstraintDescription: Please choose a valid instance type.
|
||||
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 four subnets which cover the ranges:
|
||||
#
|
||||
# 10.0.0.0 - 10.0.0.255
|
||||
# 10.0.1.0 - 10.0.1.255
|
||||
# 10.0.2.0 - 10.0.2.255
|
||||
# 10.0.3.0 - 10.0.3.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'
|
||||
PrivateOne:
|
||||
CIDR: '10.0.2.0/24'
|
||||
PrivateTwo:
|
||||
CIDR: '10.0.3.0/24'
|
||||
Resources:
|
||||
# VPC in which containers will be networked.
|
||||
# It has two public subnets, and two private 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
|
||||
|
||||
# Two private subnets where containers will only have private
|
||||
# IP addresses, and will only be reachable by other members of the
|
||||
# VPC
|
||||
PrivateSubnetOne:
|
||||
Type: AWS::EC2::Subnet
|
||||
Properties:
|
||||
AvailabilityZone:
|
||||
Fn::Select:
|
||||
- 0
|
||||
- Fn::GetAZs: {Ref: 'AWS::Region'}
|
||||
VpcId: !Ref 'VPC'
|
||||
CidrBlock: !FindInMap ['SubnetConfig', 'PrivateOne', 'CIDR']
|
||||
PrivateSubnetTwo:
|
||||
Type: AWS::EC2::Subnet
|
||||
Properties:
|
||||
AvailabilityZone:
|
||||
Fn::Select:
|
||||
- 1
|
||||
- Fn::GetAZs: {Ref: 'AWS::Region'}
|
||||
VpcId: !Ref 'VPC'
|
||||
CidrBlock: !FindInMap ['SubnetConfig', 'PrivateTwo', 'CIDR']
|
||||
|
||||
# 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
|
||||
|
||||
# Setup networking resources for the private subnets. Containers
|
||||
# in these subnets have only private IP addresses, and must use a NAT
|
||||
# gateway to talk to the internet. We launch two NAT gateways, one for
|
||||
# each private subnet.
|
||||
NatGatewayOneAttachment:
|
||||
Type: AWS::EC2::EIP
|
||||
DependsOn: GatewayAttachement
|
||||
Properties:
|
||||
Domain: vpc
|
||||
NatGatewayTwoAttachment:
|
||||
Type: AWS::EC2::EIP
|
||||
DependsOn: GatewayAttachement
|
||||
Properties:
|
||||
Domain: vpc
|
||||
NatGatewayOne:
|
||||
Type: AWS::EC2::NatGateway
|
||||
Properties:
|
||||
AllocationId: !GetAtt NatGatewayOneAttachment.AllocationId
|
||||
SubnetId: !Ref PublicSubnetOne
|
||||
NatGatewayTwo:
|
||||
Type: AWS::EC2::NatGateway
|
||||
Properties:
|
||||
AllocationId: !GetAtt NatGatewayTwoAttachment.AllocationId
|
||||
SubnetId: !Ref PublicSubnetTwo
|
||||
PrivateRouteTableOne:
|
||||
Type: AWS::EC2::RouteTable
|
||||
Properties:
|
||||
VpcId: !Ref 'VPC'
|
||||
PrivateRouteOne:
|
||||
Type: AWS::EC2::Route
|
||||
Properties:
|
||||
RouteTableId: !Ref PrivateRouteTableOne
|
||||
DestinationCidrBlock: 0.0.0.0/0
|
||||
NatGatewayId: !Ref NatGatewayOne
|
||||
PrivateRouteTableOneAssociation:
|
||||
Type: AWS::EC2::SubnetRouteTableAssociation
|
||||
Properties:
|
||||
RouteTableId: !Ref PrivateRouteTableOne
|
||||
SubnetId: !Ref PrivateSubnetOne
|
||||
PrivateRouteTableTwo:
|
||||
Type: AWS::EC2::RouteTable
|
||||
Properties:
|
||||
VpcId: !Ref 'VPC'
|
||||
PrivateRouteTwo:
|
||||
Type: AWS::EC2::Route
|
||||
Properties:
|
||||
RouteTableId: !Ref PrivateRouteTableTwo
|
||||
DestinationCidrBlock: 0.0.0.0/0
|
||||
NatGatewayId: !Ref NatGatewayTwo
|
||||
PrivateRouteTableTwoAssociation:
|
||||
Type: AWS::EC2::SubnetRouteTableAssociation
|
||||
Properties:
|
||||
RouteTableId: !Ref PrivateRouteTableTwo
|
||||
SubnetId: !Ref PrivateSubnetTwo
|
||||
|
||||
# OPTIONAL: VPC Endpoint for DynamoDB
|
||||
# If a container needs to access DynamoDB this allows a container in the private subnet
|
||||
# to talk to DynamoDB directly without needing to go via the NAT gateway. This reduces
|
||||
# the amount of bandwidth through the gateway, meaning that the gateway is free to serve
|
||||
# your other traffic.
|
||||
DynamoDBEndpoint:
|
||||
Type: AWS::EC2::VPCEndpoint
|
||||
Properties:
|
||||
PolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action: "*"
|
||||
Principal: "*"
|
||||
Resource: "*"
|
||||
RouteTableIds:
|
||||
- !Ref 'PrivateRouteTableOne'
|
||||
- !Ref 'PrivateRouteTableTwo'
|
||||
ServiceName: !Join [ "", [ "com.amazonaws.", { "Ref": "AWS::Region" }, ".dynamodb" ] ]
|
||||
VpcId: !Ref 'VPC'
|
||||
|
||||
# ECS Resources
|
||||
ECSCluster:
|
||||
Type: AWS::ECS::Cluster
|
||||
|
||||
# A security group for the EC2 hosts that will run the containers.
|
||||
# Two rules, allowing network traffic from a public facing load
|
||||
# balancer and from other hosts in 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.
|
||||
EcsHostSecurityGroup:
|
||||
Type: AWS::EC2::SecurityGroup
|
||||
Properties:
|
||||
GroupDescription: Access to the ECS hosts that run containers
|
||||
VpcId: !Ref 'VPC'
|
||||
EcsSecurityGroupIngressFromPublicALB:
|
||||
Type: AWS::EC2::SecurityGroupIngress
|
||||
Properties:
|
||||
Description: Ingress from the public ALB
|
||||
GroupId: !Ref 'EcsHostSecurityGroup'
|
||||
IpProtocol: -1
|
||||
SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG'
|
||||
EcsSecurityGroupIngressFromPrivateALB:
|
||||
Type: AWS::EC2::SecurityGroupIngress
|
||||
Properties:
|
||||
Description: Ingress from the private ALB
|
||||
GroupId: !Ref 'EcsHostSecurityGroup'
|
||||
IpProtocol: -1
|
||||
SourceSecurityGroupId: !Ref 'PrivateLoadBalancerSG'
|
||||
EcsSecurityGroupIngressFromSelf:
|
||||
Type: AWS::EC2::SecurityGroupIngress
|
||||
Properties:
|
||||
Description: Ingress from other containers in the same security group
|
||||
GroupId: !Ref 'EcsHostSecurityGroup'
|
||||
IpProtocol: -1
|
||||
SourceSecurityGroupId: !Ref 'EcsHostSecurityGroup'
|
||||
|
||||
# Autoscaling group. This launches the actual EC2 instances that will register
|
||||
# themselves as members of the cluster, and run the docker containers.
|
||||
ECSAutoScalingGroup:
|
||||
Type: AWS::AutoScaling::AutoScalingGroup
|
||||
Properties:
|
||||
VPCZoneIdentifier:
|
||||
- !Ref PrivateSubnetOne
|
||||
- !Ref PrivateSubnetTwo
|
||||
LaunchConfigurationName: !Ref 'ContainerInstances'
|
||||
MinSize: '1'
|
||||
MaxSize: !Ref 'MaxSize'
|
||||
DesiredCapacity: !Ref 'DesiredCapacity'
|
||||
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 'EC2InstanceProfile'
|
||||
UserData:
|
||||
Fn::Base64: !Sub |
|
||||
#!/bin/bash -xe
|
||||
echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
|
||||
yum install -y aws-cfn-bootstrap curl
|
||||
/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: '*'
|
||||
EC2InstanceProfile:
|
||||
Type: AWS::IAM::InstanceProfile
|
||||
Properties:
|
||||
Path: /
|
||||
Roles: [!Ref 'EC2Role']
|
||||
|
||||
# Role for the EC2 hosts. This allows the ECS agent on the EC2 hosts
|
||||
# to communciate with the ECS control plane, as well as download the docker
|
||||
# images from ECR to run on your host.
|
||||
EC2Role:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
AssumeRolePolicyDocument:
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Service: [ec2.amazonaws.com]
|
||||
Action: ['sts:AssumeRole']
|
||||
Path: /
|
||||
Policies:
|
||||
- PolicyName: ecs-service
|
||||
PolicyDocument:
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- 'ecs:CreateCluster'
|
||||
- 'ecs:DeregisterContainerInstance'
|
||||
- 'ecs:DiscoverPollEndpoint'
|
||||
- 'ecs:Poll'
|
||||
- 'ecs:RegisterContainerInstance'
|
||||
- 'ecs:StartTelemetrySession'
|
||||
- 'ecs:Submit*'
|
||||
- 'logs:CreateLogStream'
|
||||
- 'logs:PutLogEvents'
|
||||
- 'ecr:GetAuthorizationToken'
|
||||
- 'ecr:BatchGetImage'
|
||||
- 'ecr:GetDownloadUrlForLayer'
|
||||
Resource: '*'
|
||||
|
||||
# Load balancers for getting traffic to containers.
|
||||
# This sample template creates two load balancers:
|
||||
#
|
||||
# - 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.
|
||||
# - One private load balancer, hosted in private subnets, that only
|
||||
# accepts traffic from other containers in the cluster, and is
|
||||
# intended for private services that should not be accessed directly
|
||||
# by the public.
|
||||
|
||||
# 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 'AWS::StackName', '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
|
||||
|
||||
# An internal load balancer, this would be used for a service that is not
|
||||
# directly accessible to the public, but instead should only receive traffic
|
||||
# from your other services.
|
||||
PrivateLoadBalancerSG:
|
||||
Type: AWS::EC2::SecurityGroup
|
||||
Properties:
|
||||
GroupDescription: Access to the internal load balancer
|
||||
VpcId: !Ref 'VPC'
|
||||
PrivateLoadBalancerIngressFromECS:
|
||||
Type: AWS::EC2::SecurityGroupIngress
|
||||
Properties:
|
||||
Description: Only accept traffic from a container in the container host security group
|
||||
GroupId: !Ref 'PrivateLoadBalancerSG'
|
||||
IpProtocol: -1
|
||||
SourceSecurityGroupId: !Ref 'EcsHostSecurityGroup'
|
||||
PrivateLoadBalancer:
|
||||
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
|
||||
Properties:
|
||||
Scheme: internal
|
||||
LoadBalancerAttributes:
|
||||
- Key: idle_timeout.timeout_seconds
|
||||
Value: '30'
|
||||
Subnets:
|
||||
# This load balancer is put into the private subnet, so that there is no
|
||||
# route for the public to even be able to access the private load balancer.
|
||||
- !Ref PrivateSubnetOne
|
||||
- !Ref PrivateSubnetTwo
|
||||
SecurityGroups: [!Ref 'PrivateLoadBalancerSG']
|
||||
# This dummy target group is used to setup the ALB to just drop traffic
|
||||
# initially, before any real service target groups have been added.
|
||||
DummyTargetGroupPrivate:
|
||||
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
||||
Properties:
|
||||
HealthCheckIntervalSeconds: 6
|
||||
HealthCheckPath: /
|
||||
HealthCheckProtocol: HTTP
|
||||
HealthCheckTimeoutSeconds: 5
|
||||
HealthyThresholdCount: 2
|
||||
Name: !Join ['-', [!Ref 'AWS::StackName', 'drop-2']]
|
||||
Port: 80
|
||||
Protocol: HTTP
|
||||
UnhealthyThresholdCount: 2
|
||||
VpcId: !Ref 'VPC'
|
||||
PrivateLoadBalancerListener:
|
||||
Type: AWS::ElasticLoadBalancingV2::Listener
|
||||
DependsOn:
|
||||
- PrivateLoadBalancer
|
||||
Properties:
|
||||
DefaultActions:
|
||||
- TargetGroupArn: !Ref 'DummyTargetGroupPrivate'
|
||||
Type: 'forward'
|
||||
LoadBalancerArn: !Ref 'PrivateLoadBalancer'
|
||||
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: '*'
|
||||
|
||||
# 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 'AWS::StackName', 'ClusterName' ] ]
|
||||
InternalUrl:
|
||||
Description: The url of the internal load balancer
|
||||
Value: !Join ['', ['http://', !GetAtt 'PrivateLoadBalancer.DNSName']]
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'InternalUrl' ] ]
|
||||
ExternalUrl:
|
||||
Description: The url of the external load balancer
|
||||
Value: !Join ['', ['http://', !GetAtt 'PublicLoadBalancer.DNSName']]
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ExternalUrl' ] ]
|
||||
ECSRole:
|
||||
Description: The ARN of the ECS role
|
||||
Value: !GetAtt 'ECSRole.Arn'
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ECSRole' ] ]
|
||||
PublicListener:
|
||||
Description: The ARN of the public load balancer's Listener
|
||||
Value: !Ref PublicLoadBalancerListener
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicListener' ] ]
|
||||
PrivateListener:
|
||||
Description: The ARN of the public load balancer's Listener
|
||||
Value: !Ref PrivateLoadBalancerListener
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PrivateListener' ] ]
|
||||
VPCId:
|
||||
Description: The ID of the VPC that this stack is deployed in
|
||||
Value: !Ref 'VPC'
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'VPCId' ] ]
|
||||
PublicSubnetOne:
|
||||
Description: Public subnet one
|
||||
Value: !Ref 'PublicSubnetOne'
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicSubnetOne' ] ]
|
||||
PublicSubnetTwo:
|
||||
Description: Public subnet two
|
||||
Value: !Ref 'PublicSubnetTwo'
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicSubnetTwo' ] ]
|
||||
PrivateSubnetOne:
|
||||
Description: Private subnet one
|
||||
Value: !Ref 'PrivateSubnetOne'
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PrivateSubnetOne' ] ]
|
||||
PrivateSubnetTwo:
|
||||
Description: Private subnet two
|
||||
Value: !Ref 'PrivateSubnetTwo'
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PrivateSubnetTwo' ] ]
|
||||
EcsHostSecurityGroup:
|
||||
Description: A security group used to allow containers to receive traffic
|
||||
Value: !Ref 'EcsHostSecurityGroup'
|
||||
Export:
|
||||
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'EcsHostSecurityGroup' ] ]
|
120
aws-ecs-ec2/services-agent.yaml
Normal file
120
aws-ecs-ec2/services-agent.yaml
Normal file
@@ -0,0 +1,120 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Description: Deploy the instana agent on ECS as a daemon service
|
||||
Parameters:
|
||||
StackName:
|
||||
Type: String
|
||||
Default: production
|
||||
Description: The name of the parent cluster stack that you created. Necessary
|
||||
to locate and reference resources created by that stack.
|
||||
ServiceName:
|
||||
Type: String
|
||||
Default: instana-agent
|
||||
Description: A name for the service
|
||||
ImageUrl:
|
||||
Type: String
|
||||
Default: instana/agent
|
||||
Description: The url of a docker image that contains the application process that
|
||||
will handle the traffic for this service
|
||||
ContainerCpu:
|
||||
Type: Number
|
||||
Default: 1024
|
||||
Description: How much CPU to give the container. 1024 is 1 CPU
|
||||
ContainerMemory:
|
||||
Type: Number
|
||||
Default: 2048
|
||||
Description: How much memory in megabytes to give the container
|
||||
Role:
|
||||
Type: String
|
||||
Default: ""
|
||||
Description: (Optional) An IAM role to give the service's containers if the code within needs to
|
||||
access other AWS resources like S3 buckets, DynamoDB tables, etc
|
||||
InstanaAgentKey:
|
||||
Type: String
|
||||
InstanaAgentEndpoint:
|
||||
Type: String
|
||||
Default: "ingress-red-saas.instana.io"
|
||||
InstanaAgentEndpointPort:
|
||||
Type: Number
|
||||
Default: '443'
|
||||
|
||||
Conditions:
|
||||
HasCustomRole: !Not [ !Equals [!Ref 'Role', ''] ]
|
||||
|
||||
Resources:
|
||||
|
||||
# The task definition. This is a simple metadata description of what
|
||||
# container to run, and what resource requirements it has.
|
||||
TaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
Properties:
|
||||
Family: !Ref 'ServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
NetworkMode: host
|
||||
IpcMode: host
|
||||
PidMode: host
|
||||
Volumes:
|
||||
- Host:
|
||||
SourcePath: "/var/run"
|
||||
Name: "host-var-run"
|
||||
- Host:
|
||||
SourcePath: "/run"
|
||||
Name: "host-run"
|
||||
- Host:
|
||||
SourcePath: "/dev"
|
||||
Name: "host-dev"
|
||||
- Host:
|
||||
SourcePath: "/sys"
|
||||
Name: "host-sys"
|
||||
- Host:
|
||||
SourcePath: "/var/log"
|
||||
Name: "host-var-log"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'ServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: !Ref 'ImageUrl'
|
||||
Privileged: true
|
||||
MountPoints:
|
||||
- ContainerPath: /var/run
|
||||
SourceVolume: "host-var-run"
|
||||
ReadOnly: false
|
||||
- ContainerPath: /run
|
||||
SourceVolume: "host-run"
|
||||
ReadOnly: false
|
||||
- ContainerPath: /dev
|
||||
SourceVolume: "host-dev"
|
||||
ReadOnly: false
|
||||
- ContainerPath: /sys
|
||||
SourceVolume: "host-sys"
|
||||
ReadOnly: false
|
||||
- ContainerPath: /var/log
|
||||
SourceVolume: "host-var-log"
|
||||
ReadOnly: false
|
||||
Environment:
|
||||
- Name: INSTANA_ZONE
|
||||
Value: !Ref 'StackName'
|
||||
- Name: INSTANA_AGENT_ENDPOINT
|
||||
Value: !Ref 'InstanaAgentEndpoint'
|
||||
- Name: INSTANA_AGENT_ENDPOINT_PORT
|
||||
Value: !Ref 'InstanaAgentEndpointPort'
|
||||
- Name: INSTANA_AGENT_KEY
|
||||
Value: !Ref 'InstanaAgentKey'
|
||||
|
||||
# The service. The service is a resource which allows you to run multiple
|
||||
# copies of a type of task, and gather up their logs and metrics, as well
|
||||
# as monitor the number of running tasks and replace any that have crashed
|
||||
Service:
|
||||
Type: AWS::ECS::Service
|
||||
Properties:
|
||||
ServiceName: !Ref 'ServiceName'
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
TaskDefinition: !Ref 'TaskDefinition'
|
||||
SchedulingStrategy: DAEMON
|
752
aws-ecs-ec2/services.yaml
Normal file
752
aws-ecs-ec2/services.yaml
Normal file
@@ -0,0 +1,752 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Description: Deploy robot shop services to a given ECS cluster
|
||||
Parameters:
|
||||
StackName:
|
||||
Type: String
|
||||
Default: ecs-ec2-robotshop
|
||||
Description: The name of the parent cluster stack that you created. Necessary
|
||||
to locate and reference resources created by that stack.
|
||||
WebServiceName:
|
||||
Type: String
|
||||
Default: web
|
||||
Description: The web service name
|
||||
MongoDbServiceName:
|
||||
Type: String
|
||||
Default: mongodb
|
||||
Description: The mongodb service name
|
||||
RedisServiceName:
|
||||
Type: String
|
||||
Default: redis
|
||||
Description: The redis service name
|
||||
RabbitMqServiceName:
|
||||
Type: String
|
||||
Default: rabbitmq
|
||||
Description: The rabbitmq service name
|
||||
CatalogueServiceName:
|
||||
Type: String
|
||||
Default: catalogue
|
||||
Description: The catalogue service name
|
||||
UserServiceName:
|
||||
Type: String
|
||||
Default: user
|
||||
Description: The user service name
|
||||
CartServiceName:
|
||||
Type: String
|
||||
Default: cart
|
||||
Description: The cart service name
|
||||
MySqlServiceName:
|
||||
Type: String
|
||||
Default: mysql
|
||||
Description: The cart service name
|
||||
ShippingServiceName:
|
||||
Type: String
|
||||
Default: shipping
|
||||
Description: The cart service name
|
||||
RatingsServiceName:
|
||||
Type: String
|
||||
Default: ratings
|
||||
Description: The cart service name
|
||||
PaymentServiceName:
|
||||
Type: String
|
||||
Default: payment
|
||||
Description: The payment service name
|
||||
DispatchServiceName:
|
||||
Type: String
|
||||
Default: dispatch
|
||||
Description: The payment service name
|
||||
ImageUrl:
|
||||
Type: String
|
||||
Default: nginx
|
||||
Description: The url of a docker image that contains the application process that
|
||||
will handle the traffic for this service
|
||||
WebContainerPort:
|
||||
Type: Number
|
||||
Default: 8080
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
MongoDbContainerPort:
|
||||
Type: Number
|
||||
Default: 27017
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
RedisContainerPort:
|
||||
Type: Number
|
||||
Default: 6379
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
RabbitMqContainerPort:
|
||||
Type: Number
|
||||
Default: 5672
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
CatalogueContainerPort:
|
||||
Type: Number
|
||||
Default: 8080
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
UserContainerPort:
|
||||
Type: Number
|
||||
Default: 8080
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
CartContainerPort:
|
||||
Type: Number
|
||||
Default: 8080
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
MySqlContainerPort:
|
||||
Type: Number
|
||||
Default: 3306
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
ShippingContainerPort:
|
||||
Type: Number
|
||||
Default: 8080
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
RatingsContainerPort:
|
||||
Type: Number
|
||||
Default: 80
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
PaymentContainerPort:
|
||||
Type: Number
|
||||
Default: 8080
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
DispatchContainerPort:
|
||||
Type: Number
|
||||
Default: 8080
|
||||
Description: What port number the application inside the docker container is binding to
|
||||
ContainerCpu:
|
||||
Type: Number
|
||||
Default: 256
|
||||
Description: How much CPU to give the container. 1024 is 1 CPU
|
||||
ContainerMemory:
|
||||
Type: Number
|
||||
Default: 512
|
||||
Description: How much memory in megabytes to give the container
|
||||
Path:
|
||||
Type: String
|
||||
Default: "*"
|
||||
Description: A path on the public load balancer that this service
|
||||
should be connected to. Use * to send all load balancer
|
||||
traffic to this service.
|
||||
Priority:
|
||||
Type: Number
|
||||
Default: 1
|
||||
Description: The priority for the routing rule added to the load balancer.
|
||||
This only applies if your have multiple services which have been
|
||||
assigned to different paths on the load balancer.
|
||||
DesiredCount:
|
||||
Type: Number
|
||||
Default: 2
|
||||
Description: How many copies of the service task to run
|
||||
Role:
|
||||
Type: String
|
||||
Default: ""
|
||||
Description: (Optional) An IAM role to give the service's containers if the code within needs to
|
||||
access other AWS resources like S3 buckets, DynamoDB tables, etc
|
||||
WebLogGroup:
|
||||
Type: String
|
||||
Default: "rs-web"
|
||||
|
||||
Conditions:
|
||||
HasCustomRole: !Not [ !Equals [!Ref 'Role', ''] ]
|
||||
|
||||
Resources:
|
||||
Registry:
|
||||
Type: AWS::ServiceDiscovery::PrivateDnsNamespace
|
||||
Properties:
|
||||
Description: RobotShop registry for ecs
|
||||
Name: robot-shop
|
||||
Vpc:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'VPCId']]
|
||||
|
||||
# MongoDB service
|
||||
MongoDbTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
Properties:
|
||||
Family: !Ref 'MongoDbServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'MongoDbServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: robotshop/rs-mongodb:0.4.17
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'MongoDbContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
MongoDbService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: LoadBalancerRule
|
||||
Properties:
|
||||
ServiceName: !Ref 'MongoDbServiceName'
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'MongoDbTaskDefinition'
|
||||
|
||||
# Redis service
|
||||
RedisTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
Properties:
|
||||
Family: !Ref 'RedisServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'RedisServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: redis:4.0.6
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'RedisContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
RedisService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: LoadBalancerRule
|
||||
Properties:
|
||||
ServiceName: !Ref 'RedisServiceName'
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'RedisTaskDefinition'
|
||||
|
||||
# rabbitmq service
|
||||
RabbitMqTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
Properties:
|
||||
Family: !Ref 'RabbitMqServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'RabbitMqServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: rabbitmq:3.7-management-alpine
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'RabbitMqContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
RabbitMqService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: LoadBalancerRule
|
||||
Properties:
|
||||
ServiceName: !Ref 'RabbitMqServiceName'
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'RabbitMqTaskDefinition'
|
||||
|
||||
# catalogue service
|
||||
CatalogueTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
DependsOn: ['MongoDbService']
|
||||
Properties:
|
||||
Family: !Ref 'CatalogueServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
NetworkMode: awsvpc
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'CatalogueServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: robotshop/rs-catalogue:0.4.17
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'CatalogueContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
CatalogueService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: [LoadBalancerRule, CatalogueRegistryService]
|
||||
Properties:
|
||||
ServiceName: !Ref 'CatalogueServiceName'
|
||||
NetworkConfiguration:
|
||||
AwsvpcConfiguration:
|
||||
Subnets:
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetOne']]
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetTwo']]
|
||||
ServiceRegistries:
|
||||
- ContainerName: !Ref 'CatalogueServiceName'
|
||||
ContainerPort: !Ref 'CatalogueContainerPort'
|
||||
RegistryArn: !GetAtt CatalogueRegistryService.Arn
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'CatalogueTaskDefinition'
|
||||
CatalogueRegistryService:
|
||||
Type: AWS::ServiceDiscovery::Service
|
||||
DependsOn: Registry
|
||||
Properties:
|
||||
Name: !Ref 'CatalogueServiceName'
|
||||
DnsConfig:
|
||||
NamespaceId: !GetAtt Registry.Id
|
||||
DnsRecords:
|
||||
- TTL: 10
|
||||
Type: SRV
|
||||
- TTL: 10
|
||||
Type: A
|
||||
RoutingPolicy: WEIGHTED
|
||||
|
||||
# user service
|
||||
UserTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
DependsOn: ['MongoDbService', 'RedisService']
|
||||
Properties:
|
||||
Family: !Ref 'UserServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
NetworkMode: awsvpc
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'UserServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: robotshop/rs-user:0.4.17
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'UserContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
UserService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: [LoadBalancerRule, UserRegistryService]
|
||||
Properties:
|
||||
ServiceName: !Ref 'UserServiceName'
|
||||
NetworkConfiguration:
|
||||
AwsvpcConfiguration:
|
||||
Subnets:
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetOne']]
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetTwo']]
|
||||
ServiceRegistries:
|
||||
- ContainerName: !Ref 'UserServiceName'
|
||||
ContainerPort: !Ref 'UserContainerPort'
|
||||
RegistryArn: !GetAtt UserRegistryService.Arn
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'UserTaskDefinition'
|
||||
UserRegistryService:
|
||||
Type: AWS::ServiceDiscovery::Service
|
||||
DependsOn: Registry
|
||||
Properties:
|
||||
Name: !Ref 'UserServiceName'
|
||||
DnsConfig:
|
||||
NamespaceId: !GetAtt Registry.Id
|
||||
DnsRecords:
|
||||
- TTL: 10
|
||||
Type: SRV
|
||||
- TTL: 10
|
||||
Type: A
|
||||
RoutingPolicy: WEIGHTED
|
||||
|
||||
# cart service
|
||||
CartTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
DependsOn: ['RedisService']
|
||||
Properties:
|
||||
Family: !Ref 'CartServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
NetworkMode: awsvpc
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'CartServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: robotshop/rs-cart:0.4.17
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'CartContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
CartService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: [LoadBalancerRule, CartRegistryService]
|
||||
Properties:
|
||||
ServiceName: !Ref 'CartServiceName'
|
||||
NetworkConfiguration:
|
||||
AwsvpcConfiguration:
|
||||
Subnets:
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetOne']]
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetTwo']]
|
||||
ServiceRegistries:
|
||||
- ContainerName: !Ref 'CartServiceName'
|
||||
ContainerPort: !Ref 'CartContainerPort'
|
||||
RegistryArn: !GetAtt CartRegistryService.Arn
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'CartTaskDefinition'
|
||||
CartRegistryService:
|
||||
Type: AWS::ServiceDiscovery::Service
|
||||
DependsOn: Registry
|
||||
Properties:
|
||||
Name: !Ref 'CartServiceName'
|
||||
DnsConfig:
|
||||
NamespaceId: !GetAtt Registry.Id
|
||||
DnsRecords:
|
||||
- TTL: 10
|
||||
Type: SRV
|
||||
- TTL: 10
|
||||
Type: A
|
||||
RoutingPolicy: WEIGHTED
|
||||
|
||||
# mysql service
|
||||
MySqlTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
Properties:
|
||||
Family: !Ref 'MySqlServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'MySqlServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
LinuxParameters:
|
||||
Capabilities:
|
||||
Add:
|
||||
- NET_ADMIN
|
||||
Image: robotshop/rs-mysql-db:0.4.17
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'MySqlContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
MySqlService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: LoadBalancerRule
|
||||
Properties:
|
||||
ServiceName: !Ref 'MySqlServiceName'
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'MySqlTaskDefinition'
|
||||
|
||||
# shipping service
|
||||
ShippingTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
DependsOn: ['MySqlService']
|
||||
Properties:
|
||||
Family: !Ref 'ShippingServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
NetworkMode: awsvpc
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'ShippingServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: robotshop/rs-shipping:0.4.17
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'ShippingContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
ShippingService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: [LoadBalancerRule, ShippingRegistryService]
|
||||
Properties:
|
||||
ServiceName: !Ref 'ShippingServiceName'
|
||||
NetworkConfiguration:
|
||||
AwsvpcConfiguration:
|
||||
Subnets:
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetOne']]
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetTwo']]
|
||||
ServiceRegistries:
|
||||
- ContainerName: !Ref 'ShippingServiceName'
|
||||
ContainerPort: !Ref 'ShippingContainerPort'
|
||||
RegistryArn: !GetAtt ShippingRegistryService.Arn
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'ShippingTaskDefinition'
|
||||
ShippingRegistryService:
|
||||
Type: AWS::ServiceDiscovery::Service
|
||||
DependsOn: Registry
|
||||
Properties:
|
||||
Name: !Ref 'ShippingServiceName'
|
||||
DnsConfig:
|
||||
NamespaceId: !GetAtt Registry.Id
|
||||
DnsRecords:
|
||||
- TTL: 10
|
||||
Type: SRV
|
||||
- TTL: 10
|
||||
Type: A
|
||||
RoutingPolicy: WEIGHTED
|
||||
|
||||
# ratings service
|
||||
RatingsTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
DependsOn: ['MySqlService']
|
||||
Properties:
|
||||
Family: !Ref 'RatingsServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
NetworkMode: awsvpc
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'RatingsServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: robotshop/rs-ratings:0.4.17
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'RatingsContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
RatingsService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: [LoadBalancerRule, RatingsRegistryService]
|
||||
Properties:
|
||||
ServiceName: !Ref 'RatingsServiceName'
|
||||
NetworkConfiguration:
|
||||
AwsvpcConfiguration:
|
||||
Subnets:
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetOne']]
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetTwo']]
|
||||
ServiceRegistries:
|
||||
- ContainerName: !Ref 'RatingsServiceName'
|
||||
ContainerPort: !Ref 'RatingsContainerPort'
|
||||
RegistryArn: !GetAtt RatingsRegistryService.Arn
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'RatingsTaskDefinition'
|
||||
RatingsRegistryService:
|
||||
Type: AWS::ServiceDiscovery::Service
|
||||
DependsOn: Registry
|
||||
Properties:
|
||||
Name: !Ref 'RatingsServiceName'
|
||||
DnsConfig:
|
||||
NamespaceId: !GetAtt Registry.Id
|
||||
DnsRecords:
|
||||
- TTL: 10
|
||||
Type: SRV
|
||||
- TTL: 10
|
||||
Type: A
|
||||
RoutingPolicy: WEIGHTED
|
||||
|
||||
# payment service
|
||||
PaymentTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
DependsOn: ['RabbitMqService']
|
||||
Properties:
|
||||
Family: !Ref 'PaymentServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
NetworkMode: awsvpc
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'PaymentServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: robotshop/rs-payment:0.4.17
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'PaymentContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
PaymentService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: [LoadBalancerRule, PaymentRegistryService]
|
||||
Properties:
|
||||
ServiceName: !Ref 'PaymentServiceName'
|
||||
NetworkConfiguration:
|
||||
AwsvpcConfiguration:
|
||||
Subnets:
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetOne']]
|
||||
- Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PrivateSubnetTwo']]
|
||||
ServiceRegistries:
|
||||
- ContainerName: !Ref 'PaymentServiceName'
|
||||
ContainerPort: !Ref 'PaymentContainerPort'
|
||||
RegistryArn: !GetAtt PaymentRegistryService.Arn
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'PaymentTaskDefinition'
|
||||
|
||||
PaymentRegistryService:
|
||||
Type: AWS::ServiceDiscovery::Service
|
||||
DependsOn: Registry
|
||||
Properties:
|
||||
Name: !Ref 'PaymentServiceName'
|
||||
DnsConfig:
|
||||
NamespaceId: !GetAtt Registry.Id
|
||||
DnsRecords:
|
||||
- TTL: 10
|
||||
Type: SRV
|
||||
- TTL: 10
|
||||
Type: A
|
||||
RoutingPolicy: WEIGHTED
|
||||
|
||||
# dispatch service
|
||||
DispatchTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
DependsOn: ['RabbitMqService']
|
||||
Properties:
|
||||
Family: !Ref 'DispatchServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'DispatchServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: robotshop/rs-dispatch:0.4.17
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'DispatchContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: json-file
|
||||
DispatchService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: LoadBalancerRule
|
||||
Properties:
|
||||
ServiceName: !Ref 'DispatchServiceName'
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DesiredCount: 1
|
||||
TaskDefinition: !Ref 'DispatchTaskDefinition'
|
||||
|
||||
WebTaskDefinition:
|
||||
Type: AWS::ECS::TaskDefinition
|
||||
Properties:
|
||||
Family: !Ref 'WebServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
TaskRoleArn:
|
||||
Fn::If:
|
||||
- 'HasCustomRole'
|
||||
- !Ref 'Role'
|
||||
- !Ref "AWS::NoValue"
|
||||
ContainerDefinitions:
|
||||
- Name: !Ref 'WebServiceName'
|
||||
Cpu: !Ref 'ContainerCpu'
|
||||
Memory: !Ref 'ContainerMemory'
|
||||
Image: robotshop/rs-web:0.4.17
|
||||
Environment:
|
||||
- Name: CATALOGUE_HOST
|
||||
Value: catalogue.robot-shop
|
||||
- Name: USER_HOST
|
||||
Value: user.robot-shop
|
||||
- Name: CART_HOST
|
||||
Value: cart.robot-shop
|
||||
- Name: SHIPPING_HOST
|
||||
Value: shipping.robot-shop
|
||||
- Name: PAYMENT_HOST
|
||||
Value: payment.robot-shop
|
||||
- Name: RATINGS_HOST
|
||||
Value: ratings.robot-shop
|
||||
PortMappings:
|
||||
- ContainerPort: !Ref 'WebContainerPort'
|
||||
LogConfiguration:
|
||||
LogDriver: awslogs
|
||||
Options:
|
||||
awslogs-create-group: true
|
||||
awslogs-region: !Ref AWS::Region
|
||||
awslogs-group: !Ref WebLogGroup
|
||||
awslogs-stream-prefix: ecs
|
||||
WebService:
|
||||
Type: AWS::ECS::Service
|
||||
DependsOn: ['LoadBalancerRule', 'CatalogueService']
|
||||
Properties:
|
||||
ServiceName: !Ref 'WebServiceName'
|
||||
Cluster:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'ClusterName']]
|
||||
DeploymentConfiguration:
|
||||
MaximumPercent: 200
|
||||
MinimumHealthyPercent: 75
|
||||
DesiredCount: !Ref 'DesiredCount'
|
||||
TaskDefinition: !Ref 'WebTaskDefinition'
|
||||
LoadBalancers:
|
||||
- ContainerName: !Ref 'WebServiceName'
|
||||
ContainerPort: !Ref 'WebContainerPort'
|
||||
TargetGroupArn: !Ref 'WebTargetGroup'
|
||||
WebTargetGroup:
|
||||
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
||||
Properties:
|
||||
HealthCheckIntervalSeconds: 6
|
||||
HealthCheckPath: /
|
||||
HealthCheckProtocol: HTTP
|
||||
HealthCheckTimeoutSeconds: 5
|
||||
HealthyThresholdCount: 2
|
||||
Name: !Ref 'WebServiceName'
|
||||
Port: !Ref 'WebContainerPort'
|
||||
Protocol: HTTP
|
||||
UnhealthyThresholdCount: 2
|
||||
VpcId:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'VPCId']]
|
||||
LoadBalancerRule:
|
||||
Type: AWS::ElasticLoadBalancingV2::ListenerRule
|
||||
Properties:
|
||||
Actions:
|
||||
- TargetGroupArn: !Ref 'WebTargetGroup'
|
||||
Type: 'forward'
|
||||
Conditions:
|
||||
- Field: path-pattern
|
||||
Values: [!Ref 'Path']
|
||||
ListenerArn:
|
||||
Fn::ImportValue:
|
||||
!Join [':', [!Ref 'StackName', 'PublicListener']]
|
||||
Priority: !Ref 'Priority'
|
8
aws-ecs-fargate/README.md
Normal file
8
aws-ecs-fargate/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Robot-Shop on AWS ECS with Fargate
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The `ecs-cli` tool has to be on your `$PATH`.
|
||||
|
||||
[Read more on installing it](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_CLI_installation.html)
|
||||
|
Reference in New Issue
Block a user