Translate ECS service to cloudformation - amazon-web-services

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"

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.

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

Related

AWS Fargate: unable to pull secrets or registry auth

I am trying to launch a containerized grpc application on aws fargate. I've tested the image locally, and have pushed it to ecr. I've created a task with a role that has permission to reach ecr, yet I am still getting an error pulling the container (error message shown below). I even tried launching the container in a public subnet with internet gateway/route table association that auto assigns public ips and the security group allows all outbound traffic.
The full cloudformation template is given below:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
TicketingAppTaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
ContainerDefinitions:
- Essential: true
Image: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/ticketing-app:latest"
Name: ticketing-app
PortMappings:
- ContainerPort: 8080
Cpu: "1 vCPU"
ExecutionRoleArn: !Ref ExecutionRole
Memory: "2 GB" #this is smallest for 1 vcpu .... could maybe decrease
NetworkMode: awsvpc
RuntimePlatform:
CpuArchitecture: X86_64
OperatingSystemFamily: LINUX
ExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: [ sts:AssumeRole ]
Effect: Allow
Principal:
Service: [ ecs-tasks.amazonaws.com ]
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
TicketingEcsService:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref TicketingEcsCluster
LaunchType: FARGATE
#TODO I think we eventually need to specify load balancers here
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED #TODO remove this when done, just seeing if this let's us grab image from ecr?
SecurityGroups: [ !GetAtt TicketingServiceSecurityGroup.GroupId ]
Subnets:
- !Ref TicketingServicePrivateSubnet01
- !Ref TicketingServicePrivateSubnet02
TaskDefinition: !Ref TicketingAppTaskDefinition
TicketingEcsCluster:
Type: AWS::ECS::Cluster
TicketingServiceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "A security group used for the ticketing app"
VpcId: !Ref TicketingServiceVpc
TicketingServiceVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
TicketingServicePrivateSubnet01:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Sub "${AWS::Region}a"
VpcId: !Ref TicketingServiceVpc
CidrBlock: 10.0.0.0/18
TicketingServicePrivateSubnet02:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Sub "${AWS::Region}b"
VpcId: !Ref TicketingServiceVpc
CidrBlock: 10.0.64.0/18
#TODO public subnets and NAT gateway?
TicketingSecurityGroupHttpIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
#TODO I would probably use load balancer security group name here once we make one instead of opening up to any ip
GroupId: !GetAtt TicketingServiceSecurityGroup.GroupId
CidrIpv6: "::/0"
FromPort: 8080
IpProtocol: tcp
ToPort: 8080
TicketingSecurityGroupAllTrafficEgress:
Type: AWS::EC2::SecurityGroupEgress
Properties:
GroupId: !GetAtt TicketingServiceSecurityGroup.GroupId
IpProtocol: "-1" #-1 indicates all -- like a wildcard
CidrIp: "0.0.0.0/0"
TicketingServiceInternetGateway:
Type: AWS::EC2::InternetGateway
DependsOn: TicketingServiceVpc
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref TicketingServiceVpc
InternetGatewayId: !Ref TicketingServiceInternetGateway
TicketingAppRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref TicketingServiceVpc
TicketingVPCRouteAllTrafficToInternetGateway:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref TicketingAppRouteTable
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref TicketingServiceInternetGateway
Would anyone be able to point out a simple way to get this working (even if it uses not best practices, such as public subnet instead of private subnet and nat gateway) -- it is just for a poc.
Thanks
I had pushed my image to ecr in a different region..... changed the region and it worked (face palm).
So check your region if anyone else is in the same spot as me.

AWS ECS Scheduled task not running when released by CI/CD

I'm experiencing a very annoying problem. I created a CI/CD pipelines using AWS CodePipeline and CloudFormation.
This is the template.yml used by CloudFormation to create a ScheduledTask on ECS.
AWSTemplateFormatVersion: "2010-09-09"
Description: Template for deploying a ECR image on ECS
Resources:
VPC:
Type: "AWS::EC2::VPC"
Properties:
CidrBlock: "10.0.0.0/16"
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: default
Subnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !Sub "10.0.0.0/20"
MapPublicIpOnLaunch: true
Subnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [1, !GetAZs ""]
CidrBlock: !Sub "10.0.32.0/20"
MapPublicIpOnLaunch: true
InternetGateway:
Type: "AWS::EC2::InternetGateway"
VPCGatewayAttachment:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
RouteTable:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref VPC
RouteTableAssociation1:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref Subnet1
RouteTableId: !Ref RouteTable
RouteTableAssociation2:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref Subnet2
RouteTableId: !Ref RouteTable
InternetRoute:
Type: "AWS::EC2::Route"
DependsOn: VPCGatewayAttachment
Properties:
GatewayId: !Ref InternetGateway
RouteTableId: !Ref RouteTable
DestinationCidrBlock: "0.0.0.0/0"
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: "SLAComputation"
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: ecs-services
Subnets:
- !Ref "Subnet1"
- !Ref "Subnet2"
SecurityGroups:
- !Ref LoadBalancerSecurityGroup
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref LoadBalancer
Protocol: HTTP
Port: 80
DefaultActions:
- Type: forward
TargetGroupArn: !Ref DefaultTargetGroup
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for loadbalancer to services on ECS
VpcId: !Ref "VPC"
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
DefaultTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: default
VpcId: !Ref "VPC"
Protocol: "HTTP"
Port: "80"
CloudWatchLogsGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: "sla_computation"
RetentionInDays: 1
ContainerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref "VPC"
GroupDescription: for ecs containers
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref "LoadBalancerSecurityGroup"
IpProtocol: -1
Task:
Type: AWS::ECS::TaskDefinition
Properties:
Family: apis
Cpu: 1024
Memory: 2048
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn: !Ref ECSTaskExecutionRole
ContainerDefinitions:
- Name: ass001
Image: !Sub 649905970782.dkr.ecr.eu-west-1.amazonaws.com/ass001:latest
Cpu: 1024
Memory: 2048
HealthCheck:
Command: [ "CMD-SHELL", "exit 0" ]
Interval: 30
Retries: 5
Timeout: 10
StartPeriod: 30
PortMappings:
- ContainerPort: 8080
Protocol: tcp
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: "sla_computation"
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: "ass001"
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: employee-tg
VpcId: !Ref VPC
Port: 80
Protocol: HTTP
Matcher:
HttpCode: 200-299
TargetType: ip
ListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
ListenerArn: !Ref LoadBalancerListener
Priority: 2
Conditions:
- Field: path-pattern
Values:
- /*
Actions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
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:
# ECS Tasks to download images from ECR
- "ecr:GetAuthorizationToken"
- "ecr:BatchCheckLayerAvailability"
- "ecr:GetDownloadUrlForLayer"
- "ecr:BatchGetImage"
# ECS tasks to upload logs to CloudWatch
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource: "*"
TaskSchedule:
Type: AWS::Events::Rule
Properties:
Description: SLA rule ass001
Name: ass001
ScheduleExpression: cron(0/5 * * * ? *)
State: ENABLED
Targets:
- Arn:
!GetAtt ECSCluster.Arn
Id: dump-data-ecs-task
RoleArn:
!GetAtt ECSTaskExecutionRole.Arn
EcsParameters:
TaskDefinitionArn:
!Ref Task
TaskCount: 1
LaunchType: FARGATE
PlatformVersion: LATEST
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- sg-07db5ae6616a8c5fc
Subnets:
- subnet-031d0787ad492c1c4
TaskSchedule:
Type: AWS::Events::Rule
Properties:
Description: SLA rule ass002
Name: ass002
ScheduleExpression: cron(0/5 * * * ? *)
State: ENABLED
Targets:
- Arn:
!GetAtt ECSCluster.Arn
Id: dump-data-ecs-task
RoleArn:
!GetAtt ECSTaskExecutionRole.Arn
EcsParameters:
TaskDefinitionArn:
!Ref Task
TaskCount: 1
LaunchType: FARGATE
PlatformVersion: LATEST
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- sg-07db5ae6616a8c5fc
Subnets:
- subnet-031d0787ad492c1c4
Outputs:
ApiEndpoint:
Description: Employee API Endpoint
Value: !Join ["", ["http://", !GetAtt LoadBalancer.DNSName, "/employees"]]
Export:
Name: "EmployeeApiEndpoint"
The ScheduledTask is created successfully but it is not running actually. Very strange. But the strangest thing is that the ScheduledTask starts working when I click on "Edit" from the AWS console and (without making any change) I save.
The main issue I see is that you are using wrong role for your scheduled rule. It can't be !GetAtt ECSTaskExecutionRole.Arn. Instead you should create new role (or edit existing one) which has AmazonEC2ContainerServiceEventsRole AWS Managed policy.
It works after you edit in console, because AWS console will probably create the correct role in the background and use it instead of yours.

Cloudformation Blue/Green Deployment HealthCheckGracePeriodSeconds

I am trying to use the Cloudformation Codedeploy Blue/Green deployment feature so have a task set that looks like the following.
TaskSet:
Type: AWS::ECS::TaskSet
Properties:
Cluster:
Fn::ImportValue: !Sub "${ClusterStackName}-ClusterID"
LaunchType: FARGATE
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- !Ref FargateSecurityGroup
Subnets:
- Fn::ImportValue: !Sub "${ClusterStackName}-SUBNET1ID"
- Fn::ImportValue: !Sub "${ClusterStackName}-SUBNET2ID"
PlatformVersion: 1.3.0
Scale:
Unit: PERCENT
Value: 1
Service: !Ref ECSService
TaskDefinition: !Ref TaskDefinition
LoadBalancers:
- ContainerName: !Ref ServiceName
ContainerPort: !Ref ContainerPort
TargetGroupArn: !Ref TargetGroup
My ECS Service definition looks like the following
ECSService:
Type: AWS::ECS::Service
DependsOn: HTTPSListener
Properties:
ServiceName: !Sub "${ServiceName}-service"
Cluster:
Fn::ImportValue: !Sub "${ClusterStackName}-ClusterID"
DeploymentController:
Type: EXTERNAL
DesiredCount: 4
EnableECSManagedTags: true
HealthCheckGracePeriodSeconds: 30
SchedulingStrategy: REPLICA
This causes the following error in Cloudformation
Invalid request provided: CreateService error: Health check grace period is only valid for services configured to use load balancers
However omitting HealthCheckGracePeriodSeconds causes my tasks to fail the healthcheck while starting. I have checked the docs and there appears to be no option to add HealthCheckGracePeriodSeconds to the TaskSet definition.
How can I use Cloudformation blue/green deployment for ECS with a health check grace period?
Full Example
Here is a full template that I would expect to work but does not.
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Image:
Type: String
Vpc:
Type: 'AWS::EC2::VPC::Id'
Subnet1:
Type: 'AWS::EC2::Subnet::Id'
Subnet2:
Type: 'AWS::EC2::Subnet::Id'
Transform:
- AWS::CodeDeployBlueGreen
Hooks:
CodeDeployBlueGreenHook:
Type: AWS::CodeDeploy::BlueGreen
Properties:
TrafficRoutingConfig:
Type: AllAtOnce
Applications:
- Target:
Type: AWS::ECS::Service
LogicalID: ECSService
ECSAttributes:
TaskDefinitions:
- TaskDefinition
- GreenTaskDefinition
TaskSets:
- TaskSet
- GreenTaskSet
TrafficRouting:
ProdTrafficRoute:
Type: AWS::ElasticLoadBalancingV2::Listener
LogicalID: HTTPListener
TargetGroups:
- TargetGroup
- TargetGroupGreen
Resources:
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP to load balancer
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
FargateSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow port 80 to service
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ALBSecurityGroup
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: load-balancer
Type: application
IpAddressType: ipv4
Scheme: internet-facing
SecurityGroups: [!Ref ALBSecurityGroup]
Subnets: [!Ref Subnet1, !Ref Subnet2]
HTTPListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
LoadBalancerArn: !Ref LoadBalancer
Port: 80
Protocol: HTTP
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
Name: targetgroup-blue
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 10
VpcId: !Ref Vpc
TargetGroupGreen:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
Name: targetgroup-green
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 10
VpcId: !Ref Vpc
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: "task-family-name"
NetworkMode: awsvpc
RequiresCompatibilities: [FARGATE]
Cpu: 512
Memory: 1024
ContainerDefinitions:
- Name: Container
Essential: true
Image: !Ref Image
PortMappings:
- ContainerPort: 80
TaskSet:
Type: AWS::ECS::TaskSet
Properties:
Cluster: !Ref ECSCluster
LaunchType: FARGATE
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!Ref FargateSecurityGroup]
Subnets: [!Ref Subnet1, !Ref Subnet2]
Scale:
Unit: PERCENT
Value: 100
Service: !Ref ECSService
TaskDefinition: !Ref TaskDefinition
PlatformVersion: LATEST
LoadBalancers:
- ContainerName: Container
ContainerPort: 80
TargetGroupArn: !Ref TargetGroup
ECSService:
Type: AWS::ECS::Service
DependsOn: HTTPListener
Properties:
ServiceName: "service"
Cluster: !Ref ECSCluster
DeploymentController:
Type: EXTERNAL
DesiredCount: 4
EnableECSManagedTags: true
HealthCheckGracePeriodSeconds: 30
SchedulingStrategy: REPLICA
PrimaryTaskSet:
Type: 'AWS::ECS::PrimaryTaskSet'
Properties:
Cluster: !Ref ECSCluster
Service: !Ref ECSService
TaskSetId: !GetAtt 'TaskSet.Id'
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: Cluster
CapacityProviders:
- FARGATE
DefaultCapacityProviderStrategy:
- CapacityProvider: FARGATE
Weight: 1
The error is correct, health checks at the Service level, will need a Load Balancer. However, you can define at the task level, health checks:
EscTaskDef:
Type: 'AWS::ECS::TaskDefinition'
Properties:
...
ContainerDefinitions:
- Name: !Ref AWS::StackName
Image: !Ref Image
PortMappings:
- ContainerPort: 80
HealthCheck:
Command: [ "CMD-SHELL", "curl -f http://localhost:80/api/healthcheck/ping || exit 1" ]
StartPeriod: 200
Here is an example of a rollback example using this type of health check with Cloudformation.

Trigger Cloudformation Blue/Green With Image Parameter Change

In my Cloudformation template, I am using the blue-green deployment trigger and have the following TaskDefinition
TaskDefinition:
Type: AWS::ECS::TaskDefinition
DependsOn: LogGroup
Properties:
Family: "task-family-name"
NetworkMode: awsvpc
RequiresCompatibilities: [FARGATE]
Cpu: 512
Memory: 1024
ExecutionRoleArn: arn:aws:iam::579072907853:role/ecsTaskExecutionRole
TaskRoleArn: !Ref ServiceRole
ContainerDefinitions:
- Name: !Ref ServiceName
Essential: true
Image: !Ref ImageARN
PortMappings:
- ContainerPort: !Ref ContainerPort
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-region: !Ref AWS::Region
awslogs-group: !Ref LogGroup
awslogs-stream-prefix: ecs
Environment:
- Name: RACK_ENV
Value: !Ref EnvironmentName
If I update the stack with a new value for the ImageARN parameter, I get the following error
'CodeDeployBlueGreenHook' of type AWS::CodeDeploy::BlueGreen failed with message: The submitted template's primary task definition 'TaskDefinition' was never updated. The template's 'AWS::CodeDeployBlueGreen' Transform might be missing or removed
If I don't use a parameter but instead use a hardcoded Image then update the template it works fine.
Is there a way to use a parameter?
Example
Below is a full example of a template that has this issue. I change the ImageARN parameter between these two images
nginx:1.18.0#sha256:001487e0a8c6abf91351ab45fdb308c0c2b95e8a67260b7ca5cf064462689a9e
nginx:1.19.4#sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Image:
Type: String
CIDRBlock:
Type: String
Default: 192.168.5.0/24
Description: CIDR block for VPC
ExecutionRoleARN:
Type: String
Transform:
- AWS::CodeDeployBlueGreen
Hooks:
CodeDeployBlueGreenHook:
Type: AWS::CodeDeploy::BlueGreen
Properties:
TrafficRoutingConfig:
Type: AllAtOnce
Applications:
- Target:
Type: AWS::ECS::Service
LogicalID: ECSService
ECSAttributes:
TaskDefinitions:
- TaskDefinition
- GreenTaskDefinition
TaskSets:
- TaskSet
- GreenTaskSet
TrafficRouting:
ProdTrafficRoute:
Type: AWS::ElasticLoadBalancingV2::Listener
LogicalID: HTTPListener
TargetGroups:
- TargetGroup
- TargetGroupGreen
Resources:
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP to load balancer
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
FargateSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow port 80 to service
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ALBSecurityGroup
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: load-balancer
Type: application
IpAddressType: ipv4
Scheme: internet-facing
SecurityGroups: [!Ref ALBSecurityGroup]
Subnets: [!Ref Subnet1, !Ref Subnet2]
HTTPListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
LoadBalancerArn: !Ref LoadBalancer
Port: 80
Protocol: HTTP
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
Name: targetgroup-blue
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 10
VpcId: !Ref Vpc
TargetGroupGreen:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
Name: targetgroup-green
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 10
VpcId: !Ref Vpc
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: "task-family-name"
NetworkMode: awsvpc
RequiresCompatibilities: [FARGATE]
Cpu: 512
Memory: 1024
ExecutionRoleArn: !Ref ExecutionRoleARN
ContainerDefinitions:
- Name: Container
Essential: true
Image: !Ref Image
PortMappings:
- ContainerPort: 80
TaskSet:
Type: AWS::ECS::TaskSet
Properties:
Cluster: !Ref ECSCluster
LaunchType: FARGATE
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!Ref FargateSecurityGroup]
Subnets: [!Ref Subnet1, !Ref Subnet2]
Scale:
Unit: PERCENT
Value: 100
Service: !Ref ECSService
TaskDefinition: !Ref TaskDefinition
PlatformVersion: LATEST
LoadBalancers:
- ContainerName: Container
ContainerPort: 80
TargetGroupArn: !Ref TargetGroup
ECSService:
Type: AWS::ECS::Service
DependsOn: HTTPListener
Properties:
ServiceName: service
Cluster: !Ref ECSCluster
DeploymentController:
Type: EXTERNAL
DesiredCount: 4
EnableECSManagedTags: true
PrimaryTaskSet:
Type: 'AWS::ECS::PrimaryTaskSet'
Properties:
Cluster: !Ref ECSCluster
Service: !Ref ECSService
TaskSetId: !GetAtt 'TaskSet.Id'
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref CIDRBlock
EnableDnsHostnames: true
EnableDnsSupport: true
Subnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: !Select [0, !Cidr [!Ref CIDRBlock, 2, 6 ]]
AvailabilityZone: !Select [0, Fn::GetAZs: !Ref 'AWS::Region']
Subnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: !Select [1, !Cidr [!Ref CIDRBlock, 2, 6 ]]
AvailabilityZone: !Select [1, Fn::GetAZs: !Ref 'AWS::Region']
InternetGateway:
Type: AWS::EC2::InternetGateway
InternetGatewayVPCAssoc:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref Vpc
InternetGatewayId: !Ref InternetGateway
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
RouteTableSub1Assoc:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref Subnet1
RouteTableSub2Assoc:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref Subnet2
InternetGatewayRoute:
Type: AWS::EC2::Route
DependsOn: InternetGateway
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: Cluster
CapacityProviders:
- FARGATE
DefaultCapacityProviderStrategy:
- CapacityProvider: FARGATE
Weight: 1
I looked at your example, and what I have in my own projects. I can confirm that your example does not work as expected.
I investigated more and determined that the issue is likely to be due to creation of entire networking stack in your template. In my own projects I don't have VPC or subnets in my ecs templates, thus it all works.
So once I removed the VPC related things from your template it started to work as required. There are some other smaller changes, but they may not be necessary. I think the VPC-stuff is the main reason.
Also, please update the template by using Replace current template option, rather then Use current template. If you use the second option it will still not work. I think this is due to how macros work in CFN, and template should be replaced, rather then updated in-place. If you replace it, B/G in CodeDeploy is successful trigger and you can view it CodeDeploy console.
Here is the modified template:
AWSTemplateFormatVersion: 2010-09-09
Parameters:
ImageUrl:
Type: String
VpcId:
Type: 'AWS::EC2::VPC::Id'
Subnet1:
Type: 'AWS::EC2::Subnet::Id'
Subnet2:
Type: 'AWS::EC2::Subnet::Id'
ExecutionRoleARN:
Type: String
DesiredCount:
Type: Number
Default: 2
Transform:
- 'AWS::CodeDeployBlueGreen'
Hooks:
CodeDeployBlueGreenHook:
Type: 'AWS::CodeDeploy::BlueGreen'
Properties:
TrafficRoutingConfig:
Type: AllAtOnce
Applications:
- Target:nginx:1.19.4#sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054
Type: 'AWS::ECS::Service'
LogicalID: ECSService
ECSAttributes:
TaskDefinitions:
- TaskDefinition
- GreenTaskDefinition
TaskSets:
- TaskSet
- GreenTaskSet
TrafficRouting:
ProdTrafficRoute:
Type: 'AWS::ElasticLoadBalancingV2::Listener'
LogicalID: HTTPListener
TargetGroups:
- TargetGroupnginx:1.19.4#sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054
- TargetGroupGreen
Resources:
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP to load balancer
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
FargateSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow port 80 to service
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ALBSecurityGroup
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
#Name: load-balancer
Type: application
IpAddressType: ipv4
Scheme: internet-facing
SecurityGroups:
- !Ref ALBSecurityGroup
Subnets:
- !Ref Subnet1
- !Ref Subnet2
HTTPListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
LoadBalancerArn: !Ref LoadBalannginx:1.19.4#sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054cer
Port: 80
Protocol: HTTP
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
#Name: targetgroup-blue
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 10
VpcId: !Ref VpcId
TargetGroupGreen:
Type: nginx:1.19.4#sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054AWS::ElasticLoadBalancingV2nginx:1.19.4#sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
#Name: targetgroup-green
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 10
VpcId: !Ref VpcId
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: "task-family-name"
NetworkMode: awsvpc
RequiresCompatibilities: [FARGATE]
Cpu: 256
Memory: 512
ExecutionRoleArn: !Ref ExecutionRoleARN
ContainerDefinitions:
- Name: Container
Essential: true
Image: !Ref ImageUrl
PortMappings:
- ContainerPort: 80
Protocol: tcp
TaskSet:
Type: AWS::ECS::TaskSet
Properties:
Cluster: !Ref ECSCluster
LaunchType: FARGATE
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- !Ref FargateSecurityGroup
Subnets:
- !Ref Subnet1
- !Ref Subnet2
Scale:
Unit: PERCENT
Value: 100
Service: !Ref ECSService
TaskDefinition: !Ref TaskDefinition
PlatformVersion: LATEST
LoadBalancers:
- ContainerName: Container
ContainerPort: 80
TargetGroupArn: !Ref TargetGroup
ECSService:
Type: AWS::ECS::Service
DependsOn: HTTPListener
Properties:
#ServiceName: service
Cluster: !Ref ECSCluster
DeploymentController:
Type: EXTERNAL
DesiredCount: !Ref DesiredCount
EnableECSManagedTags: true
PrimaryTaskSet:
Type: 'AWS::ECS::PrimaryTaskSet'
Properties:
Cluster: !Ref ECSCluster
Service: !Ref ECSService
TaskSetId: !GetAtt TaskSet.Id
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
#ClusterName: Cluster
CapacityProviders:
- FARGATE
DefaultCapacityProviderStrategy:
- CapacityProvider: FARGATE
Weight: 1
Outputs:
ALBDNSName:
Value: !GetAtt LoadBalancer.DNSName
When I had this issue the solution was to replace the Image value within a step in the pipeline before the AWS CloudFomration step, basically "building" the file before deployment instead of passing parameters. Is not fancy but it works, I expect there are better solutions to this.

Error while configuring Application loadbalancer in ECS using cloudformation

I am creating ECS cluster, service and task using cloudformation but it gives an error: Embedded stack arn:aws:cloudformation:us-east-2:0212657325299:stack/Root-Cluster-153O1DKDIKGLV/f1123c5c-d1f9-11ea-1216-2a3e4111fce2 was not successfully created: The following resource(s) failed to create: [Myservice, LoadBalancerListener]. I have created a root stack which runs the vpc stack and Cluster stack. This error occurs when running the Cluster stack. I think the error is in the Load balancer and role in Myservice but I am unable to figure the solution. Any help would be appreciated.
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
SubnetA:
Type: String
SubnetB:
Type: String
VpcID:
Type: String
Resources:
Albsg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: alb-sg
VpcId: !Ref VpcID
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Description: For traffic from Internet
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Description: For traffic from Internet
GroupDescription: Security Group for demo server
Alb:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
Name: Alb
Scheme: internet-facing
SecurityGroups:
- !Ref Albsg
Subnets:
- Ref: "SubnetA"
- Ref: "SubnetB"
Type: application
DefaultTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: alb-tg
VpcId: !Ref VpcID
Port: 80
Protocol: HTTP
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref Alb
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref DefaultTargetGroup
MyCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: Flask-redis
Myservice:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref MyCluster
DeploymentController:
Type: ECS
DesiredCount: 2
LaunchType: EC2
LoadBalancers:
- !Ref Alb
# Role: String
SchedulingStrategy: REPLICA
ServiceName: Python-service
TaskDefinition: !Ref Task
Task:
Type: AWS::ECS::TaskDefinition
Properties:
Family: redis-python
ContainerDefinitions:
- Essential: true
Image: redis:latest
Name: redis
Cpu: .5 vCPU
# ExecutionRoleArn: !Ref Role
Memory: 0.5 GB
NetworkMode: bridge
RequiresCompatibilities:
- EC2---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
SubnetA:
Type: String
SubnetB:
Type: String
VpcID:
Type: String
Resources:
Albsg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: alb-sg
VpcId: !Ref VpcID
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Description: For traffic from Internet
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Description: For traffic from Internet
GroupDescription: Security Group for demo server
Alb:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
Name: Alb
Scheme: internet-facing
SecurityGroups:
- !Ref Albsg
Subnets:
- Ref: "SubnetA"
- Ref: "SubnetB"
Type: application
DefaultTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: alb-tg
VpcId: !Ref VpcID
Port: 80
Protocol: HTTP
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref Alb
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref DefaultTargetGroup
MyCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: Flask-redis
Myservice:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref MyCluster
DeploymentController:
Type: ECS
DesiredCount: 2
LaunchType: EC2
LoadBalancers:
- !Ref Alb
# Role: String
SchedulingStrategy: REPLICA
ServiceName: Python-service
TaskDefinition: !Ref Task
Task:
Type: AWS::ECS::TaskDefinition
Properties:
Family: redis-python
ContainerDefinitions:
- Essential: true
Image: redis:latest
Name: redis
Cpu: .5 vCPU
# ExecutionRoleArn: !Ref Role
Memory: 0.5 GB
NetworkMode: bridge
RequiresCompatibilities:
- EC2
The AWS::ECS::Service LoadBalancer is an object. There were also other issues:
Missing DependsOn
Missing port on container
I used the template in us-east-1 using default VPC. The template will still not work as there are no container instances. But at least your original issue should be addressed.
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
SubnetA:
Default: subnet-00afd36c5eb1d367b
Type: String
SubnetB:
Default: subnet-0573cd428fe807ebc
Type: String
VpcID:
Default: vpc-040d4c42ee5a159fc
Type: String
Resources:
Albsg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: alb-sg
VpcId: !Ref VpcID
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Description: For traffic from Internet
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Description: For traffic from Internet
GroupDescription: Security Group for demo server
Alb:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
Name: Alb
Scheme: internet-facing
SecurityGroups:
- !Ref Albsg
Subnets:
- Ref: "SubnetA"
- Ref: "SubnetB"
Type: application
DefaultTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: alb-tg
VpcId: !Ref VpcID
Port: 5000
Protocol: HTTP
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref Alb
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref DefaultTargetGroup
MyCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: Flask-redis
Myservice:
Type: AWS::ECS::Service
DependsOn: LoadBalancerListener
Properties:
Cluster: !Ref MyCluster
DeploymentController:
Type: ECS
DesiredCount: 2
LaunchType: EC2
LoadBalancers:
- ContainerName: redis
ContainerPort: 5000
TargetGroupArn: !Ref DefaultTargetGroup
# Role: String
SchedulingStrategy: REPLICA
ServiceName: Python-service
TaskDefinition: !Ref Task
Task:
Type: AWS::ECS::TaskDefinition
Properties:
Family: redis-python
ContainerDefinitions:
- Essential: true
Image: redis:latest
Name: redis
PortMappings:
- ContainerPort: 5000
#HostPort: Integer
#Protocol: tcp
Cpu: .5 vCPU
# ExecutionRoleArn: !Ref Role
Memory: 0.5 GB
NetworkMode: bridge
RequiresCompatibilities:
- EC2