将ECS服务转换为cloudformation

Lui*_*uin 1 amazon-web-services amazon-ecs aws-cloudformation aws-fargate aws-cloudformation-custom-resource

我正在尝试将手动创建的服务转换为 cloudformation 模板,但我不断收到错误。

任务定义已使用 UI 创建,因为它需要一些特定角色

这个模板给了我: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
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

在此输入图像描述

在此输入图像描述

在此输入图像描述

在此输入图像描述

在此输入图像描述

更新:这是修改后的完整云信息模板,没有负载均衡器名称,如一些评论所明确的

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}
Run Code Online (Sandbox Code Playgroud)

现在我收到“带有 targetGroupArn arn:aws:elasticloadbalancing: ... :targetgroup/pouch-Targe-XFJ4AI7HCF6G/f2a665925da27326 的目标组没有关联的负载均衡器”

Cal*_*zar 5

来自AWS官方文档

LoadBalancerName 与 Amazon ECS 服务或任务集关联的负载均衡器的名称。

仅当使用 Classic Load Balancer 时才指定负载均衡器名称。如果您使用应用程序负载均衡器或网络负载均衡器,则应省略负载均衡器名称参数。

这意味着您不应在 CloudFormation 模板中指定负载均衡器的名称,因为您使用的是 Fargate,因此,不要使用经典负载均衡器。

另外,在你的位置,我会考虑使用类似Former2的东西。这是一个很棒的工具,可以为您生成CloudFormation模板。您可以扫描您的帐户,选择要为其创建模板的服务。不过,为了使用它,您需要访问密钥和秘密密钥,因此请考虑创建具有只读权限的 IAM 用户。

编辑以覆盖有关目标组的第二个错误:

Amazon ECS 服务需要显式依赖于 Application Load Balancer 侦听器规则和 Application Load Balancer 侦听器。这可以防止服务在侦听器准备就绪之前启动。

在将目标组添加到负载均衡器之前,可能会AWS::ECS::Service尝试附加到目标组。为了解决这个问题,您应该在服务中添加依赖项,如下所示:

Type: AWS::ECS::Service
DependsOn: Listener       # Add exact listener name, depending on the service
Properties:
Run Code Online (Sandbox Code Playgroud)

这应该有助于解决问题。