Cluster com Docker Swarm e RPi

gorgonas-1_abertura.png

Era algo que estava com vontade de fazer já há algum tempo; utilizar o Docker Swarm para implementar um pequeno cluster com os meus Raspberry Pi e isto aqui é um relato/guia dos passos necessários para montá-lo, configurá-lo e, claro, usá-lo.

Visão geral do cluster

gorgonas-1_visao-geral

Este pequeno cluster foi montado com meus três Raspberry Pi (todos são”model B” mas cada um de a uma geração distinta, ou seja, um RPi1, RPi2 eRPi3), três patch cords CAT5E, três cabos USB→microUSB e uma fonte de alimentação USB de 15W para alimentá-los — a cor diferente nos cabos é apenas para ajudar a diferenciá-los.

Instalação do HypriotOS

gorgonas-1_atualizando

O HypriotOS é uma customização do Raspbian, mantida pelo pessoal do Hypriot e que tem como objetivo ser uma distribuição pronta para usar Docker em ARM — não necessariamente Raspberry Pi — e com versões mais atualizadas do que aquelas que geralmente encontram-se empacotadas.

A instalação é a parte mais “simples”. Basta baixar a última versão do HypriotOS e transferir¹ para os cartões de memória SD/microSD para criar o “disco” dos futuros nós — no meu casoa s três górgonas²: stheno (RPi1/verde), euryale (RPi2/azul) e medusa (RPi3/vermelho).

Depois é conectar todos os cabos e ligar. Daí aproveitei também para (i) atualizar o sistema operacional e (ii) colocar o SSH sem senha antes de seguir adiante. E como cada nó informa seu nome via Multicast DNS fica fácil acessá-los diretamente com stheno.local, euryale.local e medusa.local ao invés dos endereços IP.

(¹) Usei a ferramenta que eles mesmos desenvolveram, a flash, que me deixa alterar o nome do host.

(²) Uma curiosidade pois não conhecia a ilustração das irmãs górgonas feita pelo Tobias White quando tive a ideia de usar cores diferentes para cada nó, uma interessante coincidência.

Configuração

Como o HyprotOS já tem o Docker devidamente instalado e configurado pode-se seguir para a criação do cluster, ou seja, a inicialização do swarm a partir de um dos hosts. Optei por usar o medusa.local, então:

$ docker swarm init

Terminada a inicialização este nó se torna o mestre — ou leader — e a saída do próprio comando já informar o que será necessário fazer para acrescentar os demais ao cluster:

...
To add a worker to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-«HASH» \
    192.168.0.26:2377
...

Basta executar o comando nos outros nós — euryale.local e stheno.local:

$ docker swarm join token SWMTKN-1-«HASH» 192.168.0.26:2377

Para verificar quem faz parte do cluster use:

$ docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
2abo3n3ssbzqhcy726acsq97c    stheno    Ready   Active        
fl2e7tigtpo5enmqwyu9wv4vo *  medusa    Ready   Active        Leader
xt8err6x812t1kp7zesekb8ez    euryale   Ready   Active

E o cluster está devidamente pronto para ser utilizado.

Criando os serviços

Operando com o Docker em modo swarm, você criar serviços (por exemplo, servidor web, gerenciador de banco de dados etc) que são associados a contêineres e onde são definidos parâmetros como a quantidade de instâncias (réplicas) executadas simultaneamente, portas exportadas etc.

Servidor web

gorgonas-1_http.png

Para não inventar muito, algo bem simples e usando o próprio contêiner com servidor web que o pessoal do Hypriot disponibiliza para rodar no Raspberry Pi.

Assim, a partir do medusa.local:

$ docker service create \
  --name web \
  --publish 8000:80 \
  --replicas 3 \
  hypriot/rpi-busybox-httpd

Isto criará um serviço (“web”), mapeando a porta TCP 80 dentro do contêiner para ficar visível na porta TCP 8000 e sempre com três réplicas em execução — obviamente um contêiner em cada um dos nós, ao menos no início.

Instalando o Portainer

Para ajudar um pouco a utilização do cluster achei interessante instalar também o Portainer que é uma interface web para o gerenciamento do Docker e de clusters Swarm. Como ele é disponibilizado como um contêiner sua instalação é simples e rápida.

De acordo com a documentação, em medusa.local, basta necessário criá-lo como se fosse um serviço:

$ docker service create \
  --name portainer \
  --publish 9000:9000 \
  --constraint 'node.role == manager' \
  --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
    portainer/portainer \
  -H unix:///var/run/docker.sock

Ele estará acessível em medusa.local:9000 e no primeiro acesso pedirá para ser definida a senha do usuário “admin” (outros usuários poderão ser criados depois).

Instalando o NGINX

Isto não faz parte do cluster mas decidi que seria interessante usar o nginx para rotear e distribuir a carga entre os nós do cluster e assim tornar a visão que o serviço “web” tem para o mundo exterior como se fosse uma coisa só. Já que não sobraram mais computadores disponíveis³, resolvi utilizar meu próprio notebook para a tarefa, então:

$ sudo apt install nginx

E acrescentando um arquivo de configuração próprio para o cluster e que faz o devido redirecionamento — para simplificar mantive a porta TCP 8000:

$ cat /etc/nginx/conf.d/gorgons.conf 
upstream gorgons {
  least_conn;
  server stheno.local:8000 max_fails=3 fail_timeout=60 weight=1;
  server euryale.local:8000 max_fails=3 fail_timeout=60 weight=3;
  server medusa.local:8000 max_fails=3 fail_timeout=60 weight=6;
}
server {
  listen 8000 default;
  location / {
    proxy_pass http://gorgons;
  }
}

O conjunto de valores definidos em weight fazem parte da minha “distribuição de carga” e indicam que a cada 10 requisições que chegam ao proxy elas serão distribuídas para o cluster da seguinte forma:

  • 1 requisição vai para o RPi1 (ARMv6@700MHz);
  • 3 requisições vão para o RPi2 (4×ARM7@900MHz) e
  • 6 requisições vão para o RPi3 (4×ARM7@1.2GHz).

Então é (re)iniciar nginx e usar o curl para acessar a página web:

$ curl 192.168.0.23:8000

E o acesso será redirecionado de forma transparente para algum dos três nós do cluster.

(³) Acabaram-se tanto os computadores como também as portas de rede do roteador e não estava querendo usar a rede sem fio.

Conclusão

Montar o cluster foi divertido! Do ponto de vista de capacidade de processamento ele é um cluster com 9 processadores — operando em frequências distintas — e com um total de 2,2 GiB de RAM. É limitado mas ainda assim uma ferramenta bastante interessante para se testar “no metal” tanto os recursos disponíveis no Docker.

Aliás, encontrei alguns pequenos “problemas” que careceriam de um certo ajuste fino (por exemplo, a ordem como os nós do cluster são inicializados é importante) mas deixarei isto para uma outra oportunidade.

E uma última observação : É possível replicar os passos acima substituindo o HypriotOS por qualquer outra distribuição com uma versão atual (igual ou superior a 1.12)  do Docker e criar este mesmo cluster com outro hardware ou mesmo com máquinas virtuais — mas é claro neste caso não daria para fotografá-lo… 🙂

Anúncios

Um comentário sobre “Cluster com Docker Swarm e RPi

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s