Use Application Load Balancers with your AWS OpsWorks Chef 12 Stacks
Want to build scalable applications that take advantage of Elastic Load Balancing Application Load Balancer features? You could add capabilities such as content-based routing, HTTP/2 and WebSocket protocols, support for containers, and enhanced metrics, and more.
AWS OpsWorks Stacks users have been asking AWS how they can use the new Application Load Balancer option with their layer. So AWS decided to develop and open source a set Chef 12 recipes to make this integration simple. This post walks you through the steps required to make any Chef 12 Linux layer in OpsWorks Stacks work with Application Load Balancers.
Unless otherwise noted, all steps are completed in the OpsWorks console.
Overview of the alb_support recipes
alb_support::attach_to_alb: This recipe does the actual work of attaching an instance to a target group of an Application Load Balancer. Recipes to be executed during the Setup lifecycle event must be added before this recipe, before your instance is attached to an Application Load Balancer.
alb_support::detach_from_alb: This recipe detaches instances from the load balancer. Add this recipe to the Shutdown lifecycle event. Recipes to be executed after the Shutdown lifecycle event must come after this recipe, when the instance is detached from the Application Load Balancer and the connection is drained.
alb_support::install and alb_support::uninstall_http_server: To give you an easy way to pass the default Application Load Balancer health check, and provide you with a visual indication that the load balancer works as expected, AWS also included sample recipes that install and uninstall an NGINX server on port 80 to serve as a default test page.
Step 1: Create an Application Load Balancer
Create a simple ALB with a default TCP listener and HTTP health checks performed on port 80. Do not add any instances to the target groups as this is handled by the open source Chef recipes.
Step 2: Create a Chef 12 stack
Create a new Chef 12 stack. Be sure to enable Use custom Chef cookbooks and use the following settings:
- For Repository type, choose Git.
- For Repository URL, use https://github.com/awslabs/opsworks-example-cookbooks. If you already have a running stack, you can download the alb_cookbook from the repository, and merge it into your Chef repository and continue with the next section.
Step 3: Grant the instances in your stack permission to call the Elastic Load Balancing API
- Choose Stack Settings.
- Choose the link next to Default IAM Instance Profile to open your instance profile in IAM.
- On the Permissions tab, expand Inline Policies and choose create here to create an inline policy.
- Choose Custom Policy, and then choose Select.
- Type a name for the policy, paste the following into the Policy Document field, and then choose Apply Policy.
Step 4: Create and configure an Application Load Balancer layer
Create a new layer. Next, use recipes from the open source alb_support cookbook to manage layer instance association with your Application Load Balancer.
Configure the layer recipes
To configure the recipes for your layer, do the following:
- Add alb_support::install_http_server and alb_support::attach_to_alb to the Setup lifecycle event.
- Add alb_support::detach_from_alb and alb_support::uninstall_http_server to the Shutdown lifecycle event.
Specify your ALB configuration details
After you’ve configured the alb_support recipes, change the instance shutdown timeout and provide some details via custom JSON.
- On the Layer Settings page, enter an Instance shutdown timeout that allows enough time for the execution of your shutdown recipes and the connection drainage. I recommend that you specify a period equal to the connection draining timeout (see below), plus the maximum time it takes your post-draining recipes to execute.
- Edit the layer settings and specify the following custom JSON before saving:
"target_group_arn": "SPECIFY ARN OF YOUR ALB TARGET GROUP HERE"
There are two optional parameters you might want to add to the alb_helper JSON block:
- connection_draining_timeout (default: 750)
This is the maximum amount time, in seconds, to wait for the Application Load Balancer to drain connections from the instance before executing additional shutdown recipes. You might want to set this value to match the draining timeout of your load balancer. If you do not want to postpone the execution of your shutdown recipes until the instance is drained, specify the parameter with a value of 0.
- state_check_frequency (default: 30)
This is the frequency, in seconds, in which to call EC2::describeTargetHealth to get an update on the connection draining process.
To pass the Application Load Balancer health checks, you need to allow incoming HTTP traffic. Choose Security on the layer, then add the AWS-OpsWorks-Web-Server group to your layer. This layer allows incoming traffic from any source address on port 80.
Verify your Application Load Balancer
You’re done! On the Instances page of your stack, add a new instance, choose start, and wait for it to come online. Now open the Amazon EC2 console and find the DNS name of your Application Load Balancer. When you open the address in your browser, you see the NGINX test page:
Instances added to the layer are attached automatically to the target group that you specified in the layer’s custom JSON block. Your Application Load Balancer uses health checks to detect unhealthy OpsWorks Stacks instances, and reroutes traffic to the remaining ones until the unhealthy instances have been restored.
Instances that are terminated have their connections drained and are removed from their assigned Application Load Balancer. The execution of shutdown recipes specified with an order later than alb_support::detach_from_alb are postponed until the instance is drained from the Application Load Balancer or the connection_ draining_timeout value is exceeded.
This post showed how easy it is to integrate an Application Load Balancer with your OpsWorks Stacks application. With the help of the Chef recipes, instances in your layers can automatically be added and removed from an Application Load Balancer. You can extend this example to take advantage of features such as path-based routing, HTTP/2 or WebSocket, container support and advanced metrics.
If you have questions or suggestions, please comment below.