Docker has been at the leading edge of containerized technologies with their Docker Engine and is steadily building features around it. Docker Swarm is the docker native clustering solution that turns a pool of Docker hosts into a single virtual server. In a natural step going forward, the Docker Engine version 1.12 brings a major upgrade to clustering with the introduction of built-in Swarm orchestration.

docker-swarm-orchestration

The Docker Engine 1.12 is designed around four core principles: simple yet powerful with a “just works” user experience, resilient zero single-point-of-failure architecture, secure by default with automatically generated certificates, and backwards compatibility with existing components. Thanks to the ease of use, this introductory guide is suitable for anyone looking to get started with Docker Swarm orchestration. No prior knowledge of containers is necessary, but if you wish, you can get acquainted with Docker by checking out a starters guide for How to Install WordPress with Docker.

Deploying CoreOS nodes

One of the easiest ways of running Docker is deploying a CoreOS host in which Docker comes pre-installed. CoreOS itself is a container optimised operating system that employs many of the Docker features out of the box. Deploying a CoreOS server is fast and simple using a short Initialization Script called cloud-config, which is commonly used to bootstrap together a CoreOS cluster along with the required services. However, in this case, Docker does not require any specific settings to start, but you may still wish to learn about the operating system itself with the article the Rise of CoreOS.

For this guide, you will need to deploy three cloud servers: a manager and two worker nodes. Each of the nodes in the swarm cluster can act in either role and may be promoted or demoted even during runtime. If you are ready to get started, log into your UpCloud Control Panel and select to Deploy a server under the Servers menu.

  1. Make the basic configuration by naming the new node.
  2. Select the availability zone and resource configuration.
  3. Under OS Templates section, use the CoreOS image by clicking the Select button.
  4. Include any SSH keys you may wish add to the root user.
  5. Expand the Miscellaneous server settings by clicking the Show button.
    • At the bottom of the section, you can input a cloud-config file to customise the server at deployment.
    • Add the following to the text field. Replace the placeholder <SSH key> with the key you wish to use for login.
    • #cloud-config
      ssh_authorized_keys:
        - "<SSH key>"
      users:
        - name: "docker-user"
          groups:
            - "sudo"
            - "docker"
          ssh-authorized-keys:
            - "<SSH key>"
    • The first key is added to the default username core, while in the users section you can define your own username like the example docker-user above.
  6. Once all settings are ready, start the node by clicking Deploy server at the bottom of the page.

Repeat until you have three CoreOS nodes up and running.

Log into each node over SSH using the keys you included or with the root user and password provided by the deployment process.

Configuring Docker Swarm 1.12 on CoreOS

Since the update 1.12, Docker Engine comes with an integrated cluster management solution. It allows the creation of a swarm of Docker Engines that can deploy application services. As the first party solution, no additional software is needed to use Swarm orchestration to create and manage a cluster.

CoreOS comes in three different release channels: stable, beta and alpha. At the time of the update, the Swarm orchestration was only available on the alpha channel, which closely tracks Docker updates providing the newest version for testing.

You can check the CoreOS release notes to find which channel is needed to update to Docker 1.12 or newer. If the stable channel already includes Docker 1.12 or later, you can skip these steps and go straight to the cluster initialization.

The update channel is defined in a configuration file, edit it as shown below to enable alpha releases. Perform the following on all of the nodes in your cluster.

sudo vi /etc/coreos/update.conf

GROUP=alpha

Save the file and exit the editor, then reboot the servers.

sudo reboot

CoreOS usually handles updates automatically, but in this case, use the command below run the update manually.

sudo update_engine_client -update
...
Update succeeded -- reboot needed.

Once the update is completed, reboot the nodes again to start using the new version.

sudo reboot
...
CoreOS alpha (1164.1.0)

The Docker Swarm follows a decentralised design where nodes can handle any role in the cluster. The node specialisations to managers and workers are chosen at runtime. As the cluster must have at least one manager, the first node initializing the cluster is assigned as such. Subsequent nodes joining the cluster are usually added as workers but can be assigned as either. The flexibility means that the entire swarm can be built from a single disk image with little differentiation.

Create a new swarm cluster with the initialization command below. Replace the <manager private IP> with the private IP of the host you are creating the cluster on.

docker swarm init --advertise-addr <manager private IP>

When the swarm starts successfully, you can see a docker swarm join command in the output like the example below. Use the command on your other nodes to join them to the swarm.

docker swarm join \
--token <SWMTKN token> \
<manager private IP>

When all nodes are connected, use the following command on the manager to check that the nodes are ready to accept tasks.

docker node ls

ID                          HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
3h39l1ex8c1i5oo2xn4qnwkj6 * node0     Ready   Active        Leader
4bdtzjfa0qw799e6npb4dxvl1   node1     Ready   Active
cu0jd5hb2l56swx9siq42f7li   node2     Ready   Active

If you run into problems joining nodes to the swarm, you can have the problematic node leave the cluster with the command below.

docker swarm leave

Then try to join again using the token and manager IP address as shown on your manager node. If every node of the cluster leaves, the swarm is disbanded and any node can start a new cluster with the initialization command.

Running services on Docker Swarm

Services are deployed on the cluster with simple requests for a number of containers of a certain application image. For example, if you deploy 5 replicas of a web host container, the manager takes the request and instructs the worker nodes to run more containers until the number of replicas is fulfilled.

The swarm nodes enforce TLS authentication and encryption to secure communication between nodes. All of this is done by default and requires no additional attention. It is also possible to use self-signed root certificates, but for most cases, it is fine to go with the default implementation.

swarm-automatic-tls

Prepare the cluster for containerized services by creating a network overlay for the containers to attach to.

docker network create \
--driver overlay \
--subnet 10.10.1.0/24 \
--opt encrypted \
services

Then start a pair of web hosts with the following command.

docker service create \
--replicas 2 \
--name nginx \
--network services \
--publish 80:80 \
nginx

You can see all currently deployed services with the command below.

docker service ls

ID            NAME   REPLICAS  IMAGE  COMMAND
a36vbfavxfcq  nginx  2/2       nginx

If you want to take a closer look at a specific service, use the next command.

docker service ps nginx

ID                         NAME     IMAGE  NODE   DESIRED STATE  CURRENT STATE
7g1lq4hvttrrhue9pc2jzqyiz  nginx.1  nginx  node1  Running        Running 10 seconds ago
0r30irdkm5lkwyraqdr7gcixq  nginx.2  nginx  node2  Running        Running 10 seconds ago

The output shows which nodes are running the containers.

Networking in the Swarm cluster

The swarm manages a multi-host networking which supports overlay network services. The cluster manager automatically assigns virtual IP addresses to the containers that join the overlay. The swarm runs an embedded DNS server, which makes it possible for the swarm to also assign each container a unique DNS name that is resolvable from any container within the overlay network. This greatly simplifies service discovery and allows load balancing from the get go.

docker-swarm-networking

Docker creates a number of network configurations by default. You can see the currently active networks using the ls command in the network scope.

docker network ls

Next to test the connection between containers, create a simple busybox service with the following command. The sleep parameter ensures the container remains alive long enough for you to have time to connect to it, as without having anything to do the container would simply exit.

docker service create \
--name busybox \
--network services \
busybox \
sleep 3000

With the service running, check which node it is on.

docker service ps busybox

ID                         NAME       IMAGE    NODE   DESIRED STATE  CURRENT STATE
eh2iznb6b8x8fm79eclmwbv7h  busybox.1  busybox  node1  Running        Running 9 seconds ago

Then connect to that node through SSH and check the name for the container.

docker ps

CONTAINER ID  IMAGE           COMMAND       CREATED        STATUS       PORTS  NAMES
e5329caea747  busybox:latest  "sleep 3000"  2 minutes ago  Up 2 minutes        busybox.1.4czfvm7771qy8lmbiz2bv4nbwdocker

Use the full container name to open it in a new terminal. For example as below but by using the container name shown in your terminal.

docker exec -it busybox.1.4czfvm7771qy8lmbiz2bv4nbwdocker /bin/sh

The following nslookup commands only work within a container connected to the overlay. Try to look up the web host service.

nslookup nginx

Server: 127.0.0.11
Address 1: 127.0.0.11

Name: nginx
Address 1: 10.10.1.2

The service Address 1 is the IP address for the load balancer. You can test the connectivity using wget within the busybox.

wget -O- 10.10.1.2

Alternatively, you can also look up the specific container addresses.

nslookup tasks.nginx

Server: 127.0.0.11
Address 1: 127.0.0.11

Name: tasks.nginx
Address 1: 10.10.1.4 nginx.1.288l03z4xzjrpfy53aokk1msd.services
Address 2: 10.10.1.3 nginx.2.ajyko9rdg8b7oiomd400y240g.services

Similarly, the direct container addresses are reachable from within the busybox container.

wget -O- 10.10.1.3

In both cases, you should see the default nginx welcome page in the reply.

Service scaling and management

Services running on the cluster are easily scalable through a single parameter. You can declare the number of replicas a service should have and the swarm manager automatically adapts by adding or removing containers to maintain the desired state.

The swarm also provides resilience through reconciliation of the desired states. The manager continuously monitors the state of the nodes in the cluster. If a node goes offline, the manager will reconcile the difference in the desired state and the current state by redeploying the lost services on the available nodes.

Inspect the web host service currently running on your cluster. Using the –pretty parameter formats the output into a more human readable list.

docker service inspect --pretty nginx

Create an additional container for the web host by updating the scale of the service with the following command.

docker service scale nginx=3

Then check which node was assigned to run the third task. Note that a single node can host multiple containers of the same service.

docker service ps nginx

If you ever have to scale down the entire cluster or even just temporarily shut down a node, you can prepare the swarm in advance by updating the node availability. Empty one of the nodes in your cluster by changing its availability to drain with the command below.

docker node update --availability=drain <node hostname>

The swarm manager will then migrate any containers running on the drained node elsewhere in the cluster. Scale the service back down again.

docker service scale nginx=2

Lastly, return the node availability back to active, therefore allowing new containers to run on it as well.

docker node update --availability=active <node hostname>

The cluster is then ready for anything. You may still want to remove the web host containers when you are done with them to free up the port reservations.

Summary

That concludes this getting started guide to Docker Swarm. The inclusion of native Swarm orchestration is a big update but it is very easy to learn the basics. As a result, managing your swarm is greatly simplified thanks to the first party support.

The automatic TLS configuration enables a secure connection between nodes, along with the already secure UpCloud private network in which only cloud servers on your account are connected. The Swarm networking allows containers to easily communicate using service names through the secure overlay, however, remember to take care when publishing container ports to the public network.

Next, you might wish to look into the load balancing provided by the swarm orchestration. You can read more about the Swarm mode routing mesh at the docker documentation. Together with an external proxy the swarm can manage an idea backend for distributed services.