1

I'm trying to replicate the flow described in here.

I have a load balancer, a listener on 80 port which is supposed to redirect calls to different target groups and a target group for a specific service.

How do I tell pulumi that I want to associate a specific service with existing lb, listener and a target group? A sample from here creates a listener but I don't want it to be derived from my target group, it should be able to handle multiple target groups as I described earlier.

When I'm using AWS Console, I can easily specify a target group in a service definition, as seen on the picture: enter image description here

But I'm unable to find analogous fields in pulumi doc.

nicks
  • 2,161
  • 8
  • 49
  • 101

1 Answers1

2

ECS's level of indirection, console magic and naming overloads ("service is valid for ECS and ALBs) can often be difficult to understand.

Ultimately, the configuration I think you're looking for is here in the ECS service definition.

When you define your ECS definition, you can the target group you wish to use, like so:

const svcA = new aws.ecs.Service("example-A", {
    cluster: cluster.arn,
    desiredCount: 1,
    launchType: "FARGATE",
    taskDefinition: taskDefinition.arn,
    networkConfiguration: {
        assignPublicIp: true,
        subnets: subnets.ids,
        securityGroups: [ securityGroup.id ]
    },
    loadBalancers: [{
        targetGroupArn: targetGroupA.arn,
        containerName: "my-app",
        containerPort: 80,
    }]
})

Note the loadBalancers object defined there.

You can then define multiple services and point them at whichever target group you like. Here, we can define a loadbalancer with two listeners and target groups:

// define a loadbalancer
const lb = new aws.lb.LoadBalancer("example", {
  securityGroups: [securityGroup.id],
  subnets: subnets.ids,
});

// target group for port 80
const targetGroupA = new aws.lb.TargetGroup("example-A", {
  port: 80,
  protocol: "HTTP",
  targetType: "ip",
  vpcId: vpc.id,
});

// listener for port 80
const listenerA = new aws.lb.Listener("example-A", {
  loadBalancerArn: lb.arn,
  port: 80,
  defaultActions: [
    {
      type: "forward",
      targetGroupArn: targetGroupA.arn,
    },
  ],
});

// target group for port 8080
const targetGroupB = new aws.lb.TargetGroup("example-B", {
  port: 8080,
  protocol: "HTTP",
  targetType: "ip",
  vpcId: vpc.id,
});

// listener for port 8080
const listenerB = new aws.lb.Listener("example-B", {
  loadBalancerArn: lb.arn,
  port: 8080,
  defaultActions: [
    {
      type: "forward",
      targetGroupArn: targetGroupB.arn,
    },
  ],
});

And then define two distinct services that point to different target groups:

// service listening on port 80
const svcA = new aws.ecs.Service("example-A", {
  cluster: cluster.arn,
  desiredCount: 1,
  launchType: "FARGATE",
  taskDefinition: taskDefinition.arn,
  networkConfiguration: {
    assignPublicIp: true,
    subnets: subnets.ids,
    securityGroups: [securityGroup.id],
  },
  loadBalancers: [
    {
      targetGroupArn: targetGroupA.arn,
      containerName: "my-app",
      containerPort: 80,
    },
  ],
});

// service listening on port 8080
const svcB = new aws.ecs.Service("example-B", {
  cluster: cluster.arn,
  desiredCount: 1,
  launchType: "FARGATE",
  taskDefinition: taskDefinition.arn,
  networkConfiguration: {
    assignPublicIp: true,
    subnets: subnets.ids,
    securityGroups: [securityGroup.id],
  },
  loadBalancers: [
    {
      targetGroupArn: targetGroupB.arn,
      containerName: "my-app",
      containerPort: 80,
    },
  ],
});

You can find a full end to end example of how this looks here

jaxxstorm
  • 12,422
  • 5
  • 57
  • 67
  • Thanks for the response. In your example you’re creating 2 listeners for the same lb, on ports 80 and 8080. I want to use a single listener for multiple services, as I can do for lambdas - I can create a new target group per lambda and register them all in the same listener on port 80 and route requests based on path rules. – nicks Mar 25 '22 at 15:51
  • You can't create multiple listeners on the same port for fargate/IP based networking, the AWS API will throw an error. If you want to route different rules to different target groups, you'd use a listenerrule: https://www.pulumi.com/registry/packages/aws/api-docs/alb/listenerrule/ – jaxxstorm Mar 25 '22 at 16:08
  • Understood, but what if I want to serve multiple services all on port 80, will I need to crate multiple LBs? – nicks Mar 25 '22 at 16:10
  • Updated my comment, no. you'd use listenerrule to capture the host headers and route to distinct target groups. – jaxxstorm Mar 25 '22 at 16:11
  • @nicks did this answer your question, or would an example with listenerrules helps? – jaxxstorm Mar 25 '22 at 22:24
  • i'm trying to replicate your example. "containerName" needs to be defined before i mention it in loadBalancers but it can't find any "name" property on ecs.Container. – nicks Mar 26 '22 at 16:06
  • the full link is here, you'll need the whole thing: https://github.com/jaxxstorm/pulumi-examples/tree/main/typescript/aws/fargate – jaxxstorm Mar 26 '22 at 16:22
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/243349/discussion-between-jaxxstorm-and-nicks). – jaxxstorm Mar 26 '22 at 16:23