Compartilhando volumes entre nodes do Swarm com NFS
Tags: docker
Published: 2020-10-11 12:45:46

>Quando precisamos persistir dados, pensamos nos volumes, porém como estamos trabalhando com orquestração o *Swarm* não faz o compartilhamento de dados entre os nodes.

![volumes-shared-storage](https://dev-to-uploads.s3.amazonaws.com/i/xtgbeqryznkq89zlefa9.jpg)

####O que precisamos e onde vamos chegar com o artigo.
Nesse artigo vou mostrar como fazer com NFS esse compartilhamento de dados entre nos nodes, é simples e pode ser útil em alguns casos de usos. Utilizarei três maquinas *EC2 da AWS* com o sistema *Ubuntu*, *Docker* e o *Swarm* previamente instalado e configurado para formar nosso *cluster*, e como resultado final vamos ter a mesma página estática em todas requisições feitas na porta 80 de um container nginx.

####1. Configurando o NFS em uma maquina para ser nosso "server".
Vamos escolher um node e também um diretório que será compartilhado, vou chamar esse node escolhido de *Micro1*.
Rode o seguinte comando:
`sudo apt install nfs-kernel-server` para instalar o *nfs "server"* e vamos alterar o arquivo de configuração dele `nano /etc/exports`  adicione a seguinte linha `/opt/site *(rw,sync,no_subtree_check)` salve e feche o arquivo, estamos compartilhando o diretório `/opt/site` que vamos criar no *Micro1* para qualquer ip, ao invés de * podemos colocar o ip de nossos clientes que no caso é os outros dois nodes, crie a pasta a ser compartilhada `mkdir /opt/site` e em seguida vamos reiniciar o *nfs* `sudo systemctl restart nfs-kernel-server`, tudo isso ainda na instância *Micro1*.

![1](https://dev-to-uploads.s3.amazonaws.com/i/bpwf93ezp1w4cfh7v5g8.PNG)
 
####2. Configurando os outros nodes.
Nos demais nodes, que chamarei de *Micro2* e *Micro3*, vamos instalar o *nfs* como cliente:
`sudo apt install nfs-common` e em seguida podemos ver a lista de exportação rodando o seguinte comando `showmount -e <ip do node Micro1>`, para verificar o ip podemos rodar o comando ifconfig e verificar o ip da rede *eth0*.
Vamos montar essa exportação no *Micro2* e *Micro3* `sudo mount -t nfs <ip do node Micro1>:/opt/site /var/lib/docker/volumes/compartilhando-volume`
Isso significa que estamos *linkando* o */opt/site* do *Micro1* para o diretório */var/lib/docker/volumes/compartilhando-volume* de onde está sendo executado.

####3. Vamos testar se está funcionando?
No *Micro1*  crie uma pasta chamada *_data* no diretório */opt/site/*:
`mkdir  /opt/site/ _data`.
![1.5](https://dev-to-uploads.s3.amazonaws.com/i/tf2ezano5t2u1ot4urf4.PNG)
Nos outros nodes podemos verificar se existe a pasta *_data* que criamos:
 `ls /var/lib/docker/volumes/compartilhando-volume`
![2](https://dev-to-uploads.s3.amazonaws.com/i/9be41zlqo8i8z4rahswq.PNG) 
Veja que a pasta que criamos em */opt/site* do *Micro1* está criada no `/var/lib/dockeer/volumes/compartilhando-volume`do *Micro2* e *Micro3*.

####4. Ainda temos problemas.
No *Micro1* não estamos apontando `/opt/site` para `/var/lib/docker/volumes/compartilhando-volume`, vamos fazer isso agora.
Vamos criar finalmente o volume no docker `docker volume create compartilhando-volume`
![Criando volum](https://dev-to-uploads.s3.amazonaws.com/i/q61nl5vmx0nlqsfnz5n8.PNG) 
Apague a pasta *_data* para não conflitar com a pasta que criamos anteriormente `rm -rf /var/lib/docker/volumes/compartilhando-volume/_data`
Rode o comando `ln -s /opt/site/_data/ /var/lib/docker/volumes/compartilhando-volume/_data` para deixar ambos diretórios síncronos, para testar crie um arquivo em qualquer dos dois diretórios e no outro o mesmo arquivo é visível.

####5. Compartilhando o arquivo.
No *Micro1* vamos criar um arquivo *index.html* em `/opt/site/_data` ou em `/var/lib/docker/volumes/compartilhando-volume/_data` com o seguinte comando:
`nano /var/lib/docker/volumes/compartilhando-volume/_data/index.html` e escrever qualquer coisa dentro.
Podemos verificar que nos demais nodes o arquivo já está dentro do diretório `/var/lib/docker/volumes/compartilhando-volume/_data`.

####6. Criando nosso serviço.
Vamos criar um serviço do nginx em nosso cluster com o seguinte comando `docker service create --name nginx --replicas 3 -p 8080:80 --mount type=volume,src=compartilhando-volume,dst=/usr/share/nginx/html nginx`
![Serviço criado](https://dev-to-uploads.s3.amazonaws.com/i/jm0kka7ttyxjxsix2qbf.PNG)
 
####7. Testando as requisições.
Agora podemos testar tudo o que fizemos, svamos dar um `curl localhost:8080` varias vezes e sempre teremos o mesmo resultado pois fizemos todo procedimento de cliente no *Micro2* e no *Micro3*, e a pasta */var/lib/docker/volumes/compartilhando-volume* são síncronos nas 3 instâncias.
![Testando](https://dev-to-uploads.s3.amazonaws.com/i/xutamo7zaixlcsvart8w.PNG)
 
####8. Revertendo o procedimento e provando o funcionamento.
Vamos em algum de nossos nodes clientes nfs(Micro2 ou Micro3) e desmontar a montagem com o seguinte comando `umount /var/lib/docker/volumes/compartilhando-volume` e em seguida vamos apagar o serviço criado `docker service rm nginx` e subir novamente `docker service create --name nginx --replicas 3 -p 8080:80 --mount type=volume,src=compartilhando-volume,dst=/usr/share/nginx/html nginx` agora novamente faça varias requisições `curl localhost:8080` e veremos que quando a requisição que cai no container que está no node que revertemos o processo ela aparece o html padrão do nginx.

## Referências
[Jeferson Fernando do Linux Tips](https://www.linuxtips.io/)
[Documentação do swarm](https://docs.docker.com/engine/swarm/)