cluster

Auto Scaling Docker Nodes in AWS

ButterBall Turkey

I once heard a story from someone who worked at ConAgra. They produce and sell a variety of food products that you and I eat all the time. The most notorious is the ButterBall turkey. ConAgra owned Butterball from 1990 to 2006. Every Thanksgiving holiday, so I am told, ButterBall would have to scale up their call-center as well as their website to a couple hundred web servers to handle the demand for “how to cook my turkey?” That’s a lot of hardware!

We are only a couple months away from Thanksgiving. So, what do you call a turkey on the day after Thanksgiving? Lucky. #dadjoke

So, I decided to look into how to automatically scale up my Docker worker nodes when the average CPU threshold of 80% utilization is crossed. It turns out to be pretty straight forward and can be accomplished with a three step process.

  1. Create a Launch Template
  2. Create an Auto Scaling Group
  3. Create a cpu load greater than my threshold

Let’s be clear here. I am not talking about Kubernetes dynamically scaling out my pods. I am talking about measuring the average cpu utilization across all of my worker nodes and creating a brand new virtual machine (VM) that is added to my cluster. So when ALL my containers get a bit punchy, then it’s time to expand their world.

Starting Point

Before we get started with this 3 step approach, let’s talk about my cluster. Currently my demo cluster contains 1 UCP manager, 1 DTR, and 1 Worker. By the time we are done, I will show you how it dynamically grows by one worker node.

Auto Scaling Docker Nodes in AWS

Create a Launch Template

Logging into my AWS account using the left navigation to find Instances and select the Launch Templates.

Auto Scaling Docker Nodes in AWS

You can see in the diagram above that I already have a launch template created. Let’s see what it takes to create this. By selecting the Create Launch Template button you will get the following form to fill out. There are three critical things to fill out here. First you need to select an AMI by it’s ID and it should be a known AMI that you will use for all your Docker nodes. Second, you want to choose an appropriately sized VM that suits the needs of your worker nodes. I chose a t2.medium for demonstration purposes only. Third, be sure to include your key pair so that you can login to your VM. Next you will need to choose the appropriate security groups to apply to this VM so that you can SSH into the machine as needed and allow http/https traffic.

Auto Scaling Docker Nodes in AWS

Next you will want to scroll down to the bottom of the form and open the Advanced Details. This section allows you to execute a one-time only post-create-vm script. This is the secret sauce of how my new VM joins the cluster.

Auto Scaling Docker Nodes in AWS

This script includes the download and install of the docker engine as well as the command to join the VM to the Docker cluster. Copy the script from below.

#!/bin/bash
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
export DOCKER_EE_URL=https://storebits.docker.com/ee/m/sub-abcdefg-hijk-lmno-pqrst-uvwxyz/
export DOCKER_EE_VERSION=18.09
curl -fsSL "${DOCKER_EE_URL}/ubuntu/gpg" | sudo apt-key add -
sudo apt-key fingerprint 6D085F96
sudo add-apt-repository "deb [arch=$(dpkg --print-architecture)] $DOCKER_EE_URL/ubuntu $(lsb_release -cs) stable-$DOCKER_EE_VERSION"
sudo apt-get update
sudo apt-get install -y docker-ee=5:18.09.7~3-0~ubuntu-bionic docker-ee-cli=5:18.09.7~3-0~ubuntu-bionic containerd.io
sudo docker swarm join --token SWMTKN-1-abcdefg-qrstuvwxyz 172.31.7.68:2377

Create an Auto Scaling Group

Now we can create an AWS Auto Scaling Groups that utilizes your Launch template. Start by navigating to Auto Scaling and select Auto Scaling Groups. Then select the Create Auto Scaling Group button.

Auto Scaling Docker Nodes in AWS

Now choose the Launch Template panel on the right. Then select your newly created launch template from the list at the bottom and press the Next Step button.

Auto Scaling Docker Nodes in AWS

I have entered a name for my auto scaling group as well as the network and subnet’s that I want attached to my VM.

Auto Scaling Docker Nodes in AWS

This the crucial part of deciding how to to auto scale our VM’s. I have chosen an Average CPU Utilization of 75%. You can select the Review button and finish the process.

This blog doesn’t even scratch the surface of what is available for auto scaling. Read more about Auto Scaling Groups.

Simulate a Load

Now we need to test that the Auto Scaling Group will function properly. The easiest thing is to login to the existing worker node and run the progrium/stress container.

$ sudo docker run --rm -it progrium/stress --cpu 2
stress: info: [1] dispatching hogs: 2 cpu, 0 io, 0 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 6000us
stress: dbug: [1] --> hogcpu worker 2 [6] forked
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogcpu worker 1 [7] forked

This will immediately spin up 2 programs to stress each cpu on this VM. As you’ll notice below stress is running at a hefty pace on both cores for a total system load of 98.8% cpu utilization.

Auto Scaling Docker Nodes in AWS

This load will certainly surpass our 75% threshold for our auto scaling group. And looking at the Activity History you can see the event triggered a new VM to be provisioned.

Auto Scaling Docker Nodes in AWS

This is very exciting to me. Now we just need to wait until it is totally up and running and verify if the Docker engine was installed correctly and see if it properly joins the cluster.

The Results

Auto Scaling Docker Nodes in AWS

Well, there you have it. I now have 2 Kubernetes worker nodes in my cluster!

The beauty of Auto Scaling Groups is that you can tune many parameters including the instance type of the VM you are creating. You can even choose to use Spot Instances and get up to 90% reduced cost for your AWS VM’s.

Summary

When I have a customer facing containerized web application that will get hammered over the holidays, then I now have a solution to automatically scale out my VM’s using an AWS feature called Auto Scaling Groups. There is so much more to talk about regarding scaling including placement of new vm’s, scaling policies, scaling back, etc.

My family told me to stop telling Thanksgiving jokes, but I told them I couldn’t quit “cold turkey”. Feel free to contact us at Capstone IT especially if you want more #dadjokes. See you next time.

Mark Miller
Solutions Architect
Docker Accredited Consultant

Building Images in a Heterogeneous Cluster

Recently I was troubleshooting a customer problem in their on-premise cluster. But I was not sure where the problem lay. So I switched over to using my colleagues Docker Enterprise demo cluster that is running in Azure. In this heterogeneous cluster are 1 Universal Control Plan (UCP) manager, 1 Docker Trusted Registry (DTR), 2 Windows workers, and 1 Linux worker.

Building Images in a Heterogeneous Cluster

I was attempting to reproduce my customer’s problem. However, what should have been easy turned into a problem; or else I wouldn’t be writing about it. I could not even get to my customer’s problem until I resolved an issue with simply building a linux image against a heterogeneous (Windows and Linux workers) cluster. At the time, it felt rather silly and frustrating all at the same time. All I could do was wring my hands and groan.

I had downloaded my client bundle and sourced it in my bash shell.

$ source env.sh

The next thing I needed was to build the docker image from my custom Dockerfile. The Dockerfile was based on nginx and had a custom nginx.conf loaded into the image.

$ cd ~/my-pp
$ docker build -t my-app:1.0 .
Sending build context to Docker daemon  4.096kB
worker-win-2: Step 1/3 : FROM nginx:1.15.2 
worker-win-2: Pulling from library/nginx
worker-win-2: 
Failed to build image: no matching manifest for unknown in the manifest list entries

Ok, based on the last line of the log output it is not obvious what the issue is. However, if you look at the machine name that the build command was sent to, it becomes quite obvious what the problem is. I cannot build a linux based image on a windows machine. But how do I specify the target operating system on the command line?

I knew my friend Chuck had already encountered this problem. So this is what he told me to do; add the following option –build-arg ‘constraint:ostype==linux’ to my build command.

$ cd ~/my-app
$ docker build --build-arg 'constraint:ostype==linux' -t my-app .
Sending build context to Docker daemon  4.096kB
worker-linux-1: Step 1/3 : FROM nginx:1.15.2
worker-linux-1: Pulling from library/nginx
worker-linux-1: Pull complete 
worker-linux-1: Digest: sha256:d85914d547a6c92faa39ce7058bd7529baacab7e0cd4255442b04577c4d1f424
worker-linux-1: Status: Downloaded newer image for nginx:1.15.2
worker-linux-1:  ---> c82521676580
worker-linux-1: Step 2/3 : EXPOSE 8443 
worker-linux-1:  ---> Running in 88e99ace1e12
worker-linux-1: Removing intermediate container 88e99ace1e12
worker-linux-1:  ---> bd98a77c3b6b
worker-linux-1: Step 3/3 : COPY nginx.conf /etc/nginx/ 
worker-linux-1:  ---> 62b9f978af24
worker-linux-1: Successfully built 62b9f978af24
worker-linux-1: Successfully tagged my-app:latest

That’s it folks. Plain and simple.

$ docker build –build-arg ‘constraint:ostype==linux’ -t my-app .

In a heterogeneous cluster my builds are now targeting linux machines and not windows. Of course you can alternate the ostype to windows if that is your goal. Good luck and contact us at https://capstonec.wpengine.com/contact-us/

Mark Miller
Solutions Architect
Docker Accredited Consultant

Docker Clustering Approaches

Most enterprises have a structured release management process that allows phased deployment between multiple environments including development, test, model (stage or acceptance), and production.  https://en.wikipedia.org/wiki/Deployment_environment.

With Docker Enterprise Swarm you can generally setup these environments in one of the following ways: Single Cluster, Multi-Env Cluster, Geo-Single Clusters, and Geo-Multi-Env Cluster.  I will explain these different approaches and help you determine when each approach might be useful in your enterprise.  Of course, there is a myriad of variations on each of these that you could employ to suit your own needs.