Networking & Content Delivery

Resolve DNS names of Network Load Balancer nodes to limit cross-Zone traffic

Introduction

Network Load Balancer (NLB), part of the Elastic Load Balancing Family, is the flagship Layer 4 load balancer for AWS. It offers elastic capacity, high performance, and integration with many other AWS services (such as Amazon EC2 Auto Scaling). NLB is designed to handle millions of requests per second while maintaining ultra-low latency, improving both availability and scalability. NLBs are used by all types of applications, from low-latency media streaming to high-scale enterprise data services, and in software architectures ranging from traditional virtual machines to containerized environments.

Challenge

Customers use NLBs to load balance traffic to backend applications per availability zone (AZ). These applications could be running natively on Amazon Elastic Compute Cloud (EC2) instances, Amazon Elastic Container Service (ECS), Amazon Elastic Kubernetes Service (EKS), or Kubernetes clusters on EC2. Or, they might also target IP addresses in your VPC subnets and utilize multiple AZs per Region for high availability (HA).

Customers often have several client business applications running inside the same AZ, and all of them consume backend services behind an NLB. To connect to and consume these backend services, the business application first must resolve the NLB DNS name. The NLB has one IP address for each node in an AZ, with each resolving to a DNS name. This is shown in the following diagram (figure 1).

Resolving NLB DNS name returns IP addresses for all enabled AZs

Figure 1: Resolving NLB DNS name returns IP addresses for all enabled AZs

 

For example, suppose that the DNS name for your load balancer is my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com and has 3 AZs enabled. Resolving this DNS name returns the IP addresses for all NLB nodes in all 3 enabled AZs.  This is shown in the following code:

Linux or Mac

$ dig +short my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com	
172.31.27.8
172.31.44.188
172.31.7.90

Windows

C:\> nslookup my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
Non-authoritative answer:
Name: my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
Addresses:  172.31.7.90
            172.31.27.8
            172.31.44.188

The load balancer has DNS records for each of its nodes. You use these DNS names, along with the following syntax, to determine the IP addresses of the load balancer nodes: az.name-id.elb.region.amazonaws.com. Please see the Network Load Balancer DNS Name documentation for more details.

Suppose your business application is consuming backend services running in the same local AZ. This may be to meet latency needs or to minimize cross-zone data transfer cost. In this case, you must resolve the DNS record for the NLB node that is running in the same AZ as your business application. You do this by appending the AZ-name to your NLB DNS name.

In the example above, a business application running in either eu-central-1a, eu-central-1b or eu-central-1c would resolve the DNS record for the local NLB local node as follows:

Linux or Mac

$ dig +short eu-central-1a.my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
172.31.7.90

$ dig +short eu-central-1b.my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
172.31.27.8

$ dig +short eu-central-1c.my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
172.31.44.188

Windows

c:\>nslookup eu-central-1a.my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
Non-authoritative answer:
Name:eu-central-1a.my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
Address: 172.31.7.90 c:\>nslookup eu-central-1b.my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
Non-authoritative answer:
Name: eu-central-1b.my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
Address: 172.31.27.8 c:\>nslookup eu-central-1c.my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
Non-authoritative answer:
Name: eu-central-1c.my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com
Address: 172.31.44.188

This will return a single IP address for the NLB local node in any of the enabled AZs. This is shown in the following diagram (figure 2). With this approach, a client application is able to consume local resources rather than cross-AZ backend services.

Resolving NLB local node returns 1 IP address

Figure 2: Resolving NLB local node returns 1 IP address

 

Solution

To meet these challenges, your client application can determine the AZ it is running in using the EC2 instance metadata service. The instance metadata is available from your running instance, CLI, and the AWS SDKs. The different instance metadata categories provide data about your instance that you can use to configure or manage the running instance. AZ information for a specific EC2 instance is retrieved from the Placement category as follows: placement/availability-zone. We will look in to this in more detail in the section that follows.

Resolving NLB nodes across Accounts

Many customers use multiple accounts to run their workloads. A client application running in Account A could be consuming a backend application running on a Kubernetes cluster behind an NLB in Account B. You can use the same method that we used earlier across AWS accounts when you want to consume services behind an NLB in the same physical AZ. To ensure that resources are distributed across the AZs in a Region, we independently map AZs to names for each account. For example, the AZ eu-central-1a for your AWS account might not have the same location as eu-central-1a for another AWS account. To identify the location of your resources relative to your accounts, you must use the AZ ID, which is a unique and consistent identifier for an AZ. For example, euc-az1 is an AZ ID for the eu-central-1(FRA) Region and it is the same location in every AWS account. As described earlier you resolve the IP address for an AZ specific NLB node by appending the AZ-Name to the NLB DNS name.

In some cases you will want client EC2 instance in AWS Account A is running in eu-central-1a, and you want to invoke services running an NLB in Account B in the same physical AZ. To make sure your client EC2 is resolving the NLB local node in the same physical AZ in a different Account, you need to determine the AZ-ID of your client EC2 in Account A. You do this by using the describe-availability-zones CLI command as shown in the code block that follows. (The same can be seen in the AWS Console under Resource Access Manager (RAM) or EC2 Dashboard as described in the next section.)

Using the CLI

[ec2-user@ip-10.0.0.1] $ aws ec2 describe-availability-zones --zone-name `curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone`
{
    "AvailabilityZones": [
        {
            "State": "available", 
            "ZoneName": "eu-central-1a", 
            "ZoneType": "availability-zone",
            "Messages": [], 
            "ZoneId": "euc1-az3", 
            "RegionName": "eu-central-1"
        }
    ]
}

The AZ ID is returned in the ZoneId property, euc1-az3.

You use this AZ ID in Account B (where the NLB is running) to determine the account-specific AZ mapping for AZ ID euc1-az3. To do so, use the aws ec2 describe-availability-zones CLI command as follows:

[ec2-user@ip-172.55.33.1] $ aws ec2 describe-availability-zones --zone-id euc1-az3
{
    "AvailabilityZones": [
        {
            "State": "available", 
            "ZoneName": "eu-central-1b", 
            "Messages": [], 
            "ZoneId": "euc1-az3", 
            "RegionName": "eu-central-1"
        }
    ]
}

Given AZ ID euc1-az3 in Account B, we see it’s mapped to eu-central-1b. This means that the same physical AZ ID euc1-az3 is mapped to AZ Name eu-central-1a in Account A and to eu-central-1b in Account B. Therefore, for the client EC2 instance in Account A to resolve the NLB local node in the same physical AZ in account B, you must append the AZ-name corresponding to AZ ID euc1-az3 from account B to the NLB DNS name. For example:  eu-central-1b.my-example-nlb-4e2d1f8bb2751e6a.elb.eu-central-1.amazonaws.com

Using the RAM Console 

  1. Open the AWS Resource Access Manager console.
  2. In the navigation bar, select your Region from the Region Selector.
  3. In the Your AZ ID pane on the right, review the list of Availability Zone names and their corresponding AZ IDs. This is shown in the following diagram (figure 3)
  4. Identify which Availability Zones have the same AZ IDs across your accounts.
AZ ID Mappings in AWS Resource Access Manager

Figure 3: AZ ID Mappings in AWS Resource Access Manager

Using the EC2 Dashboard 

  1. Open the EC2 Dashboard console
  2. In the navigation bar, select your Region from the Region Selector.
  3. On the navigation pane, choose EC2 Dashboard.
  4. The Availability Zone mappings are listed under Service health. This is shown in the following diagram (figure 4)
  5. Identify which Availability Zones have the same AZ IDs across your accounts.
AZ ID Mappings in EC2 Dashboard

Figure 4: AZ ID Mappings in EC2 Dashboard

Conclusion

You can now prefer consuming local AZ backend services to consuming cross-AZ services. To do so, you append the AZ name to the NLB DNS name and it resolves the IP address of the NLB local node. This is particularly useful for application with very low latency requirements. It is also a cost saving mechanism by limiting EC2 regional traffic.

 

Ahmed Gamaleldin

Ahmed is a Senior Technical Account Manager (TAM) at Amazon Web Services. Ahmed helps customers run optimized workloads on AWS and make the best out of their cloud journey.