My CloudFormation stack creation fails with a very generic error and I can't seem to figure out why.
I'm creating a single-container ECS service task with ALB.
Here's my stack template:
AWSTemplateFormatVersion: '2010-09-09'
Description: Services Containers
Parameters:
VpcId:
Type: String
Default: vpc-4796bd23
SubnetId:
Type: String
Default: subnet-f4701ff8
ELBSecondarySubnetId:
Type: String
Default: subnet-8a453cef
ECSCluster:
Type: String
Default: dev-ecs
EcsSecurityGroup:
Type: String
Default: sg-74cb7b0c
Color:
Type: String
AllowedValues: ['blue', 'green']
Description: The deployment color
Default: 'blue'
BuildVersion:
Type: String
Description: The build version to deploy
ComPublic:
Type: String
Description: Hosted Zone ID
Default: Z00669325SSURKTK4ZPA
MQPort:
Type: Number
Description: MQ Connectivity port
Default: 5672
Resources:
ApiLogsGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Join ['-', [ path-services-api, !Ref Color ]]
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
ContainerDefinitions:
- Essential: True
Image: ***.dkr.ecr.us-east-1.amazonaws.com/path-services/path-services-api
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref ApiLogsGroup
awslogs-region: us-east-1
awslogs-stream-prefix: !Ref BuildVersion
Name: path-services-api
PortMappings:
- ContainerPort: !Ref MQPort
Protocol: tcp
ExecutionRoleArn: arn:aws:iam::***:role/ecs-task-execution-role
Family: path-services-api
NetworkMode: awsvpc
Cpu: 4096
Memory: 8192 # max
RequiresCompatibilities:
- FARGATE
TaskRoleArn: !Ref ServiceTaskRole
ServiceTaskRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ['ecs-tasks.amazonaws.com', 'ecs.amazonaws.com']
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: !Join ['-', [path-services, !Ref Color, read-secrets]]
PolicyDocument:
Statement:
- Effect: Allow
Action:
- 'secretsmanager:ListSecrets'
- 'secretsmanager:DescribeSecret'
- 'secretsmanager:GetRandomPassword'
- 'secretsmanager:GetResourcePolicy'
- 'secretsmanager:GetSecretValue'
- 'secretsmanager:ListSecretVersionIds'
Resource: [ 'arn:aws:secretsmanager:us-east-1:***:secret:prod/path-services*' ]
PathService:
Type: AWS::ECS::Service
DependsOn: LoadBalancerListener
Properties:
Cluster: !Ref ECSCluster
DesiredCount: 1
LaunchType: FARGATE
LoadBalancers:
- ContainerName: path-services-api
ContainerPort: !Ref MQPort
TargetGroupArn: !Ref TargetGroup
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- !Ref EcsSecurityGroup
Subnets:
- !Ref SubnetId
PropagateTags: SERVICE
ServiceName: !Join ['-', [ path-services-api, !Ref Color ] ]
TaskDefinition: !Ref TaskDefinition
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckPort: !Ref MQPort
HealthCheckProtocol: TCP
Port: !Ref MQPort
Protocol: TCP
TargetType: ip
VpcId: !Ref VpcId
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
LoadBalancerAttributes:
- Key: routing.http2.enabled
Value: false
Scheme: internet-facing
SecurityGroups:
- !Ref EcsSecurityGroup
Subnets:
- !Ref SubnetId
- !Ref ELBSecondarySubnetId
Type: application
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref TargetGroup
LoadBalancerArn: !Ref ApplicationLoadBalancer
Port: !Ref MQPort
Protocol: TCP
ServiceScalingPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
DependsOn: PathService
Properties:
PolicyName: !Join ['-', [ path-services-api, !Ref Color, scaling-policy ] ]
PolicyType: TargetTrackingScaling
ResourceId: !Join [ '/', [ service, !Ref ECSCluster, !Join ['-', [ path-services-api, !Ref Color ] ] ] ]
ScalableDimension: ecs:service:DesiredCount
ServiceNamespace: ecs
TargetTrackingScalingPolicyConfiguration:
PredefinedMetricSpecification:
PredefinedMetricType: ECSServiceAverageCPUUtilization
ScaleInCooldown: 30
ScaleOutCooldown: 30
TargetValue: 70.0
# Route53Record:
# Type: AWS::Route53::RecordSet
# Properties:
# HostedZoneId: !Ref ComPublic
# Name: ***
# AliasTarget:
# DNSName: ApplicationLoadBalancer.DNSName
# HostedZoneId: !GetAtt ApplicationLoadBalancer.CanonicalHostedZoneI
# TTL: 600
# Type: A
ServiceCpuAlarm:
Type: AWS::CloudWatch::Alarm
DependsOn: PathService
Properties:
AlarmActions:
- !Ref ServiceAlarmTopic
OKActions:
- !Ref ServiceAlarmTopic
ComparisonOperator: GreaterThanOrEqualToThreshold
DatapointsToAlarm: 1
Dimensions:
- Name: Service
Value: !GetAtt PathService.Name
EvaluationPeriods: 1
MetricName: CPUUtilization
Namespace: AWS/ECS
Period: 60
Statistic: Maximum
Threshold: 90
TreatMissingData: notBreaching
ServiceMemoryAlarm:
Type: AWS::CloudWatch::Alarm
DependsOn: PathService
Properties:
AlarmActions:
- !Ref ServiceAlarmTopic
OKActions:
- !Ref ServiceAlarmTopic
ComparisonOperator: GreaterThanOrEqualToThreshold
DatapointsToAlarm: 1
Dimensions:
- Name: Service
Value: !GetAtt PathService.Name
EvaluationPeriods: 1
MetricName: MemoryUtilization
Namespace: AWS/ECS
Period: 60
Statistic: Maximum
Threshold: 90
TreatMissingData: notBreaching
ServiceAlarmTopic:
Type: AWS::SNS::Topic
DependsOn: PathService
Properties:
TopicName: path-services-api-alarm-topic
Subscription:
- Endpoint: ***
Protocol: email
- Endpoint: ***
Protocol: email
CloudFormation stack creation fails on resource LoadBalancerListener
with status reason:
Invalid request provided: AWS::ElasticLoadBalancingV2::Listener Validation exception
I've found no similar issue so far and don't know where to get more details about what's wrong. Thank you.
This happens probably because you are using application load balancer:
Type: application
However, you specify that your connection protocol is TCP
. This is obviously incorrect, as ALB only supports HTTP and HTTPS protocols. For TCP you need network load balancer (NLB).