Mark de Haan
Mark de Haan

Reputation: 33

AWS CDK setting a second listener + target ignores the target port

I have an ECS container which runs two endpoints on two different ports. I configure a network load balancer infront of it to have two listeners, each with their own target group.

AWS CDK code for my stack is here (Note: I changed the construct in my example)

class MyStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, certificate: Certificate, vpc: Vpc, repository: Repository, subnets: SubnetSelection, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

      cluster: Cluster = Cluster(self, "MyCluster", vpc=vpc, container_insights=True)
      image: ContainerImage = ContainerImage.from_ecr_repository(repository=repository, tag="latest")
    
      task_definition: FargateTaskDefinition = FargateTaskDefinition(
            self, "MyTaskDefinition", cpu=512, memory_limit_mib=1024,
      )

      container: ContainerDefinition = task_definition.add_container(
            "MyContainer", image=image, environment={}
      )

      # As you can see, here I add two port mappings on my container
      container.add_port_mappings(PortMapping(container_port=9876, host_port=9876))
      container.add_port_mappings(PortMapping(container_port=8000, host_port=8000))

      load_balancer: NetworkLoadBalancer = NetworkLoadBalancer(
        self, "MyNetworkLoadBalancer",
        load_balancer_name="my-nlb",
        vpc=vpc,
        vpc_subnets=subnets,
        internet_facing=False
      )

      security_group: SecurityGroup = SecurityGroup(
        self, "MyFargateServiceSecurityGroup",
        vpc=vpc,
        allow_all_outbound=True,
        description="My security group"
      )

      security_group.add_ingress_rule(
        Peer.any_ipv4(), Port.tcp(9876), 'Allow a connection on port 9876 from anywhere'
      )
      security_group.add_ingress_rule(
        Peer.any_ipv4(), Port.tcp(8000), "Allow a connection on port 8000 from anywhere"
      )

      service: FargateService = FargateService(
        self, "MyFargateService",
        cluster=cluster,
        task_definition=task_definition,
        desired_count=1,
        health_check_grace_period=Duration.seconds(30),
        vpc_subnets=subnets,
        security_groups=[security_group]
      )

      # Listener 1 is open to incoming connections on port 9876
      listener_9876: NetworkListener = load_balancer.add_listener(
        "My9876Listener",
        port=9876,
        protocol=Protocol.TLS,
        certificates=[ListenerCertificate(certificate.certificate_arn)],
        ssl_policy=SslPolicy.TLS12_EXT
      )

      # Incoming connections on 9876 are redirected to the container on 9876
      # A health check is done on 8000/health
      listener_9876.add_targets(
        "My9876TargetGroup", targets=[service], port=9876, protocol=Protocol.TCP,
        health_check=HealthCheck(port="8000", protocol=Protocol.HTTP, enabled=True, path="/health")
      )

      # Listener 2 is open to incoming connections on port 443
      listener_443: NetworkListener = load_balancer.add_listener(
        "My443Listener",
        port=443,
        protocol=Protocol.TLS,
        certificates=[ListenerCertificate(certificates.quickfix_certificate.certificate_arn)],
        ssl_policy=SslPolicy.TLS12_EXT
      )

      # Incoming connections on 443 are redirected to the container on 8000
      # A health check is done on 8000/health
      listener_443.add_targets(
        "My443TargetGroup", targets=[service], port=8000, protocol=Protocol.TCP,
        health_check=HealthCheck(port="8000", protocol=Protocol.HTTP, enabled=True, path="/health")
      )

Now I deploy this stack successfully, but the result is not what I expected

Two target groups directing traffic to my container, but both on port 9876

Two target groups directing traffic to my container, but both on port 9876.

I read in the documentation that it is possible to have a load balancer direct traffic to different ports via different target groups.

Am I doing something wrong? Or does AWS CDK not support this?

I double checked the synthesized cloudformation template. It properly generates two target groups, one with port 9876 and one with port 8000.

Upvotes: 0

Views: 1447

Answers (1)

Tugay Karacay
Tugay Karacay

Reputation: 46

Hi you need create a target from service then add as a target to listener.

const target = service.loadBalancerTarget({
  containerName: 'MyContainer',
  containerPort: 8000
}));

Upvotes: 2

Related Questions