1. Answers
  2. Routing traffic to multiple ports on the same EC2 instance with ALB

How do I route traffic to multiple ports on the same EC2 instance with ALB?

In this guide, we’ll walk through setting up an Application Load Balancer (ALB) that routes traffic to an EC2 instance on multiple ports. We’ll create the necessary resources including the load balancer, target groups, listener rules, and EC2 instance.

  1. VPC and Subnets: We need a VPC and subnets where our resources will be deployed.
  2. Security Groups: Security groups to allow traffic to the ALB and the EC2 instance.
  3. ALB: The Application Load Balancer to distribute incoming traffic.
  4. Target Groups: Target groups to define a collection of targets (in this case, the EC2 instance) that will receive the traffic.
  5. Listeners and Listener Rules: Define how the ALB routes traffic based on path patterns to different target groups.
  6. EC2 Instance: The target instance receiving traffic on specified ports.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// Create a VPC
const main = new aws.ec2.Vpc("main", {
    cidrBlock: "10.0.0.0/16",
    tags: {
        Name: "main_vpc",
    },
});
// Create subnets
const mainSubnet = new aws.ec2.Subnet("main", {
    vpcId: main.id,
    cidrBlock: "10.0.1.0/24",
    availabilityZone: "us-west-2a",
    tags: {
        Name: "main_subnet",
    },
});
// Create a security group for the ALB
const albSg = new aws.ec2.SecurityGroup("alb_sg", {
    vpcId: main.id,
    ingress: [{
        fromPort: 80,
        toPort: 80,
        protocol: "tcp",
        cidrBlocks: ["0.0.0.0/0"],
    }],
    egress: [{
        fromPort: 0,
        toPort: 0,
        protocol: "-1",
        cidrBlocks: ["0.0.0.0/0"],
    }],
    tags: {
        Name: "alb_sg",
    },
});
// Create a security group for the EC2 instance
const instanceSg = new aws.ec2.SecurityGroup("instance_sg", {
    vpcId: main.id,
    ingress: [
        {
            fromPort: 80,
            toPort: 80,
            protocol: "tcp",
            cidrBlocks: ["0.0.0.0/0"],
        },
        {
            fromPort: 8080,
            toPort: 8080,
            protocol: "tcp",
            cidrBlocks: ["0.0.0.0/0"],
        },
    ],
    egress: [{
        fromPort: 0,
        toPort: 0,
        protocol: "-1",
        cidrBlocks: ["0.0.0.0/0"],
    }],
    tags: {
        Name: "instance_sg",
    },
});
// Create the ALB
const appLb = new aws.lb.LoadBalancer("app_lb", {
    name: "app-lb",
    internal: false,
    loadBalancerType: "application",
    securityGroups: [albSg.id],
    subnets: [mainSubnet.id],
    tags: {
        Name: "app_lb",
    },
});
// Create target groups
const tgHttp = new aws.lb.TargetGroup("tg_http", {
    name: "tg-http",
    port: 80,
    protocol: "HTTP",
    vpcId: main.id,
    healthCheck: {
        path: "/",
        protocol: "HTTP",
        interval: 30,
        timeout: 5,
        healthyThreshold: 2,
        unhealthyThreshold: 2,
    },
    tags: {
        Name: "tg_http",
    },
});
const tgHttpAlt = new aws.lb.TargetGroup("tg_http_alt", {
    name: "tg-http-alt",
    port: 8080,
    protocol: "HTTP",
    vpcId: main.id,
    healthCheck: {
        path: "/",
        protocol: "HTTP",
        interval: 30,
        timeout: 5,
        healthyThreshold: 2,
        unhealthyThreshold: 2,
    },
    tags: {
        Name: "tg_http_alt",
    },
});
// Define listeners for the ALB
const httpListener = new aws.lb.Listener("http_listener", {
    loadBalancerArn: appLb.arn,
    port: 80,
    protocol: "HTTP",
    defaultActions: [{
        type: "fixed-response",
        fixedResponse: {
            contentType: "text/plain",
            messageBody: "Not found",
            statusCode: "404",
        },
    }],
});
const listenerRuleHttp = new aws.lb.ListenerRule("listener_rule_http", {
    listenerArn: httpListener.arn,
    priority: 1,
    actions: [{
        type: "forward",
        targetGroupArn: tgHttp.arn,
    }],
    conditions: [{
        pathPattern: {
            values: ["/http*"],
        },
    }],
});
const listenerRuleHttpAlt = new aws.lb.ListenerRule("listener_rule_http_alt", {
    listenerArn: httpListener.arn,
    priority: 2,
    actions: [{
        type: "forward",
        targetGroupArn: tgHttpAlt.arn,
    }],
    conditions: [{
        pathPattern: {
            values: ["/http-alt*"],
        },
    }],
});
// Create an EC2 instance
const appInstance = new aws.ec2.Instance("app_instance", {
    ami: "ami-0c55b159cbfafe1f0",
    instanceType: aws.ec2.InstanceType.T2_Micro,
    subnetId: mainSubnet.id,
    securityGroups: [instanceSg.name],
    tags: {
        Name: "app_instance",
    },
});
// Register EC2 instance with the target groups
const tgHttpAttachment = new aws.lb.TargetGroupAttachment("tg_http_attachment", {
    targetGroupArn: tgHttp.arn,
    targetId: appInstance.id,
    port: 80,
});
const tgHttpAltAttachment = new aws.lb.TargetGroupAttachment("tg_http_alt_attachment", {
    targetGroupArn: tgHttpAlt.arn,
    targetId: appInstance.id,
    port: 8080,
});
export const albDnsName = appLb.dnsName;
export const instanceId = appInstance.id;

In summary, this example sets up an Application Load Balancer (ALB) to route traffic to an EC2 instance based on path patterns. We created a VPC, subnets, security groups, the ALB, target groups, listener rules, and the EC2 instance. By defining appropriate listener rules, we directed different path patterns to specific target groups and ports on the EC2 instance. The outputs provide the ALB’s DNS name and the EC2 instance ID.

Deploy this code

Want to deploy this code? Sign up for a free Pulumi account to deploy in a few clicks.

Sign up

New to Pulumi?

Want to deploy this code? Sign up with Pulumi to deploy in a few clicks.

Sign up