Search code examples
amazon-web-servicesaws-cloudformationamazon-ecsaws-ecs

AWS ECS: LoadBalancers property error in ECSService CloudFormation resource definition


Trying to create an ECS Service using the following Cloudformation resource definition:

  MyUIService:
    Type: AWS::ECS::Service
    Properties:
      Cluster: !ImportValue MyClusterName
      DesiredCount: 1
      LaunchType: EC2
      LoadBalancers:
        - !ImportValue ALBDemo
      Role: !Ref MyServiceRole
      ServiceName: my-ui-service
      ServiceRegistries:
       - arn:aws:servicediscovery:eu-west-1:2398942890842:service/srv-ohc098mdj55yesez7
      TaskDefinition: !ImportValue MyTaskArn

However it fails with the following error:

Value of property LoadBalancers must be a list of objects

But I am defining a list (albeit with one element).

The list contains an export of the ALB's arn.

What is the exact syntax?

edit: Here is the relevant documentation that does not seem consistent with the error:

LoadBalancers

A list of load balancer objects to associate with the cluster. If you specify the Role property, LoadBalancers must be specified as well. For information about the number of load balancers that you can specify per service, see Service Load Balancing in the Amazon Elastic Container Service Developer Guide. Required: Conditional Type: List of Amazon Elastic Container Service Service LoadBalancers


Solution

  • I see that you copied the same template from AWS templates.

    MyUIService:
      Type: AWS::ECS::Service
      Properties:
        Cluster: !ImportValue MyClusterName
        DesiredCount: 1
        LaunchType: EC2
        LoadBalancers:
          - ContainerName: simple-app
            ContainerPort: '80'
            TargetGroupArn: !Ref 'ECSTG'
        Role: !Ref MyServiceRole
        ServiceName: my-ui-service
        ServiceRegistries:
         - arn:aws:servicediscovery:eu-west-1:2398942890842:service/srv-ohc098mdj55yesez7
        TaskDefinition: !ImportValue MyTaskArn
    

    Note that LoadBalancers does not really directly reference the load balancer. It references the target group. This is quite weird given the naming but if you go through the web console you will reach the same conclusion.

    If you look at AWS documentation:

    ContainerName
    The name of a container to use with the load balancer.
    
    Required: Yes
    
    Type: String
    
    
    ContainerPort
    The port number on the container to direct load balancer traffic to. Your container instances must allow ingress traffic on this port.
    
    Required: Yes
    
    Type: Integer
    

    These are Required but you can never get them by importing a load balancer.

    If you think about it, by referencing a target group instead of a load balancer, you can share the same ALB for multiple target groups which is good for cost. So in conclusion it makes sense to reference the target group but the property name is misleading indeed.