Docker Swarm Peer Discovery Backend #7515
Replies: 5 comments 8 replies
-
You could still assist us in doing this by providing explicit API calls, code samples, doc links etc that demonstrate how to register and remove nodes from whatever registry Docker Swarm provides. Right now you're asking us to do all the work but I'm certain you could contribute a lot without writing any Erlang. This would be very helpful because I don't think Team RabbitMQ members have much experience with Swarm. Thanks. |
Beta Was this translation helpful? Give feedback.
-
Consul, etcd, DNS peer discovery can be used with Docker Swarm. If there is an API that would allow for swam node discovery using a certain condition, it would be able to build a rough alternative to the Kubernetes peer discovery. Docker Swarm has extensive documentation but I could not find anything that would cover the API bits we need. |
Beta Was this translation helpful? Give feedback.
-
@lukebakken I'm sorry if the initial post did appear like that. I just wanted to initiate some discussion and see if the team is interested at all! If you are, I'm naturally doing everything I can to assist. |
Beta Was this translation helpful? Give feedback.
-
This is a short introduction from 10,000 feet on how Docker Swarm works, how it enables service discovery, and which options are available for peer discovery. I tried to be as concise as possible, but can go into detail on any of these sections if desired. How Docker Swarm worksSwarm forms a cluster from multiple Docker engines, organised as manager and worker nodes. Managers are elected via raft consensus and distribute workloads among all cluster nodes, including managers. Swarm clusters run collections of Docker containers referred to as stacks, which can conveniently be defined using docker compose – any valid compose file can be deployed to a Docker swarm, with additional deployment settings being available. Among them is the ability to create an arbitrary number of replicas tasks of a service, that is, instances of a container. Swarm follows a declarative approach to define desired cluster state and will attempt to reconcile any differences. Additionally, it forms a routing mesh to distribute socket connections among all members of a service; effectively this means the ingress controller is built-in. The documentation gives a good introduction: https://docs.docker.com/engine/swarm/key-concepts/ Service Discovery in SwarmAs previously mentioned, deployments in Swarm are organised like this: The stack groups all services an application consists of, somewhat similar to a Kubernetes deployment. A service maps closer to k8s: It represents a logical application with an arbitrary amount of replicas, defines reliance on external secrets, volumes, networks, etc. A single task (= replica) of a service is an actual Docker container running on one of the Swarm nodes. It doesn't matter which one, because Swarm forms a virtual network for each stack and transparently handles routing packets between the container instances. You can also assign additional networks to build a custom topology. To make it easier to work with dynamically assigned IP addresses, Swarm provides a simple DNS server on each container (127.11). It resolves service names to a single, virtual IP address that will be routed to the next best task; thus, one can use e.g.
This name can be queried again to return the IP of the task instance. Why the current RabbitMQ DNS backend doesn't work for SwarmAs outlined above, the service discovery DNS service provided by Swarm is insufficient for usage with the DNS peer discovery backend, because the reverse records reported by Swarm do not correspond to the hostnames reported to RabbitMQ instances themselves, that is: A replica task has an auto-generated (or manually configured) hostname, and Swarm DNS has A records for that name, but it will not report those hostnames in reverse records, nor provide a list of those hostnames. Options for RabbitMQ peer discoveryThat said, I do see two alternative approaches which could work: 1 - Not relying on RR recordsThis Swarm backend would work similar to the existing DNS backend, but instead of relying on the hostnames obtained from reverse records, it would attempt to connect to and query the identified instances for their node name. Open questions:
This approach has the advantage of not requiring privileged access to the Docker daemon - more on that issue in the next section. I suppose a lot of code from the DNS backend could be reused if not shared, so this would probably be the least invasive option. 2 - Asking the Docker daemonIn this scenario, cluster operators would need to mount the host's Docker socket into the service, or expose it to the host network. Both are possible, mounting the socket is favoured by the industry. By doing so, the new RabbitMQ peer discovery backend could connect to the Docker HTTP API, which opens up interesting capabilities - such as retrieving and manipulating the full service configuration. I still think this approach deserves some attention, as other major vendors use it to communicate with the Docker daemon, too; Additionally, this would allow the backend to actually perform similar work to the Kubernetes operator, even if that probably requires significant engineering work. @michaelklishin @lukebakken I hope this clears some things up - let me know if there are things missing or too vague. I'm going to devote some brain cycles to the Docker daemon approach and read the RabbitMQ Kubernetes operator thoroughly in the mean time! |
Beta Was this translation helpful? Give feedback.
-
@dtila and others, thanks for taking the time to look into this. FYI, there is no need to As a couple people have said here, the core issue is how DNS works in docker. I have run into the same problem using the DNS peer discovery plugin with @Radiergummi provides an idea to use the docker manager socket, would would work. Also, I hope everyone on this discussion is aware of the classic peer discovery backend, in which you list all node names in rabbitmq.conf. This means you must use pre-defined node names, but it works great with docker (https://github.com/lukebakken/docker-rabbitmq-cluster). Like @michaelklishin and I have said before, we'd welcome a contribution to get swarm working with RabbitMQ. Unless a customer with a support contract requests it, we probably won't work on it ourselves. |
Beta Was this translation helpful? Give feedback.
-
I'm operating a RabbitMQ cluster in a Docker Swarm cluster. This generally works well, but I fought bitterly to get automatic node discovery working -- in the end, I had to settle for a suboptimal workaround.
The general problem is that while Docker Swarm provides a DNS service discovery mechanism, the reverse records do not match the hostnames of the containers RabbitMQ is running in - and there is no way to achieve that. The seed host
tasks.<service name>
returns a list of A records as required by the DNS backend:The IPs resolve to the following, however:
for a container with a hostname configured to
rabbitmq-foo-2
.This means that currently, the only options are to run a separate service mesh, or configure the hosts statically using the classic file backend - which works, but isn't ideal (I have to modify and re-deploy the RMQ service anytime we add or remove a Swarm node).
I would like to formally suggest adding a service discovery backend plugin for Docker Swarm; in theory, this isn't too complicated, but would make it easier to get RabbitMQ running dynamically in Swarm.
I'm out of my depth in Erlang however, so I cannot do this on my own.
In the mean time, if anyone is interested in my solution: We run the service in global mode, so one RabbitMQ instance is deployed to every Swarm node. This makes it possible to use a volume persistent to the host. Additionally, we set the task hostname to that of the host node, so we can configure it statically.
The compose file looks like so:
The last step requires some kind of deployment script or CI pipeline. While we use Bitbucket pipelines, here's the meaty bits from our script:
I hope this helps someone - I spent considerable time researching.
Beta Was this translation helpful? Give feedback.
All reactions