This How to Use AWS Application Load Balancer and Network Load Balancer with ECS post originally posted on Medium first by Nathan Peck. Follow Nathan on Medium and twitter
Amazon Web Services recently released new second generation load balancers: Application Load Balancer (ALB), and Network Load Balancer (NLB). This was accompanied by a rename of the previous generation of load balancer to Classic Load Balancer. Understanding what these two new load balancers do and how they work will allow you to utilize the advantages of their new features, particularly their deep integration with EC2 Container Service to route traffic to your docker containers running in the cloud.
What is a load balancer?
A load balancer accepts incoming network traffic from a client, and based on some criteria in the traffic it distributes those communications out to one or more backend servers:
- Redundancy (One application server could die, but as long as there is at least one application server left the load balancer can still direct client traffic to the remaining working application server.)
- Scalability (By running two servers behind a load balancer you can now handle 2x the traffic from clients. Load balancers make it easy to add more and more backend servers as your traffic increases.)
What is the difference between an ALB and an NLB?
If you read the official AWS documentation for Application Load Balancer and Network Load Balancer you will notice that ALB is referred to as a “level 7” load balancer, while NLB is referred to as a “level 4” load balancer. These levels are a reference to the Open Systems Interconnection (OSI) model:
At the application layer a web browser constructs an HTTP request, which is a small text document describing what resource the browser wants to fetch from a web server.- In order to make sure the communication between browser and server is secure the web request is encrypted using SSL/TLS. This process takes a server’s public key and uses it to turn the HTTP payload into an unreadable chunk of encrypted binary data.
- A few layers below at the transport layer the encrypted payload is split up into TCP packets. Each packet is a piece of the HTTP payload wrapped in metadata such as the source IP address that the packet originated from and the destination IP address where the packet should go.
- The physical layer takes the raw digital 1’s and 0’s that make up TCP packets and turns them into an analog signal such as an electrical pulse on a copper wire, a light pulse in a fiber optic cable, or a radio wave in the air. On the other end another device turns that analog signal back into a digital 1’s and 0’s.
- The network traffic starts its trip back up the network stack as the 1’s and 0’s are interpreted into packets, which are then reassembled into the original encrypted data payload.
- The server uses its private key to decrypt the SSL/TLS encrypted payload back into the original plaintext HTTP request document.
- The server is able to interpret the plaintext HTTP request and figure out what resource to deliver back over the network.
So with this understanding of how a network communication travels across the network it is clear that a load balancer is more than just this:
The “level” of a load balancer refers to how far back up the network stack a network communication must travel before the load balancer can direct it on its way back down the stack towards its final destination.
For a level 7 application load balancer network communication looks like this:
A level 4 network load balancer looks like this:
ALB and NLB Specific Features
The level of the load balancer that you use for your application controls what you can do with that load balancer, and make the different load balancers better suited for particular design patterns.
SSL/TLS
There are a few approaches to implementing SSL/TLS encryption for network traffic between a client and web server. For example, one common use for a level 7 application load balancer is SSL/TLS termination:
However, some applications have regulatory or security concerns that require that they have encryption of data while in transit. If you use a level 7 load balancer for such an application you would end up with this:
If end to end encryption is a requirement it would make more sense to use a level 4 network load balancer instead of a level 7 load balancer:
HTTP Host and Path Based Routing
If end to end encryption is not needed then it is possible to take advantage of one of the powerful features of a level 7 application load balancer: host and path based routing.
Once again this type of routing can only be done using a load balancer at level 7 because it requires reading details of the HTTP request. The level 4 network load balancer only has TCP packets to work with, so it can’t read the HTTP request headers like the application load balancer can.
Protocols other than HTTP
Not every web application is built on top of HTTP. For example, a realtime multiplayer game might implement its own lightweight protocol on top of TCP (or even UDP) for communication between a game client and a game server. For such communication a layer 7 application load balancer would not work, because a load balancer at this level expects that all network traffic be HTTP.
A level 4 network load balancer should be used, as it can forward the TCP packets from the game client to the game server. In the case of a realtime game the level 4 network load balancer will also introduce less latency because network communication does not have to go all the way up and back down the network stack at the load balancer.
Dynamic Ports in ALB and NLB
One feature that is common to both the ALB and the NLB is the ability to send network traffic to dynamic ports. In the past a load balancer traditionally looked like this:
But with the rise of docker containers and binpacking strategies for running multiple applications on a single instance there are many architectures that look like this:
Both Application Load Balancer and Network Load Balancer support this new pattern of dynamic ports by using an AWS resource called the “Target Group”. A target group tracks the list of ports that are accepting traffic on each instance and gives the load balancer a way to distribute traffic evenly across ports. So in the above example 2/5ths of the traffic would be sent to the first instance that has containers hosted on two ports, while the remaining 3/5ths of the traffic would be sent to the other instance which has three open ports.
This also applies to an application load balancer that is doing HTTP based routing on level 7 of the network stack:
Integrating ALB and NLB with EC2 Container Service
Because of their dynamic port support the second generation load balancers are ideal for routing traffic to containerized services. There is a seamless integration between ALB and NLB, and Amazon EC2 Container Service (ECS). ECS is Amazon Web Service’s managed orchestration system for deploying and operating docker containers across a fleet of instances. It is designed to provide an easy way to connect the broad ecosystem of AWS services to containers.
Deploying a containerized application behind an ALB or NLB starts with the application itself. Lets see a basic Node.js web application
This application binds to port 8081, and expects all traffic to arrive on that port. If we were deploying this application without containers it would be run on several instances, and a load balancer would route all traffic to the static port 8081 on each instance.
But because we are deploying this application inside a docker container it allows us to take advantage of the docker feature of mapping ports inside a container to different ports on the host which is running the container. This is accomplished using a simple configuration that is passed to docker on container launch. In ECS we use a resource type called a task definition to define this configuration. The task definition is a lightweight metadata document that tells ECS what parameters to launch your docker container with.
Here is an example of a task definition that we would use to run a container for the sample application above:
Learn More AWS Cloud Formation
With this configuration multiple instances of a container can be deployed onto a single machine:
The task definition with its dynamic port mapping configuration can be used to launch a service in EC2 Container Service:
A client application initiates a new connection to the load balancer.- The load balancer receives the traffic, and picks a target from the target group attached to the load balancer. The target group has been configured by EC2 Container Service with a list of instances and ports.
- The load balancer sends the traffic to the chosen instance and port.
- The docker networking layer accepts the traffic and forwards it to the configured port inside the right container.
- Your application running inside the container receives the traffic on the port it has bound to.
Conclusion
Both Application Load Balancer and Network Load Balancer are designed from the ground up for the modern paradigm of dynamic port configurations as commonly seen in containerized deployments. Picking which load balancer is right for you will depend on the specific needs of your application, such as whether or not network traffic is HTTP, whether you need end to end SSL/TLS encryption, and whether or not you want host and path based traffic routing.
If you are deploying docker containers and using a load balancer to send network traffic to them EC2 Container Service provides a tight integration with ALB and NLB so you can keep your load balancers in sync as you start, update, and stop containers across your fleet.