All Hail the New Docker Swarm

 

by Adrian Mouat

Unfortunately, I’m not able to attend DockerCon US this year, but I will be keeping up with the announcements. As part of the Docker Captains program, I was given a preview of Docker 1.12 including the new Swarm integration which is Docker’s native clustering/orchestration solution (also known as SwarmKit, but that’s really the repo/library name). And it’s certainly a big change. In this post I’ll try to highlight the changes and why they’re important.

The first and most obvious change is the move into Docker core; to start a Docker Swarm is now as simple as running docker swarm init on the manager node and docker swarm join $IP:PORT on the worker nodes, where IP:PORT is the address of the leader. You can then use the top level node command to get more information on the swarm e.g:

There is no need to download further images or binaries; everything you need is right there in your Docker install. In this post I’ll stick to covering the technology, but it would seem naive not to point out that there are some large political ramifications from this decision; other orchestration frameworks such as Kubernetes and Mesos/Marathon which currently use Docker for running containers are unlikely to be happy with having to distribute Swarm alongside their own technology. As a side effect of this decision, I would expect to see other orchestrators move towards rkt or wrapping Docker’s underlying runc runtime with their own tooling.

Unlike the previous version of Swarm, there is also no dependency on a external store such as Consul or etcd. This has been achieved by pulling the Raft consensus implementation out of etcd and integrating it into the SwarmKit code. Comparing getting a Kubernetes or Mesos cluster running, Docker Swarm is a snap. This is a big bonus for developers who just want to try things out.

Launching containers to run on the Swarm is achieved through the service command rather than the normal docker run syntax:

We can use the ls and tasks subcommands to find out a bit more about the service:

And we can of course still find the container using the normal Docker commands:

This is a fundamental departure from the way Swarm used to work, which just re-used the normal Docker API. Whilst re-using the Docker API made things easy for developers to move between running on a single engine to a cluster, it also limited what was possible in Swarm and made it difficult or impossible to express certain concepts – for example it wasn’t possible to have a group of containers (“pod” if you must) scheduled as a single atomic unit. Notably, as can been above, the interface refers to “tasks” rather than containers. Whilst focused on containers currently, Docker intend to add support for other schedulable units such as VMs, unikernels and pods.

The service abstraction feels a lot like Kubernetes, which has clearly been a source of inspiration. For example, to increase the number of running tasks for a service:

Which even mirrors Kubernetes language (“replicas”). Docker have also paid attention to the “service” abstraction in Kubernetes and built similar functionality into Swarm. It’s easiest to describe this with an example. We’ll use a second service to test our existing redis service (we can’t use a regular container started with docker run as it will be unable to connect to the Swarm network):

We can then exec into the container created by this service (after connecting to the appropriate host and identifying the correct task):

Now we can use the “redis-cli” tool available inside the container to connect to the redis service. This is a simple utility for connecting to Redis servers and setting/getting data. By using the hostname “redis” when connecting, we should find that Docker connects us to one of the 5 Redis containers:

So we get DNS-based load-balancing for free. But that’s not all. There are a lot of cases where you don’t want to use DNS based load-balancing, so Swarm also provides a virtual IP for our service:

The IP 10.0.0.2 is “floating” or “virtual” – it hasn’t been assigned to a particular container. If we hit it, we should find that we are also load-balanced across the Redis instances:

If you have any experience with Kubernetes, this should seem familiar to you (but note that Docker have conflated the service and replication controller functionality of Kubernetes into a single service command). The lack of this functionality in the previous version of Swarm meant users had to turn to tools such as consul-template or Flux from Weaveworks. Now Swarm comes with everything you need to stand-up and properly load-balance a simple service.

Other in-built features include support for rolling-updates and TLS encryption of communication between Swarm nodes (Swarm does the hard work of automatically setting up TLS certification) for added security.

Of course, for such a new technology, it’s not all roses. It’s surprisingly annoying to go between the Swarm and container abstractions. For example, it would be nice to be able to docker exec into a task, but this requires figuring out which container represents the task and on which node it’s running. You can’t currently use Compose with Swarm, although I’m sure this will change quickly (I guess Compose will move to core at the same time). There doesn’t seem to be a way to switch between the spread and binpack scheduling strategies, but that’s probably just a documentation issue. Overall the functionality and maturity is naturally behind Kubernetes, but Swarm has made large in-roads in a very short period of time and it will be interesting to see how quickly they close the gap.

I’ve given several presentations comparing Swarm, Mesos/Marathon and Kubernetes. During these I would describe the disadvantages of Swarm as the overloading of the Docker API and the need to use third party tools for even simple systems. This new release addresses both those concerns in a single swoop and sets-up Swarm to be a serious competitor in the orchestration space.

The following two tabs change content below.

Adrian Mouat

Adrian Mouat is Chief Scientist at Container Solutions and the author of the O'Reilly book "Using Docker". He has been a professional software developer for over 10 years, working on a wide range of projects from small webapps to large data mining platforms.

Latest posts by Adrian Mouat (see all)

5 Comments

  1. ‘Docker have also paid attention to the “service” abstraction in Kubernetes and built similar functionality into Swarm.’ This is a big stretch. Kubernetes allows internal pods-as-services and also external applications to register as services which Kubernetes can route to. This is really important for enterprises that want to connect legacy services to their cluster. Services can also appear automatically in a DNS server in Kubernetes, which wasn’t demoed in swarm. From the demo we saw, a service in swarm is just a single image, which is a really weak definition of a service (if it can be called a service at all), and means that there’s no compostability (how can I build bigger services from smaller services if a service is always one unit?) A service in swarm is essentially just a replication controller, and they still don’t have any way to group related containers in a pod like fashion, so it’s a weak replication controller at that. In the future the .dab may run in a more pod like fashion, and a .dab may be the definition of a service, but for now, when the .dab was run, it clearly created discrete services for each image.

    • I think it’s clear that Docker looked at what the service abstraction bought Kubernetes and went down a similar architectural route, which is the point I was trying to make. You are of course right that it’s nowhere near as developed as Kubernetes services currently.

      If you look into the wording, Swarm now schedules “tasks” rather than containers. I think the intention is to build pods and/or stacks into the task abstraction, allowing larger units as you suggest, as well other targets such as VMs and unikernels.

      I’m not sure what you mean about DNS – Docker has used DNS for service discovery for a while now and this is shown above in the blog post.

  2. What I am missing in all those post about docker container orchestration is how to deal with the entry point to access your app.

    We are developing web applications and most of them consist of an application server and a database (e.g. tomcat and mysql). I need to point a hostname to the application so that users can access it. If the tomcat container runs “somewhere” on my node cluster what IP address do I configure in the DNS for my hostname?

    What if I want to run multiple different applications on my node cluster and access them via different domain-/hostnames?

    • The answer tends to be infrastructure specific because you need to obtain an externally addressable IP.

      One thing I didn’t cover in this post was the ability to publish a host port for services (because I didn’t understand how this worked until after keynote). Basically, you can assign a high-numbered port *on all hosts* to a service when it’s created and all nodes will then forward to that service whenever someone connects to the port (whether or not the node is running a task/container for that service). So if you use this functionality you can set-up a host (whether it’s a container/VM) with an externally addressable IP and use it to load balance over any nodes in your network.

      However, I’d really like to see something more like GKE does, where you can tell a service that it should be externally addressable. It will then be assigned an IP that you can use in DNS. I’m not sure if you could hack this yourself at the minute by having a node that is on both the swarm network and has a proper IP.

  3. Thanks for this handy and helpful tutorial.
    Just want to add that to create netwroks used by docker swarm you need to use the option “-d overlay”.
    It could be something known by others but since I am new to swarm I didn’t know it.

Leave a Reply

Your email address will not be published. Required fields are marked *