Servizi in Docker Swarm
Caratteristiche di un Servizio
Il deployment di servizi è lo scopo principale di utilizzo di Docker Swarm.
Un servizio è un certo numero di task implementati su uno o più nodi del cluster.
Il nostro applicativo è tipicamente architettato in una serie di servizi comunicanti e cooperanti per uno scopo definito - Architettura a Microservizi.
Almeno uno dei servizi componenti è visibile dall'esterno del cluster e serve a comunicazioni tra il servizio (interno al cluster) e i clients che usano il servizio (esterni).
In Docker Swarm vi sono due tipi di servizi:
-
Servizi replicati : task che viene eseguito in un numero di repliche predeterminate. Ogni replica è un’istanza del container definito nel servizio.
-
Servizi globali : ogni nodo disponibile nel cluster ha un task per il relativo servizio. Se si aggiunge un nuovo nodo al cluster, lo swarm manager gli assegnerà immediatamente un task di quel servizio.
Deployment di Servizio Replicato
Deployment di servizio replicato allo swarm, con una sola replica:
dk docker service create --name my-nginx --replicas 1 -p 8000:80 nginx
Si può omettere l'opzione --relicas 1
: di default un servizio è replicato con una replica.
Viene prodotto un rapporto del tipo:
hefgmk41sne1bjp0y9axrlyvf
overall progress: 0 out of 1 tasks
1/1: preparing
La stringa è l'identificativo del servizio.
Il servizio è in preparazione e non è ancora pronto, p.es. deve ancora scaricare l'immagine nginx
dal Docker Hub.
Si può attendere o premere Ctrl-C
: in tal caso la preparazione del servizio procede in background e ritorna il pronto.
Controllare lo stato del servizio con:
dk docker service ps my-nginx
Il risultato è simile a:
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
w8yl8k492rkj my-nginx.1 nginx:latest worker-1 Running Preparing 27 seconds ago
Il nodo a cui il servizio è stato assegnato sta ancora compiendo il pull dell'immagine e quindi il suo stato è Preparing.
Dopo un certo periodo di tempo, ripetendo il comando, il risultato è simile a:
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
ixf8qekp6lz0 my-nginx.1 nginx:latest worker-1 Running Running 4 minutes ago
Vincoli al servizio
Di solito un servizio è assegnato ad un nodo casuale dello swarm.
Possiamo desiderare che un determinato servizio venga assegnato ad un certo nodo, o che non venga assegnato ad un nodo.
Possiamo indicarlo specificando dei vincoli (constraints) al lancio del servizio. Per esempio:
dk docker service create --name my-nginx1 --replicas 1 -p 8888:80 \
--constraint node.hostname!=manager \
nginx
Viene richiesto di non installare il servizio sul nodo il cui hostname è manager
.
Gli operatori accettabili nei constraint sono ==
(uguale) e !=
(diverso da).
Servizi diversi devono avere nomi diversi. e non devono esservi collisioni nel port mapping.
Tipici constraints sono:
node.id
- listato condocker node ls
node.hostname
- listato condocker node ls
node.ip
node.role
- (manager|worker)node.platform.os
- (linux|windows|ecc.)node.platform.arch
- (x86_64|arm64|386|etc.)node.labels
- vuoto di default
Acccesso al Servizio
Dare il comando:
dk curl localhost:8000
Il risultato è la pagina di benvenuto di Nginx.
Questo avviene poichè nel lancio del servizio avevamo specificato il port mapping -p 8000:80
: se nginx ascolata sulla porta 80
del contenitore in cui gira, viene reso accessibile alla porta 8000
a livello del cluster.
Non importa in quale nodo del cluster sia il contenitore che implementa Nginx. Chiedere l'accesso al master causa una redirezione interna a tale nodo.
Si può anche dare tale comando su qualsiasi nodo del cluster, con uguale funzionamento. Ma solitamente si interagisce dall'esterno coi servizi, inviando i comandi al nodo master.
Accesso da browser
Occorre conoscere l'indirizzo IP del nodo manager
. Si può scoprire con:
docker exec -ti manager docker info | grep -w "Node Address" | awk '{print $3}'
Nel nostro caso:
192.168.77.2
In caso di presenza di pià manager va bene l'indirizzo IP di uno qualsiasi di essi.
Puntare un browser, sulla macchina host, a: 192.168.77.2:8000
.
Ispezione di Servizi
Tutti i Servizi
Listare tutti i servizi con:
dk docker service ls
produce un rapporto del tipo:
ID NAME MODE REPLICAS IMAGE PORTS
hefgmk41sne1 my-nginx replicated 1/1 nginx:latest *:8000->80/tcp
Singolo Servizio
Ispezionare un singolo servizio:
dk docker service inspect --pretty my-nginx
Produce un rapporto sulle proprietà e lo stato del servizio.
Il rapporto è in formato YAML. Senza l'opzione --pretty
il rapporto è in formato JSON.
Anche:
dk docker service ps my-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
clb3qhx1ffyl my-nginx.1 nginx:latest worker-1 Running Running 8 minutes ago
Da cui vediamo che il task singolo che implementa il servizio è stato assegnato al nodo worker-1
.
Per vedere il contenitore che implementa il servizio:
docker exec -ti worker-1 docker ps
Scalare il Servizio
Per passare a 3 task che implementano il servizio:
dk docker service scale my-nginx=3
e il responso immediato è:
my-nginx scaled to 3
overall progress: 1 out of 3 tasks
1/3: running
2/3: preparing
3/3: preparing
Dopo un breve tempo si può vedere l'avvenuta operazione di scala:
dk docker service ps my-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
clb3qhx1ffyl my-nginx.1 nginx:latest dockub Running Running 21 minutes ago
alqjhs0zemk0 my-nginx.2 nginx:latest 9dd3a81d7be6 Running Preparing 2 minutes ago
tllpd8kuuit6 my-nginx.3 nginx:latest 375e7ceddeb5 Running Preparing 2 minutes ago
E' possibile scalare un servizio a 0 repliche, p.es.:
dk docker service scale my-nginx=0
Il servizio non viene rimosso, ma vi sono al momento 0 nodi che lo eseguono.
Servizio su nodo specifico
Alle volte desideriamo che il container di un determinato servizio venga installato su uno specifico nodo.
Questo si ottiene con l'uso di constraints (vincoli).
Per esempio desideriamo installare il Visualizer sul nodo manager del cluster.
dk docker service create \
--name=viz \
--publish=8080:8080 \
--constraint=node.hostname==manager \
--mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
--detach=true \
dockersamples/visualizer
Verifichiamo il deployment in corso del servizio con:
dk docker service ps viz
e attendiamo che arrivi nello stato di Running.
Notiamo che il container è stato posto sul nodo manager.
Deployment di Servizio Globale
dk docker service create --name redis --mode global
--publish 6379:6379 redis
L'opzione --mode global
rende il servizio globale.
L'assenza di tale opzione denota di default un servizio replicato con una replica.
La presenza dell'opzione, p.es., --replicas 3
denota un servizio replicato con 3 repliche.
Rimuovere un Servizio
Col comando, p.es.:
dk docker service rm my-nginx
viene rimosso il servizio my-nginx
su tuti i nodi che lo stavano eseguendo.