Attaching instances in private subnet to ELB

Attaching instances in Private Subnets to ELB. AWS_EN

Configure instances in private subnets to be attached to ELB

We will see how to attach an instance located in a private subnet to an ALB.

The following methods are introduced in the AWS official website on this subject.

To attach Amazon EC2 instances located in a private subnet, create public subnets in the same Availability Zones as the private subnets used by the backend instances. Then, associate the public subnets with your load balancer.

How do I attach backend instances with private IP addresses to my internet-facing load balancer in ELB?



Place the ELB in front of the EC2 instance, and the ELB should be of type ALB.
The instance is Amazon Linux 2.
Instances will be placed on private subnets, but public subnets will also be created for each AZ.

CloudFormation template files

We will build the above configuration using CloudFormation.
The CloudFormation template is placed at the following URL

awstut-fa/001 at main · awstut-an-r/awstut-fa
Contribute to awstut-an-r/awstut-fa development by creating an account on GitHub.

Template file points

To attach an instance in a private subnet to an ALB, create a public subnet – VPC side

Check the public subnet-related resources.
The key points are the public subnets and the route table for the subnets.

Resources: IGW: Type: AWS::EC2::InternetGateway IGWAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref VPC InternetGatewayId: !Ref IGW PublicSubnet1: Type: AWS::EC2::Subnet Properties: CidrBlock: !Ref CidrIp1 VpcId: !Ref VPC AvailabilityZone: !Sub ${AWS::Region}${AvailabilityZone1} PublicSubnet2: Type: AWS::EC2::Subnet Properties: CidrBlock: !Ref CidrIp2 VpcId: !Ref VPC AvailabilityZone: !Sub ${AWS::Region}${AvailabilityZone2} PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC RouteToInternet: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: GatewayId: !Ref IGW PublicSubnetRouteTableAssociation1: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1 RouteTableId: !Ref PublicRouteTable PublicSubnetRouteTableAssociation2: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet2 RouteTableId: !Ref PublicRouteTable
Code language: YAML (yaml)

In the environment we will be building, an EC2 instance will be created on private subnets. However, in order to associate an EC2 instance placed on a private subnets with the ALB, it is necessary to prepare public subnets for the ALB, as shown in the first quote.

A public subnet must be created for each AZ in which a private subnet is created. In this case, there is one private subnet in each of the two AZs where the instances are located. Therefore, one public subnet must also be created in each of the two AZs.

We will also prepare a route table for the public subnet and define the route for the Internet gateway.

To attach an instance in a private subnet to an ALB, create a public subnet – ALB side

Check the subnet settings on the ALB side.

Resources: ALB: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: !Sub ${Prefix}-ALB Scheme: internet-facing SecurityGroups: - !Ref ALBSecurityGroup Subnets: - !Ref PublicSubnet1 - !Ref PublicSubnet2 Type: application
Code language: YAML (yaml)

Continuing from the previous section on public subnets, we will associate them with ALB.
Specify the public subnets in the Subnets property. You can now associate EC2 instances in the private subnet of the same AZ with the ALB.

In addition, create a target group and a listener for the ALB.

Resources: ALBTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: VpcId: !Ref VPC Name: !Sub ${Prefix}-ALBTargetGroup Protocol: HTTP Port: !Ref HTTPPort HealthCheckProtocol: HTTP HealthCheckPath: / HealthCheckPort: traffic-port HealthyThresholdCount: !Ref HealthyThresholdCount UnhealthyThresholdCount: !Ref UnhealthyThresholdCount HealthCheckTimeoutSeconds: !Ref HealthCheckTimeoutSeconds HealthCheckIntervalSeconds: !Ref HealthCheckIntervalSeconds Matcher: HttpCode: !Ref HttpCode Targets: - Id: !Ref Instance1 - Id: !Ref Instance2 ALBListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - TargetGroupArn: !Ref ALBTargetGroup Type: forward LoadBalancerArn: !Ref ALB Port: !Ref HTTPPort Protocol: HTTP
Code language: YAML (yaml)

This time, we will configure the ALB listener to accept HTTP (tcp/80) and route it to the target group to which the two instances belong.

Yum via VPC endpoint

In order to run an EC2 instance as a web server, we will use yum to install Apache.

Normally, in order to run yum, you need to access a yum repository on the Internet. However, as an exception, if the OS of your EC2 instance is Amazon Linux (2), you can access the yum repository for that OS without going through the Internet by setting up a VPC endpoint for S3.

Please refer to the following page for details.

This time, the user data will be used to install and configure the startup of Apache with yum, and output the instance ID in index.html.


Using CloudFormation, we will build this environment and check its actual behavior.

Create CloudFormation stack and check resources in stacks

Create a CloudFormation stacks.

For instructions on how to run CloudFormation from the AWS CLI, please refer to the following page.

After checking the resources for each stack, the following information is available for the main resources created this time.

  • ALB name: fa-001-ALB
  • ID of Instance 1: i-04a1be5fb6ea67d60
  • ID of Instance 2: i-009d1a1926b8f3041
  • ID of PublicSubnet1: subnet-0f6fc4befd33069d6
  • ID of PublicSubnet2: subnet-096122b720cf20e72

You can also check the status of resource creation in the AWS Managemet Console.
Let’s start with the ALB.

ALB is associated with a public subnet.

You can see that there are two public subnets tied to the ALB.
Additionally, you can check the DNS name assigned to the ALB.

Next, check the target group of the ALB.

ALB target group includes instances in private subnets.

You can see that this one contains instances in a private subnets.

Operation check

Now that we are ready, let’s check the actual behavior.

$ curl instance-id: i-009d1a1926b8f3041 $ curl instance-id: i-04a1be5fb6ea67d60 $ curl instance-id: i-009d1a1926b8f3041 $ curl instance-id: i-04a1be5fb6ea67d60
Code language: Basic (basic)

We were able to access the ALB successfully.

From the output results, we can see that the two instances placed in the private subnet are accessed alternately.


We found that in order to attach an instance in private subnets to the ELB, we need to create public subnets.