How do I set up an Internet-facing ALB for EC2 in a private subnet?
To set up an Internet-facing Application Load Balancer (ALB) for EC2 instances in a private subnet on AWS, we need to create a few key resources:
- VPC: A Virtual Private Cloud to host all our resources.
- Subnets: Public and private subnets. Public subnets will host the ALB, and private subnets will host the EC2 instances.
- Internet Gateway: To allow the ALB to communicate with the internet.
- Route Tables: To route traffic from the public subnet to the Internet Gateway.
- Security Groups: To control the inbound and outbound traffic to the ALB and EC2 instances.
- ALB: The Application Load Balancer to distribute traffic.
- EC2 Instances: The backend instances that will receive traffic from the ALB.
Below is a detailed Pulumi program written in TypeScript to accomplish this setup:
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
// Create a VPC
const vpc = new awsx.ec2.Vpc("my-vpc", {
subnetSpecs: [
{
type: awsx.ec2.SubnetType.Public,
cidrBlocks: ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"],
},
{
type: awsx.ec2.SubnetType.Private,
cidrBlocks: ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"],
}
],
});
// Create an Internet Gateway
const igw = new aws.ec2.InternetGateway("my-igw", {
vpcId: vpc.vpcId,
});
// Create a Route Table for the public subnet
const publicRouteTable = new aws.ec2.RouteTable("public-rt", {
vpcId: vpc.vpcId,
routes: [
{
cidrBlock: "0.0.0.0/0",
gatewayId: igw.id,
},
],
});
// Associate the public subnet with the route table
const publicSubnetRouteTableAssociation = new aws.ec2.RouteTableAssociation("public-subnet-rta", {
subnetId: vpc.publicSubnetIds[0],
routeTableId: publicRouteTable.id,
});
// Create a Security Group for the ALB
const albSecurityGroup = new aws.ec2.SecurityGroup("alb-sg", {
vpcId: vpc.vpcId,
ingress: [
{
protocol: "tcp",
fromPort: 80,
toPort: 80,
cidrBlocks: ["0.0.0.0/0"],
},
],
egress: [
{
protocol: "-1",
fromPort: 0,
toPort: 0,
cidrBlocks: ["0.0.0.0/0"],
},
],
});
// Create a Security Group for the EC2 instances
const ec2SecurityGroup = new aws.ec2.SecurityGroup("ec2-sg", {
vpcId: vpc.vpcId,
ingress: [
{
protocol: "tcp",
fromPort: 80,
toPort: 80,
securityGroups: [albSecurityGroup.id],
},
],
egress: [
{
protocol: "-1",
fromPort: 0,
toPort: 0,
cidrBlocks: ["0.0.0.0/0"],
},
],
});
// Create an ALB
const alb = new aws.lb.LoadBalancer("my-alb", {
securityGroups: [albSecurityGroup.id],
subnets: vpc.publicSubnetIds,
loadBalancerType: "application",
});
// Create a Target Group for the ALB
const targetGroup = new aws.lb.TargetGroup("my-target-group", {
port: 80,
protocol: "HTTP",
vpcId: vpc.vpcId,
targetType: "instance",
});
// Create a Listener for the ALB
const listener = new aws.lb.Listener("my-listener", {
loadBalancerArn: alb.arn,
port: 80,
defaultActions: [
{
type: "forward",
targetGroupArn: targetGroup.arn,
},
],
});
// Launch EC2 instances in the private subnet
const ec2Instances = [];
for (let i = 0; i < 2; i++) {
ec2Instances.push(new aws.ec2.Instance(`my-instance-${i}`, {
instanceType: "t2.micro",
ami: "ami-0c55b159cbfafe1f0", // This is a public Amazon Linux 2 AMI in us-west-2
subnetId: vpc.privateSubnetIds[0],
securityGroups: [ec2SecurityGroup.name],
userData: `#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &`,
}));
}
// Register EC2 instances with the ALB Target Group
for (let i = 0; i < ec2Instances.length; i++) {
const instance = ec2Instances[i];
new aws.lb.TargetGroupAttachment(`tg-attachment-${i}`, {
targetGroupArn: targetGroup.arn,
targetId: instance.id,
port: 80,
});
}
// Export the ALB DNS name
export const albDnsName = alb.dnsName;
Explanation
- VPC and Subnets: We create a VPC with public and private subnets using
awsx.ec2.Vpc
. - Internet Gateway: An Internet Gateway is created and associated with the VPC.
- Route Table: A route table is created for the public subnet to route traffic to the Internet Gateway.
- Security Groups: Two security groups are created, one for the ALB allowing HTTP traffic from the internet, and another for the EC2 instances allowing traffic from the ALB.
- ALB: An Application Load Balancer is created in the public subnet.
- Target Group and Listener: A Target Group and a Listener are created for the ALB to forward traffic to the EC2 instances.
- EC2 Instances: Two EC2 instances are launched in the private subnet and registered with the ALB Target Group.
- Export: The DNS name of the ALB is exported for easy access.
This setup ensures that the ALB is internet-facing and can distribute traffic to EC2 instances in a private subnet.
Deploy this code
Want to deploy this code? Sign up for a free Pulumi account to deploy in a few clicks.
Sign upNew to Pulumi?
Want to deploy this code? Sign up with Pulumi to deploy in a few clicks.
Sign upThank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.