This message was deleted.
# general
s
This message was deleted.
c
Hey Dustin! Can you try to manually specify the
portMappings
for each of your
FargateService
s? For example, instead of using the respective target group instance (which implements the interface
PortMappingProvider
), specify them manually as explicit port mappings:
{ containerPort: …, hostPort: …, protocol: "tcp" }
. I think what’s happening is, that the port mappings inferred from the target group takes the container port and the host port to be the same, which is not correct if you want the load balancer to forward incoming request from a different port to the container port. You’d want the container port to be published as the port you expect incoming traffic port from the outside, which is the
hostPort
. Then you can set the target group’s port to be
80
so that it forwards 80 (ALB) -> 80 (host) -> 4000 (container).
m
Thanks for the ideas! I’ve tried this instead of using the respective target group instance:
portMappings: [{ containerPort: 5000, protocol: 'tcp' }]
This still gives me 503 errors. If I put a
hostPort
in there that doesn’t match the
containerPort
, I get an error:
When networkMode=awsvpc, the host ports and container ports in port mappings must match.
c
If I put a
hostPort
in there that doesn’t match the
containerPort
, I get an error:
When networkMode=awsvpc, the host ports and container ports in port mappings must match.
Ah ok. That makes sense. When you say you changed the port number for the ALB to listen on 80, I am assuming you changed the port number for the listener and not the target group?
m
That’s right, on the listener. I also just tried setting ALB and both target groups to use 80, then
containerPort
in the task definition to use the port I’m serving on in the container but still get 503 errors.
c
OK I just setup a simple Fargate Service myself similar to your setup and it works with listening on port 80 and forwarding requests to the right target group. I used the target group as the port mapping for my
FargateService
like in your snippet. The one thing I noticed is that you have an error in your
LoadBalancer
creation. It should be
securityGroups
(plural). I think you didn’t get any type errors because you seem to be using JS, which in JS any unknown properties would just get ignored. Here’s my example (note that I removed the client and the worker services). My “server” service is just a Python-based Flask app that simply returns “Hello World”.
Copy code
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";

// Create an ECS Fargate cluster
const cluster = new awsx.ecs.Cluster("cluster");

// Define the networking for our services
const loadBalancer = new awsx.lb.ApplicationLoadBalancer("external-load-balancer", {
    external: true,
    securityGroups: cluster.securityGroups,
});

const serverTargetGroup = loadBalancer.createTargetGroup("server", {
	port: 4000,
	protocol: 'HTTP'
});

const serverListener = loadBalancer.createListener("serverListener", {
    port: 80,
	protocol: "HTTP",
	external: true,
    // You should specify the "clientTargetGroup" here since that would be your "default" action
    // when the request path does not contain "/api".
	targetGroup: serverTargetGroup
});

serverListener.addListenerRule("serverListenerRule", {
	actions: [{ targetGroupArn: serverTargetGroup.targetGroup.arn, type: "forward" }],
	conditions: [{ field: "path-pattern", values: "/api*" }]
});

// Create Fargate service tasks that can scale out for each of our services
new awsx.ecs.FargateService("serverService", {
	cluster,
	taskDefinitionArgs: {
		container: {
			image: awsx.ecs.Image.fromPath("server", "./server"),
			memory: 512,
			portMappings: [serverTargetGroup]
		}
	},
	desiredCount: 2
});

// Export the Internet address for the service
export const url = loadBalancer.loadBalancer.dnsName;
As a side note, I highly recommend specifying security groups for your load balancer and the cluster such that not all ports are exposed to the outside. The default security group (and therefore the default ingress/egress rules) is pretty broad and admissive.
m
It works! Thank you very much for the help, and for the additional guidance. I really appreciate it.
c
Awesome! Anytime, Dustin! Please feel free to ask us any more questions you may have with your implementation. You may also want to check out the new CrossGuard feature we rolled out, so you can protect your AWS resources with policies that prevent anyone from deploying wide-open resources.