No post anterior falamos sobre o que é o Docker, e como rodar containers em cima da Raspberry Pi. Esse post, porém, vai além do básico, mostrando como criar um cluster com Raspberry Pi via software com Docker Swarm e rodar várias instâncias de uma mesma aplicação. Este é basicamente o conceito de nuvem, que permite a escalabilidade de aplicações de maneira horizontal, colocando mais instâncias da mesma em execução.
Instâncias?
No post anterior, mostramos a execução de dois containers, um MySQL e um WordPress. Daquele jeito, apenas uma instância de cada container vai ser executada, o que nos atende muito bem para cenários de teste e de baixo acesso. Mas e se eu quiser utilizar o poder computacional de vários computadores (no nosso caso, placas) para poder melhorar a performance da minha aplicação? Nesse caso, eu teria duas opções: a primeira seria o escalonamento vertical, onde eu aumentaria a memória e processador da minha máquina. Até certo ponto, isso pode me atender, mas se tratando de uma Raspberry Pi, é impossível fazer um upgrade assim…
A outra opção é o escalonamento horizontal, que permite aumentar a quantidade de containers que rodam a aplicação. É chamado de escalonamento horizontal pelo fato de ser uma série de computadores/placas conectados em rede, ocorrendo um balanceamento de carga para cada requisição que chega à aplicação. Na prática, isso permite que um usuário X seja redirecionado para o container Y, enquanto o usuário X2, que acessa a aplicação imediatamente após o usuário X, seja redirecionado para o container Y2, de maneira automática. Utilizando o Docker Swarm (ou outro orquestrador de containers, como Kubernetes), isso é feito sem a necessidade de configurações complexas.
Na imagem acima, podemos ter uma visão geral de como vai ficar nosso mini-cluster. Serão três placas formando o cluster com Raspberry Pi, sendo que uma das placas será a versão Raspberry Pi Zero W, e as outras duas, a versão Raspberry Pi 3. Cada uma vai ter uma instalação do Docker, e todas elas vão se comunicar através do Docker Swarm.
Um cluster pra chamar de seu
Recapitulando então, vamos precisar de duas ou mais placas para montar o nosso cluster com Raspberry Pi, sendo que no exemplo agora usarei três. Além disso, é necessário ter o Raspbian Stretch e o Docker instalado em cada uma delas.
curl -sSL https://get.docker.com | sh sudo usermod -aG docker pi sudo systemctl enable docker sudo reboot -h now
Verifique se tudo correu bem com o comando
docker ps
Para ficar mais fácil, cada placa na minha rede possui um IP fixo, 192.168.1.21, 192.168.1.22 e 192.168.1.24. Como estamos lidando com um mini-cluster, cada placa será o mesmo que um “nó” (node) do cluster. Escolha um nó pra ser o “principal” (manager), e os outros dois serão apenas “trabalhadores” (workers). No meu caso, será o nó 192.168.1.21. No nó principal, primeiro vamos baixar a imagem Visualizer, que vai permitir a visualização de nós e containers para cada placa. A imagem foi criada por Alex Ellis, e está disponível no Docker Hub.
docker pull alexellis2/visualizer-arm
Docker Swarm, start!
Iniciar um cluster com Docker Swarm é muito simples. Reiterando, o IP da minha placa principal é 192.168.1.21, e estou executando o seguinte comando nela, através de SSH
docker swarm init --advertise-addr 192.168.1.21
Ele, por sua vez, me retorna a seguinte mensagem de êxito
Swarm initialized: current node (xzkp9uucjrj4ose0yfpcdsjvt) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-4ayyu7shasjzry6j6q007nd3ltal6ett0dxny8nrm0gr21z6be-c6b69sxqjgcpbeetqt4ww4vyg 192.168.1.21:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Para ver os nós que meu cluster agora tem, posso executar o comando
docker node ls
Hora de subir o container do Visualizer! Note que estou dizendo para o container expor a porta 8080 interna como 8880 externa. Isso significa que, dentro do container, a aplicação de visualização vai rodar normalmente na porta 8080, mas de fora conseguirei acessá-la pela porta 8880.
docker service create --name cluster --publish 8880:8080/tcp --constraint node.role==manager --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock alexellis2/visualizer-arm:latest
Feito isso, meu serviço de visualização já está executando no primeiro nó (manager) do cluster Docker.
Com essa imagem podemos ver que, o serviço chamado cluster tem uma instância rodando no nó raspberrypi, do tipo manager. Mas de nada adianta um cluster se ele contém apenas um nó!
Acoplando os nós do cluster com Raspberry Pi
Com o Docker já instalado nas outras duas placas, é hora de fazê-las enxergar o nó principal. Note que, quando inicializamos o Docker Swarm, na mensagem de êxito nos foi passado um comando para adição de outros nós. Iremos executar esse comando em cada um dos outros nós (no meu caso, nos IPs 192.168.1.22 e 192.168.1.24)
docker swarm join --token SWMTKN-1-4ayyu7shasjzry6j6q007nd3ltal6ett0dxny8nrm0gr21z6be-c6b69sxqjgcpbeetqt4ww4vyg 192.168.1.21:2377
Caso dê tudo certo, agora o Visualizer vai exibir os três nós, da seguinte maneira
Temos agora um cluster com três nós, e apenas um container executando! Deixe de lado os nós trabalhadores, e vamos voltar ao nó principal.
Hora do balanceamento de carga
Pelo post anterior, baixamos a imagem do MySQL e do WordPress, ambas para arquitetura ARM. Agora mudaremos um pouco a estrutura do que criamos anteriormente, removendo o container do WordPress criado fora do Docker Swarm.
docker container rm wordpress --force
Infelizmente, a versão ARM do MySQL não suporta a execução dentro do Docker Swarm, o que nos limita a apenas uma instância, fora do cluster. Execute o comando docker run normalmente, para ter certeza de que o container do MySQL está executando.
docker run --name mysql-wordpress -e MYSQL_ROOT_PASSWORD=Aa.12345678 -d hypriot/rpi-mysql
Dessa maneira, teremos um container MySQL e cinco containers do WordPress. Execute o comando a seguir, fazendo com que o WordPress enxergue o MySQL e conte com cinco instâncias, notando o parâmetro replicas:
docker service create --name wordpress -p 8080:80 -d -e WORDPRESS_DB_HOST=192.168.1.21 -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=Aa.12345678 -e WORDPRESS_DB_NAME=wordpress --replicas 5 wordpress
A mágica acontece quando, tendo três nós interligados, o Docker Swarm consegue balancear cada container para um determinado nó, baseado em sua disponibilidade, de acordo com a imagem a seguir
Em caso de apenas um nó, a placa ficaria sobrecarregada com cinco containers rodando ao mesmo tempo (fora o container do Visualizer)
Um outro comando útil é o scale, que permite escalar o WordPress em quantos containers sua placa aguentar, ou até reduzir para somente um.
docker service scale wordpress=1
Considerações finais
Como citado acima, a imagem de arquitetura ARM do MySQL não suporta o Docker Swarm. Isso nos deixa com um gargalo forte de banco de dados, pois de nada adianta ter cinco aplicações WordPress consumindo um único banco de dados. A vantagem seria quando tivéssemos também cinco instâncias de MySQL, contando com replicação entre si.
Gostou do post Cluster com Raspberry Pi e Docker Swarm? Deixe seu comentário logo abaixo.
Boa tarde, dessa forma todos os Containers terão os arquivos das paginas ? (.php, .html )
mas estaram utilizando o mesmo banco de dados. Então independende de qual nó eu esteja acessando a pagina, ela vai usar o mesmo banco de dados.
Teria um exemplo usando tambem a redundancia do banco de dados ?
Não existe ALGUM outro banco que seja compatível com o Swarm na arquitetura ARM?
Oi Roger, boa tarde.
Existe sim, no DockerHub você pode achar, por exemplo, o Postgres: https://hub.docker.com/_/postgres/
Ele tem versões pra arm32v5, arm32v7 e arm64v8.
Acredito que o MongoDB também tenha, mas não versões oficiais. Compensa dar uma olhada se você acha alguma imagem por lá que te atenda.
Abraços!