{"id":2311,"date":"2016-10-20T08:48:57","date_gmt":"2016-10-20T05:48:57","guid":{"rendered":"https:\/\/upcloud.com\/global\/us\/resources\/tutorials\/load-balancing-docker-swarm-mode\/"},"modified":"2016-10-20T08:48:57","modified_gmt":"2016-10-20T05:48:57","slug":"load-balancing-docker-swarm-mode","status":"publish","type":"tutorial","link":"https:\/\/upcloud.com\/global\/resources\/tutorials\/load-balancing-docker-swarm-mode\/","title":{"rendered":"How to get started with load balancing Docker Swarm mode"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Docker Swarm mode not only makes cluster orchestration a breeze, but it also offers an easy way to publish ports&nbsp;for services.&nbsp;Usually, containers are only accessible through their host machine\u2019s IP addresses, but in a swarm, all nodes participate in an ingress routing mesh.<\/p>\n\n\n\n\n\n<h2 class=\"wp-block-heading\">Swarm mode routing mesh<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The swarm internal networking mesh allows every node in the cluster to accept connections to any service port published in the swarm by routing all incoming requests to available nodes hosting service with the published port.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The ingress mesh uses the following ports in communication between nodes in the swarm.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Port 7946 TCP\/UDP for container network discovery.<\/li>\n\n\n\n<li>Port 4789 UDP for the container ingress network.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Using the private network between&nbsp;your UpCloud servers when initializing the swarm ensures the connections will remain secure. However, when publishing ports in the swarm, as mentioned&nbsp;before, they are accessible through any node\u2019s public IP. In Docker Engine 1.12, it is not possible to bind the published port to a specific IP address. If you wish to prevent direct access to the container ports, set up a firewall blocking the incoming connections to the swarm public IP addresses.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Deploying CoreOS nodes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Start off by logging into your <a href=\"https:\/\/hub.upcloud.com\/deploy\/\" target=\"_blank\" rel=\"noreferrer noopener\">UpCloud control panel<\/a> and deploying two CoreOS nodes for the Docker Swarm and a third node for the load balancer. If you are not familiar with deploying CoreOS nodes for Docker, take a look at our introductory guide to&nbsp;<a href=\"https:\/\/upcloud.com\/global\/resources\/tutorials\/docker-swarm-orchestration\/\" target=\"_blank\" rel=\"noreferrer noopener\">Docker Swarm Orchestration<\/a>&nbsp;for a quick start guide.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once you have the three nodes online, log into each of them with SSH.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To enable Docker Swarm mode, you will need to update CoreOS to a version that includes Docker 1.12 or newer. You can find the version numbers in the <a href=\"https:\/\/coreos.com\/releases\/\" target=\"_blank\" rel=\"noopener noreferrer\">CoreOS release notes<\/a>. At the time of the update, the required Docker version was only available on the CoreOS Alpha channel. Perform the following steps on all three of your nodes to update them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Edit the updated configuration file and change the <em>GROUP<\/em>&nbsp;from <em>stable<\/em> to <em>alpha<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo vi \/etc\/coreos\/update.conf\n\nGROUP=alpha<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Save the file and exit the editor, then reboot the servers.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo reboot<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Although CoreOS usually performs updates automatically in the background, use the following command to run the update manually.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo update_engine_client -update\n...\nUpdate succeeded -- reboot needed.<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">When the update finishes, it will prompt you to restart the servers.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo reboot\n...\nCoreOS alpha (1192.1.0)<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">With&nbsp;the CoreOS nodes updated, verify that the Docker is running the required version.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">docker -v\n\nDocker version 1.12.1, build 7a86f89<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You can then continue with configuring the swarm itself.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/signup.upcloud.com\/\">Try UpCloud for free!<\/a><\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring the backend nodes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Enable the Swarm mode for two of the three nodes by initializing one of them as the cluster manager and then joining the second node to it. Run the command below on the node you wish to assign as the Swarm manager.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">docker swarm init --advertise-addr&nbsp;&lt;manager private IP&gt;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once the initialization is complete, you will see a <tt>docker swarm<\/tt> command towards the end of the output similar to the one below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">docker swarm join \n--token &lt;SWMTKN token&gt; \n&lt;manager private IP&gt;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Run the command with your swarm manager token and manager private IP on the second node to join it to the cluster.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can see the nodes in your cluster using the command below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">docker node ls\n\nID                          HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS\n3h39l1ex8c1i5oo2xn4qnwkj6 * node0     Ready   Active        Leader\n4bdtzjfa0qw799e6npb4dxvl1   node1     Ready   Active<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then, start the web host service with replicas for both nodes.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">docker service create \n--name backend \n--replicas 2 \n--publish 8080:80 \nnginx<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A short explanation of the command above. Docker creates two replicas of the <em>latest nginx<\/em> container named&nbsp;<em>backend<\/em> and publishes them to an external port 8080.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setting up the load balancer<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Using a load balancer outside&nbsp;of the Swarm allows an easy way to connect to your containers without having to worry about the cluster nodes. As all of the published services are available through any of the swarm nodes thanks to the ingress routing, the load balancer can be set to use the swarm private IP addresses without concern of which node is hosting what service.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For consistency, the load balancer will be deployed on its own single-node swarm. Open an SSH connection to your load balancer server and initialize a new swarm on it.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">docker swarm init --advertise-addr&nbsp;&lt;load balancer private IP&gt;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, prepare the load balancer setup by creating a default.conf file in a new directory.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo&nbsp;mkdir&nbsp;-p \/data\/loadbalancer\n\nsudo vi \/data\/loadbalancer\/default.conf<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enter the following server and upstream segments in the configuration file and replace the &lt;node private IP&gt; placeholders with the private IP addresses of the two swarm nodes hosting your web service.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">server {\n   listen 80;\n   location \/ {\n      proxy_pass http:\/\/backend;\n   }\n}\nupstream backend {\n   server &lt;node0 private IP&gt;:8080;\n   server &lt;node1 private IP&gt;:8080;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Save the file and exit the editor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then, create the load balancer container using the following command to publish it to port 80 and mount the configuration directory in the container.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">docker service create \n--name loadbalancer \n--mount type=bind,source=\/data\/loadbalancer,target=\/etc\/nginx\/conf.d \n--publish 80:80 \nnginx<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The container will start in a matter of seconds and allow connections to the web services hosted by your Docker Swarm. You can test the load balancer by opening the load balancer server&#8217;s public IP address in your web browser.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/upcloud.com\/media\/nginx_custom_default_page-2.png\" alt=\"Nginx custom default page\" class=\"wp-image-2279\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">If everything is running correctly, you will be greeted by the default nginx welcome page.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The Docker Swarm mode allows an easy and fast load-balancing setup with minimal configuration. Even though the swarm itself already performs a level of load balancing with the ingress mesh, having an external load balancer makes the setup simple to expand upon.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you wish to further improve upon the redundancy of your web cluster, you should look into setting up a floating IP address between multiple load balancer servers. Follow this article to\u00a0find out more about the <a href=\"https:\/\/upcloud.com\/global\/docs\/guides\/configure-floating-ip-ubuntu\/\" target=\"_blank\" rel=\"noreferrer noopener\">floating IPs on UpCloud<\/a>.<\/p>\n","protected":false},"author":3,"featured_media":27362,"comment_status":"open","ping_status":"closed","template":"","community-category":[223,274],"class_list":["post-2311","tutorial","type-tutorial","status-publish","has-post-thumbnail","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/2311","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial"}],"about":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/types\/tutorial"}],"author":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/comments?post=2311"}],"version-history":[{"count":0,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/2311\/revisions"}],"wp:attachment":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/media?parent=2311"}],"wp:term":[{"taxonomy":"community-category","embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/community-category?post=2311"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}