Usando Docker Swarm para deploy e service discovery de serviços

Walisson de Deus Casonatto
Quick Mobile Labs
Published in
2 min readSep 27, 2016

Quanto maior fica sua arquitetura de microservices mais dificuldades aparecem. Você passa a ter que se preocupar com fatores como: como fazer um deploy contínuo, onde fazer esses deploys, como os servicos vão comunicar entre si etc. Para nossa felicidade, foi habilitado no Docker 1.12 o modo Swarm que facilmente resolve esses problemas.

Nesse guia utilizaremos um cluster de Docker Swarm. Se você não sabe ainda como fazer um cluster de Docker Swarm, aprenda como fazer aqui.

Service Discovery

O primeiro passo para habilitar o Service Discovery é: os servicos que se comunicam deve estar em uma rede comum.

docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
--opt encrypted \
refresh-network

Alguns hosts não funcionam com o modo encrypted (ainda não sei o porque, se você sabe comenta aí em baixo). Caso você estiver usando uma VM, por exemplo, use secure:

docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
--opt secure \
refresh-network

Networking no Swarm exige as seguinter portas liberadas:
udp 4789 Data plane (VXLAN)
tcp/udp 7946 Control plane

Iniciando Serviços

Agora nós podemos iniciar nosso serviço, que nesse exemplo será um serviço Redis.

docker service create --name redis-refresh --network refresh-network --update-delay 10s redis

Note que eu não publiquei nenhuma porta para o Redis. Eu fiz isso pois nossos serviços irão se comunicar através da network que eles estão (por isso a necessidade de criar uma network em comum para todos). Você apenas deve utilizar o publish quando você precisa acessar de forma pública o serviço.

docker service create --name refresh --publish 80:80 --network refresh-network --update-delay 10s walissoncasonatto/go-refresh

Neste outro comando, a porta 80 foi publicada. Com isso, independente de qual host você acessar na porta 80, este serviço responderá. Sim, no Docker Warm você pode publicar apenas um servico por porta, caso queira publicar mais de um será necessário um Proxy.

O serviço que expomos tem o seguinte código:

package mainimport (
“fmt”
“net/http”
“github.com/fiorix/go-redis/redis”
)
func handler(w http.ResponseWriter, r *http.Request) {
cliente := r.URL.Path[1:]
c := redis.New(“redis-refresh:6379”)
c.SAdd(“clients”,cliente)
c.IncrBy(cliente,1)
clientes,_ := c.SMembers(“clients”)
for _,element := range clientes {
quantidade,_ := c.Get(element)
fmt.Fprintf(w, “%s : %s \n”, element,quantidade)
}
}
func main() {
http.HandleFunc(“/”, handler)
http.ListenAndServe(“:80”, nil)
}

Note que na conexão com o redis apenas especificamos o nome do serviço com o qual queremos nos comunicar. É importante destacar que contanto que eles estejam na mesma network (não importa se eles estão em hosts diferentes), o Docker Swarm irá fazer o Service Discovery.

Se você está se perguntando o que a configuração — update-delay 10s significa: ele serve para o Roling Deploy ;)

Vamos escalar o serviço e atualizar a imagem:

docker service scale refresh=3
docker service update --image walissoncasonatto/go-refresh:novo refresh

Acesse pelo navegador o serviço. Você pode continuar atualizando a página enquanto o update é feito e poderá observar que não haverá downtime.

Simples, não? :)

--

--