Docker e orchestration, creare un ambiente di produzione con Swarmkit

18 ottobre 2016

 

Questo articolo è un estratto del libro Drive your boat like a Captain un eBook scritto da Gianluca Arbezzano su Docker in produzione e orchestration.

Docker dalla release 1.12 fornisce un sistema di orchestration built-in che permette di unire e gestire più Docker Engine in un cluster. Questa nuova feature ci permette di distribuire container su più nodi e quindi prepararsi a gestire un ambiente di produzione con Docker.

Ci sono altri framework di Orchestration che usano Docker come container runtime, Kubernetes, Swarm (inteso come docker/swarm un progetto sempre di docker ma non built-in), Mesos e molto altri.

Questa nuova funzionalità si basa su un progetto chiamato SwarmKit: una serie di primitive che permettono di gestire applicazioni distribuite come node discovery, una implementazione di raft basata su coreos/raft e altro ancora.

Qui dalla versione Docker 1.12 in poi possiamo notare alcuni nuovi comandi:

docker swarm
docker node
docker service

Il primo comando ci permette di inizializzare e gestire il nosto cluster, il secondo di ispezionare i nostri nodi ed il terzo ad avviare, gestire e scalare le nostre applicazioni.

Possiamo partire subito con un esempio pratico utilizzando docker-machine per accendere 3 nuovi server nella nostra macchina locale utilizzando VirtualBox, per questo motivo occorre verificare di avere installato dia VitualBox, sia docker-machine, oppure l’intero stack che si può installare facilmente seguendo le indicazioni sul sito Docker Toolbox.

Per accendere i 3 nodi utilizziamo i comandi:

docker-machine create -d virtualbox sw1
docker-machine create -d virtualbox sw2
docker-machine create -d virtualbox sw3

A questo punto possiamo entrare nella prima macchina sw1, che sarà il nostro master. In un cluster swarm ci sono 2 attori: i master e gli workers. All’interno dei nodi master vengono salvate le informazioni relative ai nostri containers e alla loro distribuzione, sono il cervello del cluster. In caso di failover, l’algoritmo Raft eleggerà un nuovo leader tra i master ancora attivi, è quindi importante, in un contesto di produzione assicurarsi di avere un’architettura multi master, cosí da evitare singoli punti di fallimento.

docker-machine ssh sw1

Una volta all’interno possiamo inizializzare il nostro cluster con il comando:

docker swarm init --advertise-addr  192.168.99.100

--advertise-addr è un opzione utile a comunicare su quale interfaccia di rete avverranno le comunicazioni tra i nodi, per sapere l’ip da assegnare utilizziamo invece il comando ifconfig.

L’output di questo comando contiene un’informazione essenziale per aggiungere nodi all’interno del cluster, nell’esempio:

docker swarm join \
    --token SWMTKN-1-4bl65z15zd6nt4y0xc0mf639z4hhwphqn5l523bo6ws0yp230v-b96hecfns0k8ey3pasvwcp7gt \
    192.168.99.100:2377

Questo è il comando da utilizzare all’interno dei nostri futuri nodi per poterli aggiungere al cluster swarm.

Procediamo quindi uscendo dalla macchina e entrando in sw2 e sw3 eseguendo appunto il comando che docker ci ha suggerito. Poi verifichiamo che il nostro cluster sia composto da 3 nodi. Per farlo usciamo dalla nostra macchina, torniamo al nostro terminale, utilizziamo docker-machine per comunicare al docker client locale l’indirizzo del nostro master, servendoci del comando:

eval $(docker-machine env sw1)

A questo punto il nostro client sta comunicando con il nostro master e possiamo eseguire:

docker node ls
L’output ci dovrebbe mostrare i nostri 3 nodi, pronti per essere utilizzati. Procediamo ora con il deploy di una nostra applicazione.

Per il nostro esempio utilizziamo gianarb/micro:1.0.0 un’applicazione scritta in go presa su GitHub. Si tratta di un semplice server HTTP che espone la porta 8000, ha una homepage alla rotta / the mostra l’ip del container in cui l’applicazione è eseguita. Questo piccolo servizio è molto utile perché quello che ci aspettiamo di vedere è la stessa applicazione distribuita in più container, su diversi nodi, quindi con ip diversi in base al container.

Prima di tutto creiamo un network:

docker network create -d overlay micro-net

Tutti i containers deployati all’interno di questa rete potranno comunicare tra di loro, in questo specifico esempio non abbiamo la necessità di far comunicare due container, perché la nostra applicazione non ha una dipendenza. Se invece utilizzassimo per esempio un databae mysql, dovremmo poi associare questa rete al container che ospita mysql.

Docker supporta diversi driver, perciò sentiamoci liberi di creare plugin per estendere le funzionalità del network, nel nostro caso overley è il driver di default ed permette ai nostri container di comunicare anche se non si trovano nello stesso nodo.

Creare un servizio

A questo punto creiamo il nostro primo servizio:

docker service create --name micro -p 8000 --replicas 1 --network micro-net gianarb/micro:1.0.0
ParametroDescrizione
--nameÈ il nome del servizio
-pÈ la porta che espone il nostro HTTP server
--replicasÈ il numero di tasks da avviare, nel nostro caso 1
--networkPrende il nome del network creato in precedenza e il nome dell’immagine gianarb/micro:1.0.0

Cerchiamo ora di capire come chiamare il nostro servizio e ispezionare il lavoro svolto da Swarm.

docker service ps 

Ci comunica la lista di tutti i nostri servizi, con il comando:

docker service ps <id_servizio>

Possiamo avere un’idea più chiara del numero di task e del loro stato nel nosto caso 1. L’output di questo comando è molto simile a quello che normalmente vediamo quando eseguiamo comandi con Docker in modalità single node o nella modalità originale per intenderci.

Questo perché un servizio è un entità logica che ci permette di gestire un pool di container che Swarm chiama tasks e che scala la nostra applicazione. Nel nostro esempio abbiamo un solo task ovvero un solo container. Tra le informazioni dell’ultimo comando possiamo conoscere in qualche modo i tasks che stanno girando, nel nostro esempio, nel nodo sw1.

A dimostrazione di quanto detto possiamo eseguide l’accesso all’interno del sever su cui gira il container ed eseguire:

docker ps

Qui possiamo notare che sotto il cofano swarm sta gestendo i nostri tasks come normali container. Torniamo allora nel nostro master ed eseguiamo il seguento comando:

docker service inspect 

Questo comando contiene informazione relative al nostro servizio: networking, volumi, nome. Noi stiamo cercando come collegarci ed eseguire la nostra applicazione.

Come ricorderemo al momento della creazione del nostro servizio, abbiamo specificato un parametro -p 8000, docker swarm non espone direttamente la porta richiesta ma crea un proxy che ridirige il traffico al servizio richiesto. Cerchiamo all’interno della risposta il field Endpoint al suo interno troveremo questo:

 "Ports": [
                {
                    "Protocol": "tcp",
                    "TargetPort": 8000,
                    "PublishedPort": 30000
                }
            ],

La porta 8000 del nostro servizio è esposta come porta 30000 da Swarm, questo vuol dire che possiamo prendere un qualsiasi ip del nostro cluster alla porta 30000, nell’esempio 192.168.99.100:30000. Contattando questo url potrete risovlere la nostra applicazione!

Se vuoi aggiornamenti su Docker e orchestration, creare un ambiente di produzione con Swarmkit inserisci la tua e-mail nel box qui sotto:
 
X
Se vuoi aggiornamenti su Docker e orchestration, creare un ambiente di produzione con Swarmkit

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy