Reputation: 1929
I am trying to translate a manually created service to a cloudformation template but I keep getting errors.
Task definition is already created with UI because it needs some specific roles
This template gives me: Classic Load Balancers are not supported with Fargate
ServicesSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for cluster services
VpcId: !Ref 'VPC'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
SourceSecurityGroupId: !Ref "PublicLoadBalancerSG"
ServiceStaging:
Type: AWS::ECS::Service
Properties:
ServiceName: pouch-svc-staging
TaskDefinition: pouch-td-staging:4
Cluster: !Ref 'ClusterECS'
DesiredCount: 2
SchedulingStrategy: REPLICA
LaunchType: FARGATE
EnableECSManagedTags: true
DeploymentConfiguration:
MinimumHealthyPercent: 100
MaximumPercent: 200
DeploymentCircuitBreaker:
Enable: false
Rollback: false
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
Subnets:
- !Ref PublicSubnetOne
- !Ref PublicSubnetTwo
SecurityGroups:
- !Ref ServicesSG
LoadBalancers:
- ContainerName: pouch-image-staging
LoadBalancerName: !Ref 'LoadBalancerName'
ContainerPort: 3100
Update: Here is the modified full cloudformation template without a load balancer name as explicited by some comments
AWSTemplateFormatVersion: '2010-09-09'
Description: VPC, subnets and external, public facing load balancer, for forwarding public traffic to containers
Parameters:
LoadBalancerName:
Type: String
Default: pouch-api-elb
ClusterName:
Type: String
Default: pouch-api-cluster
Mappings:
SubnetConfig:
VPC:
CIDR: '172.16.0.0/16'
PublicOne:
CIDR: '172.16.0.0/24'
PublicTwo:
CIDR: '172.16.1.0/24'
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
EnableDnsSupport: true
EnableDnsHostnames: true
CidrBlock: !FindInMap ['SubnetConfig', 'VPC', 'CIDR']
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
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
PublicLoadBalancerSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Access to the public facing load balancer
VpcId: !Ref 'VPC'
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
PublicLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Ref 'LoadBalancerName'
Scheme: internet-facing
LoadBalancerAttributes:
- Key: idle_timeout.timeout_seconds
Value: "30"
Subnets:
- !Ref PublicSubnetOne
- !Ref PublicSubnetTwo
SecurityGroups: [!Ref "PublicLoadBalancerSG"]
TargetGroupStaging:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 6
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 2
VpcId: !Ref 'VPC'
TargetGroupProduction:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 6
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 2
VpcId: !Ref 'VPC'
ListenerRuleProduction:
Type: "AWS::ElasticLoadBalancingV2::ListenerRule"
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref "TargetGroupProduction"
Conditions:
- Field: path-pattern
PathPatternConfig:
Values:
- /production/*
ListenerArn: !Ref PublicLoadBalancerListener
Priority: 100
ListenerRuleStaging:
Type: "AWS::ElasticLoadBalancingV2::ListenerRule"
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref "TargetGroupStaging"
Conditions:
- Field: path-pattern
PathPatternConfig:
Values:
- /staging/*
ListenerArn: !Ref PublicLoadBalancerListener
Priority: 50
PublicLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: "redirect"
RedirectConfig:
Protocol: "#{protocol}"
Port: "#{port}"
Host: "#{host}"
Path: "/production/"
StatusCode: "HTTP_301"
LoadBalancerArn: !Ref "PublicLoadBalancer"
Port: 80
Protocol: HTTP
ClusterECS:
Type: AWS::ECS::Cluster
DependsOn: PublicLoadBalancerListener
Properties:
ClusterName: !Ref 'ClusterName'
CapacityProviders:
- FARGATE
ServicesSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for cluster services
VpcId: !Ref 'VPC'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
SourceSecurityGroupId: !Ref "PublicLoadBalancerSG"
ServiceStaging:
Type: AWS::ECS::Service
Properties:
ServiceName: pouch-svc-staging
TaskDefinition: pouch-td-staging:4
Cluster: !Ref 'ClusterECS'
DesiredCount: 2
SchedulingStrategy: REPLICA
LaunchType: FARGATE
EnableECSManagedTags: true
DeploymentConfiguration:
MinimumHealthyPercent: 100
MaximumPercent: 200
DeploymentCircuitBreaker:
Enable: false
Rollback: false
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
Subnets:
- !Ref PublicSubnetOne
- !Ref PublicSubnetTwo
SecurityGroups:
- !Ref ServicesSG
LoadBalancers:
- ContainerName: pouch-image-staging
TargetGroupArn: !Ref 'TargetGroupStaging'
ContainerPort: 3100
ServiceProduction:
Type: AWS::ECS::Service
Properties:
ServiceName: pouch-svc-production
TaskDefinition: pouch-td-production:4
Cluster: !Ref 'ClusterECS'
DesiredCount: 2
SchedulingStrategy: REPLICA
LaunchType: FARGATE
EnableECSManagedTags: true
DeploymentConfiguration:
MinimumHealthyPercent: 100
MaximumPercent: 200
DeploymentCircuitBreaker:
Enable: false
Rollback: false
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
Subnets:
- !Ref PublicSubnetOne
- !Ref PublicSubnetTwo
SecurityGroups:
- !Ref ServicesSG
LoadBalancers:
- ContainerName: pouch-image-production
TargetGroupArn: !Ref 'TargetGroupProduction'
ContainerPort: 3100
Outputs:
VpcId:
Description: The ID of the VPC that this stack is deployed in
Value: !Ref 'VPC'
PublicSubnetOne:
Description: Public subnet one
Value: !Ref 'PublicSubnetOne'
PublicSubnetTwo:
Description: Public subnet two
Value: !Ref 'PublicSubnetTwo'
ExternalUrl:
Description: The url of the external load balancer
Value: !Sub http://${PublicLoadBalancer.DNSName}
And now I am getting "The target group with targetGroupArn arn:aws:elasticloadbalancing: ... :targetgroup/pouch-Targe-XFJ4AI7HCF6G/f2a665925da27326 does not have an associated load balancer"
Upvotes: 1
Views: 1160
Reputation: 3802
From official AWS documentation:
LoadBalancerName The name of the load balancer to associate with the Amazon ECS service or task set.
A load balancer name is only specified when using a Classic Load Balancer. If you are using an Application Load Balancer or a Network Load Balancer the load balancer name parameter should be omitted.
That means that you should not specify the name of the load balancer in the CloudFormation template, since you're using Fargate, and consequently, don't use the classic load balancer.
Also, in your place, I would consider using something like Former2. It's a great tool that can generate CloudFormation template for you. You can scan your account, choose the services for which you want a template created. In order to use it though, you need an Access key and secret key, so consider creating an IAM user with read-only privilege.
Edit to cover 2nd error about target group:
The Amazon ECS service requires an explicit dependency on the Application Load Balancer listener rule and the Application Load Balancer listener. This prevents the service from starting before the listener is ready.
It's possible that AWS::ECS::Service
is trying to attach to the target group before the target group is added to the load balancer. In order to fix that, you should add a dependency in your Service, like this:
Type: AWS::ECS::Service
DependsOn: Listener # Add exact listener name, depending on the service
Properties:
That should help fix the issue.
Upvotes: 5
Reputation: 121
I cannot add a comment yet. I think the following link could help with the issue Classic Load Balancers are not supported with Fargate
AWS Load Balancing multiple ports for an ECS Service with Fargate
Upvotes: 1