AWS ELB 侦听器创建失败并出现验证异常

AWS ELB Listener creation fails with Validation exception

我的 CloudFormation 堆栈创建失败并出现一个非常普遍的错误,我似乎无法弄清楚原因。

我正在使用 ALB 创建单容器 ECS 服务任务。

这是我的堆栈模板:

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

资源 LoadBalancerListener 上的 CloudFormation 堆栈创建失败,状态原因:

Invalid request provided: AWS::ElasticLoadBalancingV2::Listener Validation exception

到目前为止我还没有发现类似的问题,也不知道从哪里可以获得有关问题的更多详细信息。谢谢。

发生这种情况可能是因为您正在使用应用程序负载均衡器:

Type: application

但是,您指定连接协议是 TCP。这显然是不正确的,因为 ALB 只支持 HTTP 和 HTTPS 协议。对于 TCP,您需要 网络负载平衡器 (NLB)。

虽然上面的答案是 100% 正确的,但我只想为那些 运行 遇到同样问题的人详细说明一下。 @marcin 声明负载平衡器“类型”是“应用程序”,但“协议”是 TCP。他在这里引用了两个单独的 CF 模板对象。

创建负载均衡器时,实际上需要在CF模板中定义3个不同的对象。 “负载均衡器”、“负载均衡器侦听器”和“目标组”(负载均衡器将发送流量的位置)。

因此,如果负载均衡器的“类型”是“应用程序”,则关联的“TargetGroup”必须具有“HTTP”或“HTTPS”协议。一种类型的“TCP”会报这个错。

我遇到了同样的问题,但多亏了 cloudformation,一条错误消息总是意味着多件事。在我的情况下,这是负载均衡器上的权限错误。尝试将此权限添加到您的策略中:

Statement:
- Effect: Allow
  Action: 
    - elasticloadbalancing:*
    - elasticloadbalancingv2:*
  Resource: *

如果这解决了您的问题,您肯定知道这是弹性负载平衡的权限问题。尝试通过逐步降低权限来缩小范围。提示:一些负载平衡权限不是特定于资源的,对于那些你需要 Resource: * 才能对其执行某些操作。来自 AWS docs:

The Resource types column indicates whether each action supports resource-level permissions. If there is no value for this column, you must specify all resources ("*") in the Resource element of your policy statement. If the column includes a resource type, then you can specify an ARN of that type in a statement with that action.