├── LICENSE ├── README.md ├── docker-ui └── docker-compose.yml ├── loadbalancing_with_haproxy ├── README.md ├── docker-compose.yml ├── haproxy │ ├── haproxy.cfg │ └── haproxy.ctmpl └── sketch_loadbalancer_demo.png ├── traefik ├── README.md └── docker-compose.yml └── voting_app_with_crate.io ├── README.md └── voting_app_with_crate.yml /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Hypriot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rpi-cluster-demo 2 | 3 | **PLEASE NOTE: This repo is currently not maintained.** 4 | 5 | This repo contains several use cases to play with the Hypriot Cluster Lab. 6 | 7 | Before you start, read about this project's introduction blog post [here](http://blog.hypriot.com/post/introducing-hypriot-cluster-lab-docker-clustering-as-easy-as-it-gets/). 8 | 9 | We are very happy about feedback. Open an issue, create a PR or get in touch with us in the [community chat](https://gitter.im/hypriot/talk). 10 | -------------------------------------------------------------------------------- /docker-ui/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # 2 | # This docker-compose.yml starts a dockerui container with the website on port 9000 of the hardware node 3 | # It connects to the http socket of the swarm manager 4 | # (VLAN IP of the master node port 2378) to get all infos about the cluster. 5 | # 6 | dockerui: 7 | image: hypriot/rpi-dockerui 8 | ports: 9 | - 9000:9000 10 | command: -e http://192.168.200.1:2378 11 | -------------------------------------------------------------------------------- /loadbalancing_with_haproxy/README.md: -------------------------------------------------------------------------------- 1 | Loadbalancing with HAproxy 2 | ========================== 3 | 4 | This use case is about to use HAproxy as loadbalancer for several webservers. 5 | 6 | We use [Registrator from Gliderlabs](https://github.com/gliderlabs/registrator) to recognize new Docker containers that also offer a website. These new containers are registered in consul, which is globally available in the Hypriot Cluster Lab. Next, [consul-template](https://github.com/hashicorp/consul-template) recognize that a new webserver is up and tells the IP address of the new webserver to HAproxy. 7 | Thus, HAproxy always automatically knows about all available webservers and will forward incoming requests sequentially to all of them (following round-robin strategy). 8 | 9 | ![sketch](sketch_loadbalancer_demo.png) 10 | 11 | Let's do it step by step 12 | ------------------------ 13 | 14 | - Make sure that the hostname of the cluster's master node is called `master`. To do so, use our [flash tool](https://github.com/hypriot/flash) to define the hostname when flashing the SD card. 15 | - Login via SSH to all nodes of your cluster and make sure you have the latest Docker tools installed: 16 | ``` 17 | sudo apt-get update && sudo apt-get upgrade 18 | ``` 19 | When you are asked for updating the Docker config file or not, type `N` and finally reboot. 20 | 21 | - Login via SSH to the master node of your cluster, e.g. the node with hostname `master`, with user `pi` and password `raspberry`. 22 | 23 | - Checkout this repository: 24 | 25 | ``` 26 | git clone https://github.com/hypriot/rpi-cluster-demo.git 27 | ``` 28 | 29 | - Change to subfolder of this demo 30 | 31 | ``` 32 | cd rpi-cluster-demo/loadbalancing_with_haproxy 33 | ``` 34 | 35 | - Set Docker Swarm 36 | ``` 37 | export DOCKER_HOST=tcp://192.168.200.1:2378 38 | ``` 39 | 40 | - Setup Haproxy, consul-template and registrator: 41 | 42 | ``` 43 | docker-compose -p loadbalancing up -d 44 | ``` 45 | 46 | This creates all necessary services and also start one webservers 47 | 48 | - Now spin up some webservers 49 | 50 | ``` 51 | docker-compose -p loadbalancing scale demo-hostname=X 52 | ``` 53 | 54 | with `X` as the number of webservers. Note that as of today the Docker daemon can only handle up to 30 containers on one Raspberry Pi by default. Thus `X` should be 30 times the number of your RPis at max. 55 | 56 | - Open browser at IP of master node and restart page. Every page should show a new website with a new hostname because HAproxy is configured to follow the **round-robin** strategy. Thus, for every incoming HTTP request HAproxy forwards each request to a new node. 57 | 58 | 59 | Additional commands 60 | -------------------- 61 | - Permanently set environment variables for Swarm: 62 | 63 | `export DOCKER_HOST=tcp://192.168.200.1:2378` 64 | 65 | - Unset DOCKER_HOST variable 66 | 67 | `unset DOCKER_HOST` 68 | 69 | 70 | Reset your environment 71 | ---------------------- 72 | 73 | Execute the following command in the folder in which the *.yml* file resides: 74 | 75 | ``` 76 | DOCKER_HOST=tcp://192.168.200.1:2378 docker-compose -p loadbalancing down 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /loadbalancing_with_haproxy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | # 4 | # infrastructure services 5 | # 6 | services: 7 | swarmregistrator: 8 | image: hypriot/rpi-registrator:master 9 | environment: 10 | - DOCKER_HOST=tcp://192.168.200.1:2378 11 | - constraint:node==master 12 | volumes: 13 | - /var/run/docker.sock:/tmp/docker.sock:ro 14 | networks: 15 | - apps 16 | command: -internal -cleanup -ttl 15 -ttl-refresh 5 consul://192.168.200.1:8500 17 | 18 | consultemplate: 19 | image: hypriot/rpi-consul-template:0.11.0 20 | depends_on: 21 | - haproxy 22 | environment: 23 | - DOCKER_HOST=tcp://192.168.200.1:2378 24 | - constraint:node==master 25 | volumes: 26 | - /var/run/docker.sock:/var/run/docker.sock:ro 27 | - $PWD/haproxy/:/haproxy/ 28 | command: -consul 192.168.200.1:8500 -template "/haproxy/haproxy.ctmpl:/haproxy/haproxy.cfg:docker exec loadbalancing_haproxy_1 /haproxy-start reload" 29 | 30 | haproxy: 31 | image: hypriot/rpi-haproxy:1.5.8 32 | environment: 33 | - DOCKER_HOST=tcp://192.168.200.1:2378 34 | - constraint:node==master 35 | networks: 36 | - apps 37 | ports: 38 | - "0.0.0.0:80:80" 39 | - "0.0.0.0:443:443" 40 | volumes: 41 | - ./haproxy/:/haproxy-override/ 42 | 43 | # 44 | # two different websites to scale up 45 | # 46 | 47 | # hypriot-website: 48 | # image: hypriot/rpi-busybox-httpd 49 | # depends_on: 50 | # - consultemplate 51 | # networks: 52 | # - apps 53 | 54 | demo-hostname: 55 | image: firecyberice/armhf-demowebserver:hostname 56 | depends_on: 57 | - consultemplate 58 | environment: 59 | - constraint:node!=master 60 | networks: 61 | - apps 62 | 63 | networks: 64 | apps: 65 | driver: overlay 66 | 67 | -------------------------------------------------------------------------------- /loadbalancing_with_haproxy/haproxy/haproxy.cfg: -------------------------------------------------------------------------------- 1 | global 2 | maxconn 4096 3 | # haproxy 1.5.7++ option 4 | 5 | defaults 6 | mode http 7 | timeout connect 5000ms 8 | timeout client 50000ms 9 | timeout server 50000ms 10 | 11 | listen webinterface 12 | bind 0.0.0.0:8080 13 | mode http 14 | stats enable 15 | stats uri / 16 | stats realm Strictly\ Private 17 | stats auth haproxy:clusterlab 18 | timeout connect 5000ms 19 | timeout client 50000ms 20 | timeout server 50000ms 21 | 22 | frontend http-in 23 | bind *:80 24 | use_backend builder 25 | 26 | backend builder 27 | balance roundrobin 28 | option httpclose 29 | option forwardfor 30 | 31 | # Other example 32 | #listen http-in 33 | # bind *:8000 34 | -------------------------------------------------------------------------------- /loadbalancing_with_haproxy/haproxy/haproxy.ctmpl: -------------------------------------------------------------------------------- 1 | global 2 | maxconn 4096 3 | # haproxy 1.5.7++ option 4 | 5 | defaults 6 | mode http 7 | timeout connect 5000ms 8 | timeout client 50000ms 9 | timeout server 50000ms 10 | 11 | listen webinterface 12 | bind 0.0.0.0:8080 13 | mode http 14 | stats enable 15 | stats uri / 16 | stats realm Strictly\ Private 17 | stats auth haproxy:clusterlab 18 | timeout connect 5000ms 19 | timeout client 50000ms 20 | timeout server 50000ms 21 | 22 | frontend http-in 23 | bind *:80 24 | use_backend builder 25 | 26 | backend builder 27 | balance roundrobin 28 | option httpclose 29 | option forwardfor {{range service "armhf-demowebserver"}} 30 | server {{.Node}} {{.Address}}:{{.Port}} maxconn 3 {{end}} 31 | 32 | # Other example 33 | #listen http-in 34 | # bind *:8000{{range service "rpi-busybox-httpd"}} 35 | # server {{.Node}} {{.Address}}:{{.Port}}{{end}} 36 | -------------------------------------------------------------------------------- /loadbalancing_with_haproxy/sketch_loadbalancer_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hypriot/rpi-cluster-lab-demos/ff2d528dc75f5bd1dc4f3c24341594845a6deba4/loadbalancing_with_haproxy/sketch_loadbalancer_demo.png -------------------------------------------------------------------------------- /traefik/README.md: -------------------------------------------------------------------------------- 1 | ### Loadbalancing with Traefik 2 | 3 | [Traefik](https://docs.traefik.io/) is a lean and capable loadbalancer for dynamic microservice environments. 4 | 5 | Clone this repository and then change into the repository directory. 6 | 7 | There execute 8 | 9 | ``` 10 | $ export DOCKER_HOST=192.168.200.1:2378 11 | 12 | $ docker-compose up -d 13 | ``` 14 | 15 | Afterwards you should have a running traefik container on you cluster leader and one whoami container on one of your followers. 16 | 17 | ``` 18 | $ docker ps 19 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 20 | f72892c9187c hypriot/rpi-whoami "/app/http" 14 minutes ago Up 14 minutes 8000/tcp cl-follower1/traefik_whoami_1 21 | 983fbe7f3353 hypriot/rpi-traefik "/traefik --web --doc" 14 minutes ago Up 14 minutes 192.168.200.1:80->80/tcp, 192.168.200.1:8080->8080/tcp cl-leader/traefik_traefik_1 22 | ``` 23 | 24 | To test if everything works execute 25 | ``` 26 | $ curl -H Host:whoami.docker.localhost http://192.168.200.1 27 | I'am f72892c9187c 28 | ``` 29 | 30 | If this worked we can scale our backend servers up a bit: 31 | ``` 32 | $ docker-compose scale whoami=5 33 | ``` 34 | 35 | Check if everything went well by 36 | ``` 37 | $ for i in {1..5}; do curl -H Host:whoami.docker.localhost http://192.168.200.1; done 38 | I'm 5d829fecbdaa 39 | I'm 5eb115353885 40 | I'm e0313ac24554 41 | I'm 642b5d2c8d09 42 | I'm f72892c9187c 43 | ``` 44 | 45 | In the end (and there is always an end) should it down again by 46 | ``` 47 | $ docker-compose down -v 48 | ``` 49 | 50 | -------------------------------------------------------------------------------- /traefik/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | services: 4 | traefik: 5 | image: hypriot/rpi-traefik 6 | environment: 7 | - constraint:hypriot.hierarchy==leader 8 | ports: 9 | - "80:80" 10 | - "8080:8080" 11 | volumes: 12 | - /dev/null:/traefik.toml 13 | command: --web --docker --docker.domain=docker.localhost --logLevel=DEBUG --docker.endpoint tcp://192.168.200.1:2378 --docker.watch 14 | 15 | whoami: 16 | image: hypriot/rpi-whoami 17 | depends_on: 18 | - traefik 19 | environment: 20 | - constraint:hypriot.hierarchy!=leader 21 | - PORT=8000 22 | labels: 23 | - "traefik.backend=whoami" 24 | - "traefik.frontend.rule=Host:whoami.docker.localhost" 25 | - "traefik.port=8000" 26 | -------------------------------------------------------------------------------- /voting_app_with_crate.io/README.md: -------------------------------------------------------------------------------- 1 | Webserver with distributed Crate.io database 2 | ============================================ 3 | 4 | Overview 5 | --------- 6 | This use case is about to use a distributed database over several nodes. We will start a small webserver that communicates with crate.io databases that are fully synchronized over several nodes in the network. 7 | 8 | **Note:** For now, all containers are started only on a single node! We have not yet found an easy way to bring crate.io and Docker networking together. You are very welcome to join us extending this! 9 | 10 | Let's do it step by step 11 | ----------------------------- 12 | 13 | - Login via SSH to an arbitrary node of your cluster. 14 | - Checkout this repository: 15 | 16 | `git clone git@github.com:hypriot/rpi-cluster-demo.git` 17 | 18 | - Change to proper folder: 19 | 20 | `cd voting_app_with_crate.io` 21 | 22 | - Start a webserver with a voting app and crate.io as database: 23 | 24 | `docker-compose -f voting_app_with_crate.yml up -d` 25 | 26 | - Point your browser to the node you executed the previous commands. To do so, execute `hostname` on the node, and put a `http://` in front. Thus, e.g. the URL is 27 | 28 | `http://hcl-master/` 29 | 30 | You should see a simple website showing a welcome message, the hostname of the container and some buttons. 31 | 32 | - Now, connect the webinterface of crate. To so, add `:4200/admin` in the URL of your browser. The URl should result in something like 33 | 34 | `http://hcl-master:4200/admin` 35 | 36 | In the browser you should see a webinterface showing new number of nodes in the top menu bar. After some seconds, "2" nodes should be shown there. 37 | 38 | - Spawn up several more crate databases with 39 | 40 | 41 | `docker-compose -f voting_app_with_crate.yml scale crate-slave=X` 42 | 43 | where `X` is the number of crate database you would like to start. 44 | 45 | - If you then open reload your browser, the number of nodes should have increased by `X`! 46 | 47 | - To test, if all crate nodes receive data, on the website (http://hcl-master/) press the button **create table**. This initializes an empty SQL table in the crate database. Then, press the buttons **dogs** and **cats** a few times. 48 | If you then point your browser to the crate webinterface again, go to **console** in the menu on the left side, and exectute this query: 49 | 50 | `select * from voting;` 51 | 52 | Then you should see a list of how often you pressed the **dogs** or **cats** button. 53 | 54 | - Now list all containers running on the node with 55 | 56 | `docker ps` 57 | 58 | and see the **PORTS** column of your crate containers. Choose a port from one of them starting with `32`. Then replace this port in the URL pointing to the webinterface of crate. This is the webinterface of another container. 59 | Using the query statement above you should see the same results as on all other webinterfaces of crate. Thus, all crate nodes are fully synchronized. 60 | 61 | 62 | Reset your environment 63 | ---------------------- 64 | 65 | Execute the following command in the folder in which the *.yml* files reside: 66 | ``` 67 | docker-compose -f loadbalancing-applications.yml kill && \ 68 | docker-compose -f loadbalancing-applications.yml rm -f 69 | ``` 70 | -------------------------------------------------------------------------------- /voting_app_with_crate.io/voting_app_with_crate.yml: -------------------------------------------------------------------------------- 1 | # 2 | # scale mini webserver 3 | # 4 | 5 | crate-master: 6 | image: hypriot/rpi-crate:0.54.1 7 | ports: 8 | - 4200:4200 9 | environment: 10 | - CRATE_HEAP_SIZE=16m 11 | 12 | crate-slave: 13 | image: hypriot/rpi-crate:0.54.1 14 | ports: 15 | - 4200 16 | environment: 17 | - CRATE_HEAP_SIZE=16m 18 | 19 | demo-voting: 20 | image: firecyberice/armhf-demowebserver:voting 21 | ports: 22 | - 80:80 23 | links: 24 | - crate-master:crate 25 | environment: 26 | - CRATE_REST_API=crate:4200 27 | 28 | --------------------------------------------------------------------------------