Gestione dei Nodi
Aggiunta di nodi worker
Un nodo aggiuntivo deve
- essere creato come contenitore docker
- dare il comando di join allo swarm
Creazione di nodo
Per esempio, per aggiungere il nodo worker-7
, col comando
docker run -d --privileged \
--name worker-7 --hostname worker-7 --net swarmnet \
-v $PWD/worker-7:/var/lib/docker \
doker
Occorre l'opzione --privileged
affinchè il nodo possa settare le regole di iptables
.
E' una buona idea lo host mapping della directory di docker sul nodo ad una directory sulla macchina locale: il pull di immagini già esistenti non viene effettuato.
Join allo swarm
Il token di join può essere chiesto al manager:
docker exec -ti manager docker swarm join-token -q worker
Attenzione che il risultato è una stringa in formato MSDOS, quindi terminata da CR+NL anzichè da solo NL come in Unix.
Per rimuovere il CR e trasformare la stringa in formato Unix:
docker exec -ti manager docker swarm join-token -q worker |tr -d "\r"
Quindi per aggiungere il nodo, p.es. worker-7
allo swarm, nella nostra configurazione:
SWARM_TOKEN=$(docker exec -ti manager docker swarm join-token -q worker)
SWARM_TOKEN=$(echo $SWARM_TOKEN | tr -d "\r")
SWARM_MASTER_IP=$(docker exec -ti manager docker info \
| grep -w "Node Address" | awk '{print $3}')
SWARM_MASTER_IP=$(echo $SWARM_MASTER_IP |tr -d "\r")
docker exec -ti worker-7 docker swarm join \
--token $SWARM_TOKEN $SWARM_MASTER_IP:2377
Procedura shell di aggiunta nodi
Aggiunta di un singolo nodo
Aggiungere un singolo nodo con nome.
vi addnode.sh
# Controllare l'esistenza del manager
if docker ps | grep manager; then
:
else
echo "Node 'manager' does not exist"
echo "Create swarm cluster first"
exit 1
fi
if [ $# -lt 1 ]; then
echo "Must provide name of worker"
echo "Syntax: $0 worker"
exit 2
fi
WORKER=$1
# Il token di join
SWARM_TOKEN=$(docker exec -ti manager docker swarm join-token -q worker)
# I messaggi di Swarm sono in formato MSDOS
# E' necessario togliere il Carriage Return
SWARM_TOKEN=$(echo $SWARM_TOKEN | tr -d "\r")
echo Swarm token is $SWARM_TOKEN
# IP del master
SWARM_MASTER_IP=$(docker exec -ti manager docker info \
| grep -w "Node Address" | awk '{print $3}')
SWARM_MASTER_IP=$(echo $SWARM_MASTER_IP |tr -d "\r")
echo Swarm master IP is $SWARM_MASTER_IP
# Generare il workers e aggiungerlo allo swarm
echo "Starting $WORKER"
docker run -d --privileged \
--name $WORKER --hostname $WORKER --net swarmnet \
-v $PWD/$WORKER:/var/lib/docker \
-v ~/data:/data \
doker
echo "Joining $WORKER"
sleep 5
docker exec -ti $WORKER docker swarm join \
--token $SWARM_TOKEN $SWARM_MASTER_IP:2377
docker exec -ti manager docker node ls
chmode +x addnode.sh
Aggiunta di più nodi
La seguente procedura shell permette di aggiungere un numero di nodi allo swarm:
vi newnodes.sh
# Controllare l'esistenza del manager
if docker ps | grep manager; then
:
else
echo "Node 'manager' does not exist"
echo "Create swarm cluster first"
exit 1
fi
# Il token di join
SWARM_TOKEN=$(docker exec -ti manager docker swarm join-token -q worker)
# I messaggi di Swarm sono in formato MSDOS
# E' necessario togliere il Carriage Return
SWARM_TOKEN=$(echo $SWARM_TOKEN | tr -d "\r")
echo Swarm token is $SWARM_TOKEN
# IP del master
SWARM_MASTER_IP=$(docker exec -ti manager docker info \
| grep -w "Node Address" | awk '{print $3}')
SWARM_MASTER_IP=$(echo $SWARM_MASTER_IP |tr -d "\r")
echo Swarm master IP is $SWARM_MASTER_IP
# Numero di workers
if (($# < 1)) ; then
echo "Must provide number of nodes to add"
echo "Syntax: $0 numnodes"
exit 2
fi
NUM_WORKERS=$1
LAST_WORKER=$(docker ps | grep worker | awk '{n=NF; print $n}' \
| sort | tail -1 | cut -d- -f2)
NEXT_WORKER=$( expr $LAST_WORKER + 1 )
LAST_ADDED=$( expr $NEXT_WORKER + $NUM_WORKERS - 1 )
echo $NUM_WORKERS workers will be added, from $NEXT_WORKER to $LAST_ADDED
# Generare i workers e aggiungerli allo swarm
for i in $(seq "$NEXT_WORKER" "$LAST_ADDED"); do
echo "Starting worker-${i}"
docker run -d --privileged \
--name worker-${i} --hostname worker-${i} --net swarmnet \
-v $PWD/worker-${i}:/var/lib/docker \
-v ~/data:/data \
doker
echo "Joining worker-${i}"
sleep 3
docker exec -ti worker-${i} docker swarm join \
--token $SWARM_TOKEN $SWARM_MASTER_IP:2377
done
docker exec -ti manager docker node ls
Renderla eseguibile:
chmod +x newnodes.sh
Eseguirla col comando, per esempio per aggiungere 3 nodi:
./newnodes.sh 3
Rimozione di nodo
Il nodo da il comando per lasciare lo swarm.
Per esempio per worker-7
:
docker exec -ti worker-7 docker swarm leave
Il nodo lascia lo swarm.
Attenzione che il nodo rimane però nella tabella dei nodi del manager. Infatti:
dk docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
.....
aj0ope2gl1u90dptwv71fo7ta worker-7 Down Active 26.1.5
Lo STATUS del nodo è marcato come Down
.
Per evitare eccessiva digitazione è stato creato l'alias:
alias dk='docker exec -ti manager'
Il contenitore docker worker-7
naturalmente continua ad esistere.
Per rimuoverlo dalla tabella del manager occorre dare il comando:
dk docker node rm worker-7
Se si compie un nuovo join del nodo worker-7
allo swarm senza averlo rimosso dalla tabella dei nodi del manager:
SWARM_TOKEN=$(docker exec -ti manager docker swarm join-token -q worker)
SWARM_TOKEN=$(echo $SWARM_TOKEN | tr -d "\r")
SWARM_MASTER_IP=$(docker exec -ti manager docker info \
| grep -w "Node Address" | awk '{print $3}')
SWARM_MASTER_IP=$(echo $SWARM_MASTER_IP |tr -d "\r")
docker exec -ti worker-7 docker swarm join \
--token $SWARM_TOKEN $SWARM_MASTER_IP:2377
La procedura funziona ma viene creata un'altra istanza di nodo in tabella, e quella vecchia, Down
, continua ad esistere.
dk docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
.....
8m9lhsotqmb2wn84m1t21k1qr worker-7 Ready Active 26.1.5
aj0ope2gl1u90dptwv71fo7ta worker-7 Down Active 26.1.5
A questo punto non si può rimuoverla col nome, ma solo tramite l'identificativo:
dk docker node rm aj0ope2gl1u90dptwv71fo7ta
Procedura di rimozione
Rimuovere un nodo e rimuovere il contenitore docker dalla macchina ospite:
vi rmnode.sh
# Controllare la sintassi, un argomento è necessario
if [ $# -lt 1 ]; then
echo "Must indicate node to remove"
echo "Syntax: $0 node"
exit 1
fi
NODE=$1
# Controllare che il nodo esista
if docker exec -ti manager docker node ls | grep $NODE > /dev/null 2>&1
then
:
else
echo "Node $NODE does not exist in cluster"
exit 2
fi
# Il nodo lascia lo swarm
docker exec -ti $NODE docker swarm leave
# Attendere la rimozione dalla tabella dei nodi
echo "Waiting for $NODE to be down"
while true; do
if docker exec -ti manager docker node ls | grep $NODE | grep Down ; then
break
else
sleep 1
continue
fi
done
echo "Node $NODE is down"
# Il nodo è cancellato dalla tabella del manager
echo "Removing $NODE from manager table"""
docker exec -ti manager docker node rm $NODE
# Rimuovere il contenitore dalla macchina ospite
docker rm -f $NODE
echo "Node $NODE removed from host docker"
Renderla eseguibile:
chmod +x rmnode.sh
Promozione e demozione di nodo
Promuovere nodi a manager, esempi:
dk docker node promote worker-1
dk docker node promote worker-2
dk docker node promote worker-3
Per degradare (demuovere) un nodo da manager a worker il comando è, p-es.:
dk docker node demote worker-3
Lo stato dello swarm è ora:
dk docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
q2v80vqnl99wmuom4z784gvvs * manager Ready Active Leader 26.1.5
iggo7d5z82jb8zohjoxl093fq worker-1 Ready Active Reachable 26.1.5
fcj1b9vc16z2corput5ly0d1t worker-2 Ready Active Reachable 26.1.5
jexh3jjpysvs7fz0h8k93n7db worker-3 Ready Active 26.1.5
kn7q5tcb7b0844613xhwb30hi worker-4 Ready
.....
Ora un manager può lasciare lo swarm:
dk docker swarm leave -f
Il nodo manager
ha lasciato lo swarm. L'opzione -f
è indispensabile per forzare l'uscita di un nodo manager.
Il cluster elegge un nuovo leader
. Si possono ora indirizzare comandi di gestione del cluster ad un manager qualsiasi, per esempio worker-1
.
La nuova tabella del cluster è:
docker exec -ti worker-1 docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
q2v80vqnl99wmuom4z784gvvs manager Down Active Unreachable 26.1.5
iggo7d5z82jb8zohjoxl093fq * worker-1 Ready Active Reachable 26.1.5
fcj1b9vc16z2corput5ly0d1t worker-2 Ready Active Leader 26.1.5
jexh3jjpysvs7fz0h8k93n7db worker-3 Ready Active 26.1.5
kn7q5tcb7b0844613xhwb30hi worker-4 Ready Active 26.1.5
.....
Si nota che worker-2
è stato eletto nuovo leader del cluster.
I vecchi manager nello stato di Down
devono essere degradati a worker prima di essere rimossi dalla tabella del cluster:
docker exec -ti worker-1 docker node demote manager
docker exec -ti worker-1 docker node rm manager
Se vi sono duplicazioni usare lo ID anzichè lo HOSTNAME.
L'elezione di un nuovo leader avviene con il protocollo di consenso RAFT.
Il leader è il manager primario, che compie tutte le decisioni di amministrazione del cluster e di orchestrazione dei task.
Per avere un cluster stabile è necessario avere un numero dispari di manager: 1 (minimo), 3, 5 o 7 (massimo raccomandato).
Quando viene meno un manager, si raccomanda di portare al più presto il numero dei manager al prossimo numero dispari.
Questo si può fare:
- promuovendo un worker a manager
- istanziando un nuovo nodo con il token di join dei master
Per conoscere il token di join come manager, chiedere ad un maneger corrente qualsiasi:
SWARM_TOKEN=$(docker exec -ti worker-1 docker swarm join-token -q manager)
SWARM_TOKEN=$(echo $SWARM_TOKEN | tr -d "\r")
echo "Swarm Token is $SWARM_TOKEN"
Occorre anche l'indirizzo IP di uno dei manager attivi.
SWARM_MASTER_IP=$(docker exec -ti worker-1 docker info \
| grep -w "Node Address" | awk '{print $3}')
SWARM_MASTER_IP=$(echo $SWARM_MASTER_IP |tr -d "\r")
echo "Swarm Master IP is $SWARM_MASTER_IP"
Ora possiamo reinstanziare manager come nodo manager del cluster:
docker exec -ti manager docker swarm join \
--token $SWARM_TOKEN $SWARM_MASTER_IP:2377
Non sarà il leader, ma vi si possono inviare comandi di amministrazione, e saranno ridiretti al leader.
Etichette ad un nodo
Eì possibile aggiungere una label ad un nodo. p.es.:
dk docker node update --label-add function=production worker-5
Una label è una coppia chiave=valore
.
Una label può essere usata per restringere l'assegnazione di servizi a determinati nodi, per esempio con l'opzione --constraint node.labels.function=production
.
Per vedere le label del nodo worker-5
in formato YAML:
dk docker node inspect worker-5 --pretty
Per rimuovere una label, p.es.:
dk docker node update --label-rm function worker-5
Le label sono maps in linguaggio Go, su cui Docker è costruito.
Per vedere tutte le label di ogni nodo manca un comando specifico, ma si può estrarre l'informazione con:
dk bash -c "docker node ls -q | xargs docker node inspect \
-f '{{ .Description.Hostname }}: {{ .Spec.Labels }}'"
Disponibilità un nodo
Vi sono tre stati di disponibilità di un nodo:
- active
- pause
- drain
Si può mettere un nodo in pausa con:
dk docker node update --availability pause worker-4
Non verranno schedulati nuovi task al nodo, ma quelli presenti continuano a funzionare.
Per toglierlo dalla pausa:
dk docker node update --availability active worker-4
Possono venire schedulati nuovi task al nodo.
Si può mettere un nodo nello stato di drain con:
dk docker node update --availability drain worker-4
Non vengono schedulati nuovi task al nodo, e quelli presenti sono gradualmente migrati ad altri nodi.