Health checks failed with these codes: [502] - Cloudformation - amazon-web-services

Hi I am using cloudforamtion to create ecs cluster, service and task. In task I am simply pulling wordpress image and connecting it to rds database. The problem here is the instance in the target group goes to draining state and then turn unhealthy. Wordpress shows up in the dns of alb but when you refresh it sometime gives error 502 bad gateway. I am only attaching the template where the error can exist most probably I might be giving the port wrong. I have good connection to the database (I have checked it as I did ssh into the instance and then used mysql -umysqldb -pmysql123a -h rds.endpoint command). The targets in targetgroup shoes an error Health checks failed with these codes: [502]
Task:
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
ExRole:
Type: String
RDS:
Type: String
Resources:
Task:
Type: AWS::ECS::TaskDefinition
Properties:
Family: wordpress
Cpu: 1 vCPU
ExecutionRoleArn: !Ref ExRole
Memory: 1 GB
NetworkMode: bridge
RequiresCompatibilities:
- EC2
TaskRoleArn: !Ref ExRole
ContainerDefinitions:
- Essential: true
Image: wordpress:latest
Name: wordpress
PortMappings:
- ContainerPort: 80
HostPort: 0
Protocol: tcp
Environment:
- Name: WORDPRESS_DB_HOST
Value: !Ref RDS
- Name: WORDPRESS_DB_USER
Value: mysqldb
- Name: WORDPRESS_DB_PASSWORD
Value: mysql123a
- Name: WORDPRESS_DB_NAME
Value: mysqldb
Outputs:
Task:
Description: Contains all the task specifications
Value: !Ref Task
Export:
Name: "Task"
alb:
---
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: 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
DependsOn: Alb
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
Outputs:
Albsg:
Description: security group for application load balancer
Value: !Ref Albsg
Export:
Name: "Albsg"
Alb:
Description: application load balancer
Value: !Ref Alb
Export:
Name: "Alb"
DefaultTargetGroup:
Description: Default Target Group
Value: !Ref DefaultTargetGroup
Export:
Name: "DefaultTargetGroup"
Cluster and service
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Default: webserver
DesiredCapacity:
Type: Number
Default: 2
MinSize:
Type: Number
Default: 1
MaxSize:
Type: Number
Default: 4
InstanceProfile:
Type: String
DefaultTargetGroup:
Type: String
Task:
Type: String
Albsg:
Type: String
VpcID:
Type: String
SubnetA:
Type: String
SubnetB:
Type: String
webserver:
Type: String
Resources:
MyCluster:
Type: AWS::ECS::Cluster
Properties: {}
Myservice:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref MyCluster
DeploymentController:
Type: ECS
DesiredCount: 2
LaunchType: EC2
LoadBalancers:
- ContainerName: wordpress
ContainerPort: 80
TargetGroupArn: !Ref DefaultTargetGroup
#Role: !Ref InstanceProfile
SchedulingStrategy: REPLICA
ServiceName: wordpress
TaskDefinition: !Ref Task
ec2instance:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum update -y && yum install -y aws-cfn-bootstrap
echo ECS_CLUSTER=${MyCluster} >> /etc/ecs/ecs.config
echo ECS_BACKEND_HOST= >> /etc/ecs/ecs.config
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource myASG \
--region ${AWS::Region}
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
DeleteOnTermination: "true"
VolumeSize: 30
VolumeType: gp2
ImageId: ami-06e05a843071324d1
InstanceType: t2.small
IamInstanceProfile: !Ref InstanceProfile
KeyName: !Ref KeyName
SecurityGroups:
- Ref: webserver
myASG:
Type: AWS::AutoScaling::AutoScalingGroup
CreationPolicy:
ResourceSignal:
Timeout: PT5M
Count: !Ref DesiredCapacity
Properties:
#AutoScalingGroupName: myASG
MinSize: !Ref MinSize
MaxSize: !Ref MaxSize
DesiredCapacity: !Ref DesiredCapacity
HealthCheckGracePeriod: 300
LaunchConfigurationName:
Ref: ec2instance
VPCZoneIdentifier:
- !Ref SubnetA
- !Ref SubnetB
TargetGroupARNs:
- !Ref DefaultTargetGroup

most probably I might be giving the port wrong
In your Type: AWS::ECS::TaskDefinition you have defined port 80 for the wordpress.
But your target group is using port 8080:
Properties:
Name: alb-tg
VpcId: !Ref VpcID
Port: 8080 # <--- should be 80
Protocol: HTTP
To use 302 code for health checks:
DefaultTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
DependsOn: Alb
Properties:
Name: alb-tg
VpcId: !Ref VpcID
Port: 80
Protocol: HTTP
Matcher:
HttpCode: 302

Related

AWS Network LoadBalancer listener and the following target groups have incompatible protocols

I have run into an issue trying to setup rtmp on AWS EC2 using CloudFormation. I have two stack's aws.yaml and web.yaml. CF responds with the following error on execution: Internal error reported from downstream service during operation 'The listener and the following target groups have incompatible protocols: [arn:...]. I've tried to specify a protocol directly in the listener but this just results in the error, You cannot specify the protocol version for a target group with the 'TCP_UDP' protocol. Thanks in advance for help!
nlb.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Deploys a single network load balancer
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
Description: ID of the VPC
PublicSubnets:
Type: List<AWS::EC2::Subnet::Id>
Description: List of Public subnets to use for the Load Balancer
CertificateArn:
Type: String
Description: Arn of the ACM certificate to be used by the load balancer listener.
Resources:
PublicNlb:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
Name: publicNlb
Scheme: internet-facing
Subnets: !Ref PublicSubnets
Tags:
- Key: Name
Value: wordpress-nlb
Type: network
PublicNlbTargetGroupHttp:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Port: 80
Protocol: TCP
Targets:
- Id: !ImportValue WordPressPublicAlbArn
TargetType: alb
VpcId: !Ref VpcId
PublicNlbTargetGroupHttps:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Port: 443
Protocol: TCP
Targets:
- Id: !ImportValue WordPressPublicAlbArn
TargetType: alb
VpcId: !Ref VpcId
PublicNlbHttpListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref PublicNlbTargetGroupHttp
LoadBalancerArn: !Ref PublicNlb
Port: 80
Protocol: TCP
PublicNlbHttpsListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref PublicNlbTargetGroupHttps
LoadBalancerArn: !Ref PublicNlb
Port: 443
Protocol: TCP
Outputs:
PublicNlbTargetGroupHttpArn:
Value: !Ref PublicNlbTargetGroupHttp
Export:
Name: WordPressPublicNlbTargetGroupHttpArn
PublicNlbTargetGroupHttpsArn:
Value: !Ref PublicNlbTargetGroupHttps
Export:
Name: WordPressPublicNlbTargetGroupHttpsArn
PublicNlbCanonicalHostedZoneId:
Value: !GetAtt PublicNlb.CanonicalHostedZoneID
PublicNlbDnsName:
Value: !GetAtt PublicNlb.DNSName
PublicNlbFullName:
Value: !GetAtt PublicNlb.LoadBalancerFullName
PublicNlbHostname:
Value:
!Sub https://${PublicNlb.DNSName}
# !If [ NoSslCertificate, !Join [ '', [ 'http://', !GetAtt PublicAlb.DNSName ] ], !Join [ '', [ 'https://', !GetAtt PublicAlb.DNSName ] ] ]
PublicNlbHttpsListenerArn:
Value: !Ref PublicNlbHttpsListener
Export:
Name: WordPressPublicNlbHttpsListenerArn
PublicNlbHttpListenerArn:
Value: !Ref PublicNlbHttpListener
Export:
Name: WordPressPublicNlbHttpListenerArn
web.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: Deploys highly available wordpress application
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
Description: ID of the VPC
RecipeVersion:
Type: String
Description: The semantic version number you want to give to the recipe (in Major.Minor.Patch format).
AllowedPattern: ^[0-9]+\.[0-9]+\.[0-9]+$
PrivateSubnets:
Type: List<AWS::EC2::Subnet::Id>
Description: List of Private subnets to use for the application
PrivateSubnetsString:
Type: String
Description: List of Private subnets to use for the application as string
Account:
Type: String
Default: non-prod
AllowedValues:
- prod
- non-prod
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- preprod
- prod
InstanceProfileName:
Type: String
Default: EC2RoleForSSM
Description: The name of the InstanceProfile to be used with the instances.
AmazonLinuxAMI:
Type: AWS::EC2::Image::Id
MinSize:
Type: Number
Description: The minimum limit of allowed instances to be deployed.
Default: 1
MaxSize:
Type: Number
Description: The maximum limit of allowed instances to be deployed.
Default: 8
DesiredCapacity:
Type: Number
Description: The average amount of instances to be deployed.
Default: 1
OnDemandBaseCapacity:
Type: Number
Description: The minimum amount of the Auto Scaling group's capacity that must be fulfilled by On-Demand Instances. For production you should always have at least 1 On-Demand instance (set to 1).
Default: 1
OnDemandPercentageAboveBaseCapacity:
Type: Number
Description: Controls the percentages of On-Demand Instances and Spot Instances for your additional capacity beyond OnDemandBaseCapacity. Expressed as a number (for example, 20 specifies 20% On-Demand Instances, 80% Spot Instances). Defaults to 0 if not specified. If set to 100, only On-Demand Instances are provisioned.
Default: 0
Mappings:
LoadBalancerRulePriority:
dev:
"rule": "3"
preprod:
"rule": "2"
prod:
"rule": "1"
LoadBalancerHosts:
dev:
hostOne: "*.example.*"
preprod:
hostOne: "preprod.example.*"
prod:
hostOne: "*.example.*"
SalingServerProperties:
# #link https://aws.amazon.com/ec2/instance-types/
# #link https://instaguide.io/#sortField=vcpu&sortDir=-1&platform=rhel&tenancyCode=dedicated&priceCalc=abs&period=mo
dev:
instanceTypeOne: "c6gd.xlarge"
preprod:
instanceTypeOne: "c6gd.xlarge"
prod:
instanceTypeOne: "c6gd.xlarge"
Conditions:
IsProd: !Equals [!Ref Environment, prod]
IsPreProd: !Equals [!Ref Environment, preprod]
IsDev: !Equals [!Ref Environment, dev]
Resources:
AlbTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub "${Environment}-wordpress"
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 10
HealthCheckPath: /
HealthCheckPort: "80"
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 4
UnhealthyThresholdCount: 2
Port: 80
Protocol: HTTP
ProtocolVersion: HTTP1
Tags:
- Key: Name
Value: !Sub "${Environment}-${RecipeVersion}-wordpress"
TargetGroupAttributes:
- Key: stickiness.enabled
Value: "false"
- Key: stickiness.type
Value: lb_cookie # or app_cookie
TargetType: instance
VpcId: !Ref VpcId
AlbListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref AlbTargetGroup
Conditions:
- Field: host-header
HostHeaderConfig:
Values:
- dropingaming.*
- !FindInMap [ LoadBalancerHosts, !Ref Environment, hostOne ]
ListenerArn: !ImportValue WordPressPublicAlbHttpsListenerArn
Priority: !FindInMap [ LoadBalancerRulePriority, !Ref Environment, rule ]
NlbTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub "${Environment}-wordpress-rtmp"
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPort: "4444"
HealthCheckProtocol: HTTP
Port: 1935
Protocol: TCP_UDP
Tags:
- Key: Name
Value: !Sub "${Environment}-${RecipeVersion}-wordpress"
TargetGroupAttributes:
- Key: stickiness.enabled
Value: "true"
TargetType: instance
VpcId: !Ref VpcId
NlbListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref NlbTargetGroup
Conditions:
# Configures the rule to apply when the host header matches the domain we want to send to the target group
# https://stackoverflow.com/questions/45664638/how-to-make-a-list-item-conditional-in-cloud-formation-template
- Field: host-header
HostHeaderConfig:
Values:
- dropingaming.*
- !FindInMap [ LoadBalancerHosts, !Ref Environment, hostOne ]
ListenerArn: !ImportValue WordPressPublicAlbHttpsListenerArn
Priority: !FindInMap [ LoadBalancerRulePriority, !Ref Environment, rule ]
LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: !Sub "${Environment}-wordpress"
LaunchTemplateData:
ImageId: !Ref AmazonLinuxAMI
EbsOptimized: 'true'
IamInstanceProfile:
Name: EC2RoleForSSM
SecurityGroupIds:
- !ImportValue WordPressEc2SecurityGroupId
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html
# The user data to make available to the instance. You must provide base64-encoded text.
# User data is limited to 16 KB. For more information, see Running Commands on Your Linux Instance at Launch (Linux) or Adding User Data (Windows).
# logging is sent to :: /var/log/cloud-init-output.log
# this script is stored to :: /var/lib/cloud/instance/scripts/part-001
UserData:
Fn::Base64: !Sub
- |
#!/bin/bash -ex
EC2_INSTANCE_ID="`wget -q -O - http://instance-data/latest/meta-data/instance-id || die \"wget instance-id has failed: $?\"`"
test -n "$EC2_INSTANCE_ID" || die 'cannot obtain instance-id'
EC2_AVAIL_ZONE="`wget -q -O - http://instance-data/latest/meta-data/placement/availability-zone || die \"wget availability-zone has failed: $?\"`"
test -n "$EC2_AVAIL_ZONE" || die 'cannot obtain availability-zone'
EC2_REGION="`echo \"$EC2_AVAIL_ZONE\" | sed -e 's:\([0-9][0-9]*\)[a-z]*\$:\\1:'`"
EC2_PUBLIC_IPV4="`curl http://checkip.amazonaws.com`"
EC2_PRIVATE_IPV4="`curl http://169.254.169.254/latest/meta-data/local-ipv4`"
# https://tldp.org/LDP/abs/html/here-docs.html
sudo cat > '/var/ebs-www-copy/aws.json' <<End-of-message
{
"AmazonLinuxAMI": "${AmazonLinuxAMI}",
"RecipeVersion": "${RecipeVersion}",
"EfsId": "${EfsId}",
"VpcId": "${VpcId}",
"PrivateSubnets": "${PrivateSubnetsString}",
"Account": "${Account}",
"Environment": "${Environment}",
"InstanceProfileName": "${InstanceProfileName}",
"MinSize": "${MinSize}",
"MaxSize": "${MaxSize}",
"DesiredCapacity": "${DesiredCapacity}",
"OnDemandBaseCapacity": "${OnDemandBaseCapacity}",
"OnDemandPercentageAboveBaseCapacity": "${OnDemandPercentageAboveBaseCapacity}",
"EC2_PUBLIC_IPV4": "$EC2_PUBLIC_IPV4",
"EC2_PRIVATE_IPV4": "$EC2_PRIVATE_IPV4",
"EC2_INSTANCE_ID": "$EC2_INSTANCE_ID",
"EC2_AVAIL_ZONE": "$EC2_AVAIL_ZONE",
"EC2_REGION": "$EC2_REGION"
}
End-of-message
cat /var/ebs-www-copy/aws.json
# redacting the overly specific :)
systemctl start httpd
- EfsId: !ImportValue "WordPressEfsId"
# https://github.com/aws-samples/session-manager-without-igw/blob/main/session-manager-without-igw.yml
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AutoScalingGroupName: !Sub "${Environment}-wordpress"
TargetGroupARNs:
- !Ref AlbTargetGroup
- !Ref NlbTargetGroup
MinSize: !Ref MinSize
MaxSize: !Ref MaxSize
DesiredCapacity: !Ref DesiredCapacity
VPCZoneIdentifier: !Ref PrivateSubnets
MixedInstancesPolicy:
LaunchTemplate:
LaunchTemplateSpecification:
# Version: !Ref LaunchTemplateVersionNumber
Version: !GetAtt
- LaunchTemplate
- LatestVersionNumber
LaunchTemplateId: !Ref LaunchTemplate
# https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-mixed-instances-groups-launch-template-overrides.html
# #link https://aws.amazon.com/ec2/instance-types/
# #link https://instaguide.io/#sortField=vcpu&sortDir=-1&platform=rhel&tenancyCode=dedicated&priceCalc=abs&period=mo
Overrides:
# I want to know if predictive load b is bs or nah
- InstanceType: !FindInMap [SalingServerProperties, !Ref Environment, instanceTypeOne]
InstancesDistribution:
OnDemandBaseCapacity: !Ref OnDemandBaseCapacity
OnDemandPercentageAboveBaseCapacity: !Ref OnDemandPercentageAboveBaseCapacity
# https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-mixed-instances-groups.html#allocation-strategies
SpotAllocationStrategy: lowest-price
OnDemandAllocationStrategy: lowest-price
Tags:
- Key: "Name"
PropagateAtLaunch: true
Value: !Sub "${Environment}-wordpress"
- Key: "Version"
PropagateAtLaunch: true
Value: !Sub "${RecipeVersion}"
AutoScalingPolicy:
Type: AWS::AutoScaling::ScalingPolicy
Properties:
AutoScalingGroupName: !Ref AutoScalingGroup
PolicyType: PredictiveScaling
PredictiveScalingConfiguration:
MetricSpecifications:
- TargetValue: 70
PredefinedMetricPairSpecification:
PredefinedMetricType: ASGCPUUtilization
So based on the error the NlbListenerRule seems to be what is failing; though, the downstream service bit has me confused. Google return near nothing, so I'm hopeful you may know!?
So AWS support along with the comment above lead me straight to the problem. The NlbListenerRule was using an incorrect ListenerArn: !ImportValue WordPressPublicAlbHttpsListenerArn. Also, another issues which is catchable in the provided templates above was caught by the support team "NLB work on Layer-4 of OSI Model , and we cannot create NLB Listener rule based on Host-Header Condition." Thus ListenerRule's may only be applied to HTTP based hosts.
changed in web.yaml
NlbListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref NlbTargetGroup
LoadBalancerArn: !ImportValue PublicNlbLoadBalancerArn
Port: 1935
Protocol: TCP_UDP
added in alb.yaml
Outputs:
PublicNlb:
Value: !Ref PublicNlb
Export:
Name: PublicNlbLoadBalancerArn
PublicNlbTargetGroupHttpArn:

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.

Unable to create Ec2 instance with autoscaling and register them to ECS cluster

Hi I am trying to create a cluster with service and task. I have a python app in Ecr that connects to redis container. The issue is I am unable to create ec2 instance with autoscaling. Myservice in Cluster and Autoscaling doesn't builds.
Cluster:
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Alb:
Type: String
DefaultTargetGroup:
Type: String
ECSServiceRole:
Type: String
Task:
Type: String
Resources:
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:
- ContainerName: python
ContainerPort: 5000
TargetGroupArn: !Ref DefaultTargetGroup
Role: !Ref ECSServiceRole
SchedulingStrategy: REPLICA
ServiceName: Python-service
TaskDefinition: !Ref Task
Autoscaling:
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
SubnetA:
Type: String
SubnetB:
Type: String
VpcID:
Type: String
Albsg:
Type: String
Alb:
Type: String
ECSServiceRole:
Type: String
Resources:
wahajwebserver:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: wahaj-webserver
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref Albsg
Description: For traffic from Internet
GroupDescription: Security Group for demo server
VpcId: !Ref VpcID
ec2instance:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
# UserData:
# Fn::Base64: !Sub |
# #!/bin/bash -xe
# echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
# yum install -y aws-cfn-bootstrap
# /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
DeleteOnTermination: "true"
VolumeSize: "8"
VolumeType: gp2
ImageId: ami-0bdcc6c05dec346bf
InstanceType: t2.small
IamInstanceProfile: !Ref ECSServiceRole
KeyName: wahaj(webserver)
SecurityGroups:
- Ref: wahajwebserver
myASG:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AvailabilityZones:
- "us-east-2a"
- "us-east-2b"
AutoScalingGroupName: myASG
LoadBalancerNames:
- Ref: Alb
MinSize: "2"
MaxSize: "2"
DesiredCapacity: "2"
HealthCheckGracePeriod: 300
LaunchConfigurationName:
Ref: ec2instance
VPCZoneIdentifier:
- Ref: "SubnetA"
- Ref: "SubnetB"
Task:
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
ExRole:
Type: String
Resources:
Task:
Type: AWS::ECS::TaskDefinition
Properties:
Family: redis-python
Cpu: 1 vCPU
ExecutionRoleArn: !Ref ExRole
Memory: 1 GB
NetworkMode: bridge
RequiresCompatibilities:
- EC2
TaskRoleArn: !Ref ExRole
ContainerDefinitions:
- Essential: true
Image: redis:latest
Name: redis
- Essential: true
Image: 021146125185.dkr.ecr.us-east-2.amazonaws.com/python-app:latest
Name: python
PortMappings:
- ContainerPort: 5000
HostPort: 0
Protocol: tcp
DependsOn:
- Condition: START
ContainerName: redis
Links:
- redis
Outputs:
Task:
Description: Contains all the task specifications
Value: !Ref Task
Export:
Name: "Task"
Application Load balancer:
---
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
DependsOn: Alb
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
Outputs:
Albsg:
Description: security group for application load balancer
Value: !Ref Albsg
Export:
Name: "Albsg"
Alb:
Description: application load balancer
Value: !Ref Alb
Export:
Name: "Alb"
DefaultTargetGroup:
Description: Default Target Group
Value: !Ref DefaultTargetGroup
Export:
Name: "DefaultTargetGroup"
role:
---
AWSTemplateFormatVersion: 2010-09-09
Resources:
ECSServiceRole:
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: ['elasticloadbalancing:DeregisterInstancesFromLoadBalancer', 'elasticloadbalancing:DeregisterTargets',
'elasticloadbalancing:Describe*', 'elasticloadbalancing:RegisterInstancesWithLoadBalancer',
'elasticloadbalancing:RegisterTargets', 'ec2:Describe*', 'ec2:AuthorizeSecurityGroupIngress']
Resource: '*'
ExRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ecs-tasks.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Policies:
- PolicyName: AccessECR
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ecr:BatchGetImage
- ecr:GetAuthorizationToken
- ecr:GetDownloadUrlForLayer
Resource: '*'
Outputs:
ExRole:
Description: Task excution role
Value: !Ref ExRole
Export:
Name: "ExRole"
ECSServiceRole:
Description: application load balancer
Value: !Ref ECSServiceRole
Export:
Name: "ECSServiceRole"
I am unable to create Ec2 instance with autoscaling and register them to ECS cluster. Any help would be appreciated.
Since you haven't provided any error messages, the initial look at Autoscaling template shows several issues.
LoadBalancerNames
LoadBalancerNames:
- Ref: Alb
This is only for CLB, but you are using ALB. For ALB you should be using TargetGroupARNs parameter.
UserData
You commented out the UserData. Not sure why? It should be there as you should register the instance with the cluster. I guess due to mistakes? see below.
cfn-signal
In the UserData, you are using --resource ECSAutoScalingGroup. But it should be --resource myASG
ASG and creation policy
cfn-signal has no effect as your ASG is missing CreationPolicy.
ECSCluster
Again in the UserData: reference to ECSCluster is not defined.
ImageId
Just by looking at ami-0bdcc6c05dec346bf I'm not sure if this is ECS optimized AMI. This have to be checked.
ECSServiceRole
Its form is not shown. Could be incorrect or even fully missing.
Update and fixed template
Upon further examination many more issues were found. Just to name few:
missing instance profile
missing/wrong container instance role
incorrect security groups
Not using ImportValue
Missing some output exports
The fixed and modified templates was tested in us-east-1 and default VPC. It will not work in any other region unless AMI is adjusted. Also due to lack of your ECR image, I had to create my own with my own ports, so I also had to modify this as well to even attempt a verification.
roles
---
AWSTemplateFormatVersion: 2010-09-09
Resources:
ExRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- ecs-tasks.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Policies:
- PolicyName: AccessECR
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ecr:BatchGetImage
- ecr:GetAuthorizationToken
- ecr:GetDownloadUrlForLayer
Resource: '*'
ContainerInstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal: {'Service': ['ec2.amazonaws.com']}
Action: ['sts:AssumeRole']
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
Path: '/'
InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref ContainerInstanceRole
Outputs:
ExRole:
Description: Task excution role
Value: !Ref ExRole
Export:
Name: "ExRole"
InstanceProfile:
Description: profile for container instances
Value: !Ref InstanceProfile
Export:
Name: "InstanceProfile"
alb
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
SubnetA:
Type: AWS::EC2::Subnet::Id
SubnetB:
Type: AWS::EC2::Subnet::Id
VpcID:
Type: AWS::EC2::VPC::Id
Resources:
Albsg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: alb-sg
VpcId: !Ref VpcID
SecurityGroupIngress:
- 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
DependsOn: Alb
Properties:
Name: alb-tg
VpcId: !Ref VpcID
Port: 8080
Protocol: HTTP
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref Alb
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref DefaultTargetGroup
Outputs:
Albsg:
Description: security group for application load balancer
Value: !Ref Albsg
Export:
Name: "Albsg"
Alb:
Description: application load balancer
Value: !Ref Alb
Export:
Name: "Alb"
DefaultTargetGroup:
Description: Default Target Group
Value: !Ref DefaultTargetGroup
Export:
Name: "DefaultTargetGroup"
SubnetA:
Value: !Ref SubnetA
Export:
Name: "SubnetA"
SubnetB:
Value: !Ref SubnetB
Export:
Name: "SubnetB"
VpcID:
Value: !Ref VpcID
Export:
Name: "VpcID"
task
---
AWSTemplateFormatVersion: 2010-09-09
Resources:
Task:
Type: AWS::ECS::TaskDefinition
Properties:
Family: redis-python
Cpu: 1 vCPU
ExecutionRoleArn: !ImportValue ExRole
Memory: 1 GB
NetworkMode: bridge
RequiresCompatibilities:
- EC2
TaskRoleArn: !ImportValue ExRole
ContainerDefinitions:
- Essential: true
Image: redis:latest
Name: redis
- Essential: true
Image: xxxxxx.dkr.ecr.us-east-1.amazonaws.com/xxxxxx:latest
Name: python
PortMappings:
- ContainerPort: 8080
#HostPort: 0
Protocol: tcp
DependsOn:
- Condition: START
ContainerName: redis
Links:
- redis
Outputs:
Task:
Description: Contains all the task specifications
Value: !Ref Task
Export:
Name: "Task"
service_and_asg
---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Default: wahajwebserver
DesiredCapacity:
Type: Number
Default: 2
MinSize:
Type: Number
Default: 1
MaxSize:
Type: Number
Default: 4
Resources:
MyCluster:
Type: AWS::ECS::Cluster
Properties: {}
wahajwebserver:
Type: AWS::EC2::SecurityGroup
Properties:
#GroupName: wahaj-webserver
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
SourceSecurityGroupId: !ImportValue Albsg
Description: For traffic from Internet
GroupDescription: Security Group for demo server
VpcId: !ImportValue VpcID
Myservice:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref MyCluster
DeploymentController:
Type: ECS
DesiredCount: 2
LaunchType: EC2
LoadBalancers:
- ContainerName: python
ContainerPort: 8080
TargetGroupArn: !ImportValue DefaultTargetGroup
#Role: !Ref ECSServiceRole
SchedulingStrategy: REPLICA
#ServiceName: Python-service
TaskDefinition: !ImportValue Task
ec2instance:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
yum update -y && yum install -y aws-cfn-bootstrap
echo ECS_CLUSTER=${MyCluster} >> /etc/ecs/ecs.config
echo ECS_BACKEND_HOST= >> /etc/ecs/ecs.config
/opt/aws/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource myASG \
--region ${AWS::Region}
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
DeleteOnTermination: "true"
VolumeSize: 30
VolumeType: gp2
ImageId: ami-07a63940735aebd38 # before ami-0bdcc6c05dec346bf
InstanceType: t2.small
IamInstanceProfile: !ImportValue InstanceProfile
KeyName: !Ref KeyName
SecurityGroups:
- Ref: wahajwebserver
myASG:
Type: AWS::AutoScaling::AutoScalingGroup
CreationPolicy:
ResourceSignal:
Timeout: PT5M
Count: !Ref DesiredCapacity
Properties:
#AutoScalingGroupName: myASG
MinSize: !Ref MinSize
MaxSize: !Ref MaxSize
DesiredCapacity: !Ref DesiredCapacity
HealthCheckGracePeriod: 300
LaunchConfigurationName:
Ref: ec2instance
VPCZoneIdentifier:
- !ImportValue SubnetA
- !ImportValue SubnetB
TargetGroupARNs:
- !ImportValue DefaultTargetGroup
Screenshots showing an ECS cluster with two tasks and 2 tasks (1 task on each instance)

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