Search code examples
amazon-web-servicesaws-cloudformationamazon-ecsaws-fargateaws-application-load-balancer

AWS ELB Listener creation fails with Validation exception


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.


Solution

  • 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).