In this post I explain my changes to the ambassador pattern I implemented during a microservices project earlier this year.
With Docker Links, Docker containers are able to communicate with each other over the network. When creating a Link, IP and exposed ports of the linked container will be available as environment variables inside the linking container. This way you have the possibility to use the environment variables inside the configuration of the linking container.
But Docker Links only work when both containers are on the same host.
To connect Docker containers across hosts you have to connect them using host ip and exposed port:
This works, but it is a static container configuration. When IP or port change, you have to rebuild your container and/or restart it.
To realize the communication across hosts in a dynamic environment, you can apply the ambassador pattern. The needed flexibility is realized with two changes. First we add two extra containers to delegate the network communication to these containers. The second change is, that these containers are able to change their configuration during runtime. The original containers are linked to the ambassador containers. I do not want to get into more details about the original pattern, but explain my modifications.
Let us take a look at the containers as described by most blog posts on the internet:
The Simple Ambassador running on Server #2 just exposes a port and does not add any flexibility or simplicity. To follow the KISS principle, we will just remove this container:
Some articles also use the simple ambassador to communicate with etcd or alike. But this work is better done by a dedicated container or systems like systemd or upstart. The ambassador container should just do what it was designed for: handle the network communication for another container.
The other modification we implemented, is scalability. The ambassador pattern is mostly explained with one on one connections. Some implementations also technically limit the pattern to one on one connections. But you can use the ambassador pattern to also implement scalabilty by using HAProxy:
With these modifications, it does not matter whether the containers are distributed across multiple hosts or not. You can use this ambassador for each container of your application and scale every single container. This allows you to scale your application and use your resources as good as it might get. As always, do not hesitate to contact me when you have any questions.