Published on August 18, 2021
Category: Elastic Load Balancing, Networking & Content Delivery
Update: On September 27, 2021, we introduced Application Load Balancer (ALB)-type target groups for Network Load Balancers (NLB). This update allows you to register an ALB as a target for an NLB, enabling seamless traffic forwarding from the NLB to the ALB without needing to manage ALB IP address changes with AWS Lambda actively. Additionally, AWS Global Accelerator can provide static IP addresses that serve as a reliable entry point to your application endpoints across one or multiple AWS regions, including your Application Load Balancers, Network Load Balancers, or Amazon EC2 instances. These IP addresses are advertised from various AWS edge locations simultaneously through anycast, ensuring that traffic enters the AWS global network as close to your users as possible.
Introduction
Since its launch in August 2016, Elastic Load Balancing has offered the Application Load Balancer (ALB), which comes with multiple layer 7 features for HTTP traffic management. Users favor ALBs for their automatic scaling capabilities, which adjust to fluctuations in traffic. While this scalability simplifies growth planning, it can lead to changing IP addresses that clients connect to. Although this is typically manageable via DNS resolution best practices, it poses challenges for clients that cannot connect to every IP address on the internet, particularly for older devices or for security-conscious network administrators. Utilizing a static IP address effectively addresses these concerns without requiring updates to all clients or implementing workarounds, such as running scripts to keep firewalls aligned with current IP addresses.
A year later, the Network Load Balancer (NLB) was launched as a layer 4 TCP load balancer, providing static IP addresses for each Availability Zone. These static addresses remain unchanged, making them suitable for whitelisting in firewalls. However, while NLB supports only TCP traffic and lacks the advanced layer 7 features of ALB, users had to choose between the benefits of one or the other—until now. This blog post will demonstrate how to leverage both by placing an Application Load Balancer behind a Network Load Balancer.
Prerequisites
Before diving into the setup, ensure you have the following prerequisites in place:
- An internal or external NLB (internal for clients within your VPC and external for all others).
- An internal Application Load Balancer where layer 7 functionalities such as HTTPS termination and advanced routing will occur.
- Both the internal ALB and NLB must be located within the same Availability Zones.
- An IP-address-based target group for the NLB (with a TCP target group protocol). This is where the AWS Lambda function connects the ALB to the NLB.
- An Amazon S3 bucket for storing ALB IP address information.
- An IAM role with the necessary permissions policy allowing AWS Lambda to create the required resources (see Appendix A).
Bringing It All Together
The architecture culminates in a TCP listener on the NLB that receives traffic and forwards it to an internal ALB. The ALB handles TLS termination, inspects HTTP headers, and routes requests based on defined rules to target groups containing your instances, servers, or containers. The AWS Lambda function synchronizes everything by monitoring the ALB for IP address changes and updating the NLB target group accordingly. This setup results in a few static IP addresses that are convenient for whitelisting without sacrificing the advantages of the ALB. However, be aware that routing all traffic through two load balancers incurs costs for data processing across both, along with hourly charges for operating the load balancers, the Lambda function, Amazon S3, and Amazon CloudWatch.
The Lambda Function’s Role
The Lambda function performs several key actions to maintain synchronization:
- Queries DNS for the current IP addresses used by the ALB and uploads the results (NEW IP LIST) to the S3 bucket.
- Calls the
describe-target-health
API action to retrieve a list of currently registered IP addresses for the NLB (REGISTERED LIST). - Downloads the previous IP address list (OLD LIST). This list will be empty upon the function’s first invocation.
- Publishes the NEW LIST to the Lambda function’s CloudWatch Logs log stream for future reference.
- Updates the CloudWatch metric tracking the number of IP addresses for the internal ALB, providing insights into how many IP addresses have changed since the last run.
- Registers IP addresses from the NEW LIST that are absent from the OLD LIST or REGISTERED LIST.
- Deregisters IP addresses from the OLD LIST that are no longer present in the NEW LIST.
Getting Started and Setup
There are two methods to set up this solution: through the AWS Management Console or using AWS CloudFormation. You can find the CloudFormation template here, while the Lambda function zip package is available here. Let’s begin!
Setting Up Using the AWS Management Console
Step 1: Create an IAM Policy
In the IAM console, create an IAM policy with the permissions required by the Lambda function. A sample IAM policy can be found in Appendix A. For guidance, refer to the documentation for Creating IAM Policies.
Step 2: Create an IAM Role
Once the IAM policy is created, proceed to create an IAM role and attach the policy from Step 1.
Step 3: Create a Lambda Function
With the IAM role ready, navigate to the AWS Lambda console to create the Lambda function. Ensure you select the IAM role from Step 2 and set the runtime environment to Python 3.8.
Step 4: Configure the Lambda Function
Update the handler name to “populate_NLB_TG_with_ALB.lambda_handler” so that AWS Lambda can execute the correct Python file containing the function code. Click the “Upload” button to upload the Lambda function zip file.
Step 5: Set Up Lambda Environment Variables
After the function code appears in the Lambda console, add the following environment variables to enable the function to populate the NLB’s target group with ALB IP addresses:
- ALB_DNS_NAME – the fully qualified domain name (FQDN) of the ALB
- ALB_LISTENER – the ALB’s traffic listener port
- S3_BUCKET – the bucket for tracking changes between Lambda invocations
- NLB_TG_ARN – the ARN of the NLB’s target group
- MAX_LOOKUP_PER_INVOCATION – the maximum DNS lookups per invocation.
This revised approach offers both functionality and efficiency in managing static IP addresses with your Application Load Balancer.
Leave a Reply