Giter Club home page Giter Club logo

docker-consul-demo's Introduction

Automatic proxified docker setup demo

By Camptocamp

What is this?

This is a demo using:

  • docker
  • docker-compose for composition
  • consul for service discovery
  • registrator to automatically feed consul with new containers
  • tutum/hello-world as the demo application

docker_consul_haproxy

How to run

Start the consul/registrator/haproxy stack

First, launch the consul/registrator/haproxy base infrastructure with:

$ docker-compose -f consul.yml up -d

You will then be able to see:

Start the application stack

Then launch the hello-world application with:

$ docker-compose up -d

which will let you access:

the web_1 node was also added to:

Scale the app

If you type:

$ docker-compose scale web=2

You will see:

Health checking

Health checking is implemented at two levels in this stack:

  • haproxy checks that port 80 of each member is up
  • consul checks that the node is up and that / returns a 200 status

If either check fails, the node will not be proxified.

You can test the HTTP check with:

$ docker-compose scale web=3
$ docker exec -ti $(basename $PWD)_web_2 pkill php-fpm

This will kill the php-fpm master process of the second container:

  • The web_2 node will be shown in error in the consul dashboard
  • The web_2 node will not appear anymore in the haproxy dashboard
  • The service will still run on the two other instances

To fix it, kill the container and scale again:

$ docker rm -f $(basename $PWD)_web_2
$ docker-compose scale web=3

Use service tags

Options of the haproxy are managed using service tags. An example is provided in hello2.yml, which provides the same www service as docker-compose.yml, but using a world.dev domain name, as well as hello.home, using a server_aliases= tag. The container is also named differently (web2) to avoid compose thinking it's the same containers.

If you launch:

$ docker-compose -f hello2.yml up -d

you should see:

You can access the new application at http://www.world.dev.127.0.0.1.nip.io as well as http://hello.home.127.0.0.1.nip.io.

Notes

Application internal load-balancing

The current setup using haproxy, consul and registrator makes it easy to load-balance applications by their service names (and optionally server aliases).

However, it does not solve out of the box the problem of internal load-balancing (i.e. when component A of the application needs to connect to component B, in a load-balanced way). One way to achieve that is demonstrated in hello2.yml, using external_links. In our case, this would be:

- "load-balancer:B"

This will insert and entry for B in /etc/hosts, resolving to the IP of the haproxy container. Since haproxy-consul will accept connections with the simple service name B, this will effectively load-balance to all B containers behind the proxy, without using the full address.

This saves us from using an ambassador or connectable for this purpose, since haproxy can load-balance on dynamic IP/port combinations.

Multiple versions of the same service

Since there is currently no namespace system in consul, deploying multiple versions of the same service can be tricky. The official recommendation seems to use tags, ACLs and prepared queries. This is complex and quite confusing (since all nodes are listed under the same service name with different labels).

What we are advocating with this setup is to use different service names, which will map to different domain names behind the proxies. One way to do that would be to have an environment variable set up when launching your docker-compose stack. For example, if that variable is called $PROD_LINE, your composition could be something like:

serviceA:
  image: foobar/a
  external_links:
    - "load-balancer:serviceB.${PROD_LINE}"
  environment:
    SERVICE_B: "http://serviceB.${PROD_LINE}:80"
    SERVICE_NAME: "serviceA.${PROD_LINE}"
    SERVICE_TAGS: "server_alias=serviceA.${PROD_LINE}.example.com"
  ports:
    - 80

serviceB:
  image: foobar/b
  environment:
    SERVICE_NAME: "serviceB.${PROD_LINE}"
  ports:
    - 8080

In this setup, provided the composition is started with PROD_LINE=prod, serviceA will be accessible by users as serviceA.prod.example.com (provided the DNS entry is made to point to the proxy). ServiceA will be able to communicate with serviceB by directly using the serviceB.prod name. The $SERVICE_B environment variable is passed to the serviceA container for that purpose.

In a CI/CD setup, it would be rather simple to use for example the commit ID or the branch name as the PROD_LINE value, allowing to point to domains such as serviceA.2a5bf183.example.com or serviceA.feat42.example.com.

TODO

  • Test with an overlay network and:

    • get rid of links
    • use consul DNS instead of links
  • Test on swarm

  • Port to an AWS ECS stack with CloudFormation

  • Add a demo of internal load-balancing using the haproxy container with the short service name

  • Prioritize local containers (with weights) on the proxy (using the IP address in the service registration?)

docker-consul-demo's People

Contributors

mbornoz avatar raphink avatar saimonn avatar vampouille avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

docker-consul-demo's Issues

503 server error

Hello,
I set the same example in a virtual server everything seems okay, I manage to display the dashboard consul and proxy, but when up to app test hello-world at times I responds with a 503 error which does not happen when I answered the example in a local environment.

consul.yml consul-haproxy infrastructure doesn't seem to work with consul-template 0.18.1

I've made some experiments locally based on this demo project (branch master) and while trying to do some experiments I've noticed that not the latest consul-template is being used

 docker-consul-demo git:(master) sudo docker-compose -f consul.yml  up -d
Creating consul
Creating registrator
Creating load-balancer
➜  docker-consul-demo git:(master) sudo docker ps
CONTAINER ID        IMAGE                              COMMAND                  CREATED             STATUS              PORTS                                                              NAMES
a635bed7d44f        camptocamp/haproxy-consul:latest   "/launch.sh"             6 seconds ago       Up 5 seconds        0.0.0.0:80->80/tcp, 0.0.0.0:32772->8080/tcp                        load-balancer
f20d742a31f3        gliderlabs/registrator:latest      "/bin/registrator -in"   6 seconds ago       Up 5 seconds                                                                           registrator
66c5aafe998c        progrium/consul:latest             "/bin/start -server -"   7 seconds ago       Up 6 seconds        53/tcp, 53/udp, 8300-8302/tcp, 8400/tcp, 8500/tcp, 8301-8302/udp   consul
➜  docker-consul-demo git:(master) sudo docker exec -ti load-balancer /bin/bash
root@a635bed7d44f:/# consul-template -v                                                                                                                                                                      
consul-template v0.13.0
root@a635bed7d44f:/# haproxy -v
HA-Proxy version 1.7.2-1 2017/01/13
Copyright 2000-2017 Willy Tarreau <[email protected]>

I had a look on
https://github.com/camptocamp/docker-haproxy-consul/blob/master/Dockerfile

and seen that the latest version of consul template is used

ENV CONSUL_TEMPLATE_VERSION=0.18.1

Can it be that the latest version of camptocamp/haproxy-consul:latest is not quite up-to-date?

I've build the docker-haproxy-consul locally and referenced it in consul.yml file and got the following error while executing docker-compose -f consul.yml up

load-balancer  | 2017/03/12 14:47:48.714156 [INFO] (runner) executing command "/usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -sf $(pidof haproxy)" from "/etc/consul-template/template.d/haproxy.tmpl" => "/etc/haproxy/haproxy.cfg"
load-balancer  | 2017/03/12 14:47:48.714234 [INFO] (child) spawning: /usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -sf $(pidof haproxy)
load-balancer  | Usage : haproxy [-f <cfgfile|cfgdir>]* [ -vdVD ] [ -n <maxconn> ] [ -N <maxpconn> ]
load-balancer  |         [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]
load-balancer  |         -v displays version ; -vv shows known build options.
load-balancer  |         -d enters debug mode ; -db only disables background mode.
load-balancer  |         -dM[<byte>] poisons memory with <byte> (defaults to 0x50)
load-balancer  |         -V enters verbose mode (disables quiet mode)
load-balancer  |         -D goes daemon ; -C changes to <dir> before loading files.
load-balancer  |         -q quiet mode : don't display messages
load-balancer  |         -c check mode : only check config files and exit
load-balancer  |         -n sets the maximum total # of connections (2000)
load-balancer  |         -m limits the usable amount of memory (in MB)
load-balancer  |         -N sets the default, per-proxy maximum # of connections (2000)
load-balancer  |         -L set local peer name (default to hostname)
load-balancer  |         -p writes pids of all children to this file
load-balancer  |         -de disables epoll() usage even when available
load-balancer  |         -dp disables poll() usage even when available
load-balancer  |         -dS disables splice usage (broken on old kernels)
load-balancer  |         -dR disables SO_REUSEPORT usage
load-balancer  |         -dr ignores server address resolution failures
load-balancer  |         -dV disables SSL verify on servers side
load-balancer  |         -sf/-st [pid ]* finishes/terminates old pids.
load-balancer  | 
load-balancer  | HA-Proxy version 1.7.3-1 2017/03/01
load-balancer  | Copyright 2000-2017 Willy Tarreau <[email protected]>
load-balancer  | 
load-balancer  | 2017/03/12 14:47:48.738839 [DEBUG] (cli) receiving signal "child exited"
load-balancer  | Consul Template returned errors:
load-balancer  | 1 error occurred:
load-balancer  | 
load-balancer  | * failed to execute command "/usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -sf $(pidof haproxy)" from "/etc/consul-template/template.d/haproxy.tmpl" => "/etc/haproxy/haproxy.cfg": child: command exited with a non-zero exit status:
load-balancer  | 
load-balancer  |     /usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -sf $(pidof haproxy)
load-balancer  | 
load-balancer  | This is assumed to be a failure. Please ensure the command
load-balancer  | exits with a zero exit status.

load-balancer exited with code 14

Any ideas why this happens?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.