Swarm con Nodi Docker
Oltre che con macchine virtuali è possibile implementare un cluster Swarm con contenitori Docker.
La soluzione è molto più leggera.
Preparazione
Immagine Docker
Un'immagine che esegua Docker non è difficile da costruire, e può essere basata sul'immagine di base Alpine.
Preparazione del progetto:
mkdir -p ~/swarm/doker
cd ~/swarm/doker
La nostra immagine si chiamerà doker
.
Oltre che il Docker Engine vi saranno altre utilities.
Sarà inoltre un server SSH, con il permesso di login a root
, con password root
. E' previsto anche un utente john
con password password
.
Un entrypoint configurerà le regole di firewall necessarie a Swarm.
Inoltre lo entrypoint lancerà il server SSH in modalità demone. Avremo quindi un'immagine con due processi attivi: dockerd
come processo 1 e SSH come altro processo.
Certificato
C'è inoltre bisogno di predisporre l'immagine con un certificato per il pseudo-hostname myregistry.com
. Questo consentirà l'uso dai nodi dello swarm di un servizio registry locale.
Generare il certificato con:
openssl req -newkey rsa:4096 -nodes -sha256\
-keyout registry.key -x509 -days 365\
-out registry.crt -subj "/CN=myregistry.com"\
-addext "subjectAltName = DNS:myregistry.com"
Questo genera due files:
registry.crt
- il certificatoregistry.key
- la chiave privata
Il Dockerfile
Prepariamo il Dockerfile:
vi Dockerfile
FROM alpine
# Add software
RUN apk add --no-cache docker git jq openssl \
shadow ncurses
RUN apk --update add --no-cache openssh tcpdump bash curl \
&& rm -rf /var/cache/apk/*
# ‘root’ può fare login
RUN sed -i s/#PermitRootLogin.*/PermitRootLogin\ yes/ /etc/ssh/sshd_config \
&& echo "root:root" | chpasswd
# Abilitare la porta 22
RUN sed -ie 's/#Port 22/Port 22/g' /etc/ssh/sshd_config
# Abilitare le chiavi crittografiche
RUN sed -ri 's/#HostKey \/etc\/ssh\/ssh_host_key/HostKey \/etc\/ssh\/ssh_host_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_rsa_key/HostKey \/etc\/ssh\/ssh_host_rsa_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_dsa_key/HostKey \/etc\/ssh\/ssh_host_dsa_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_ecdsa_key/HostKey \/etc\/ssh\/ssh_host_ecdsa_key/g' /etc/ssh/sshd_config
RUN sed -ir 's/#HostKey \/etc\/ssh\/ssh_host_ed25519_key/HostKey \/etc\/ssh\/ssh_host_ed25519_key/g' /etc/ssh/sshd_config
# Generare le chiavi crittografiche
RUN /usr/bin/ssh-keygen -A
RUN ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_key
# Generazione dell’utente ‘john’ con password ‘password’
RUN adduser -D john && echo "john:password" | chpasswd
# Porta da esporre al port mapping
EXPOSE 22
# Certificati per il registry
COPY registry.crt /root
COPY registry.key /root
RUN mkdir -p /etc/docker/certs.d/myregistry.com:5000
COPY registry.crt /etc/docker/certs.d/myregistry.com:5000/ca.crt
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["dockerd"]
Lo entrypoint è:
vi entrypoint.sh
#! /bin/sh
# Porte necessarie a Swarm
iptables -A INPUT -p tcp --dport 2377 -j ACCEPT
iptables -A INPUT -p tcp --dport 7946 -j ACCEPT
iptables -A INPUT -p udp --dport 7946 -j ACCEPT
iptables -A INPUT -p udp --dport 4789 -j ACCEPT
iptables -A INPUT -p esp -j ACCEPT
# Lancio del server SSH
/usr/sbin/sshd
# Aggiungere la risoluzione del registry
echo "192.168.77.2 myregistry.com" >> /etc/hosts
exec "$@"
Si presume che la rete su cui girerà lo swarm sia la 192.168.77.0/24.
L'immagine doker
viene costruita col comando:
docker build -t doker .
Procedure shell per il cluster
Posizionamento nella directory di progetto:
cd ~/swarm
Procedura di Setup
Procedura di setup del cluster Swarm:
vi startcluster.sh
# Crea la rete su cui porre i nodi dello swarm
if docker network ls | grep swarmnet; then
:
else
docker network create swarmnet --subnet 192.168.77.0/24
fi
# Ogni nodo ha uno Host Mapping per preservare le immagini precedentemente scaricate
# un secondo host mapping per comunicare col registry su host
# terzo host mapping per ricevere files da host
# e un quarto per il mapping di dati persistenti
echo "Creating manager"
docker run -d --privileged --name manager --hostname manager --net swarmnet \
-v $PWD/manager:/var/lib/docker \
-v ~/registry:/registry \
-v ~/manager-tmp:/tmp \
-v ~/data:/data \
doker
echo "Initialising manager"
docker exec -ti manager docker swarm init
# 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
NUM_WORKERS=3
echo There will be $NUM_WORKERS workers
# Generare i workers e aggiungerli allo swarm
for i in $(seq "$NUM_WORKERS"); 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 8
docker exec -ti worker-${i} docker swarm join \
--token $SWARM_TOKEN $SWARM_MASTER_IP:2377
done
docker exec -ti manager docker node ls
Il nodo master si chiama manager
. I nodi worker si chiamano worker-1
, worker-2
, ecc.
La procedura viene resa eseguibile:
chmod +x startcluster.sh
Procedura di Teardown
Per chiudere in maniera adeguata lo Swarm e rimuoverne i nodi.
vi stopcluster.sh
# Rimozione dei nodi worker
echo "Removing worker nodes"
for i in $(docker ps -a | grep worker | awk '{n=NF;print $n}'); do
echo "Node $i leaves swarm"
docker exec -ti $i docker swarm leave -f
done
echo "Nodes are removed"
docker rm -f $(docker ps -a | grep worker | awk '{n=NF;print $n}')
# Rimozione del manager
echo "Master leaves swarm"
docker exec -ti manager docker swarm leave -f
echo "Removing manager"
docker rm -f manager
echo "Swarm cluster deleted"
Renderla eseguibile:
chmod +x stopcluster.sh
Lancio di Swarm
Semplicemente, nella directory ~/swarm
, è l'esecuzione di:
./startcluster.sh
Con risultato simile a:
Creating manager
6beab45536ff982b109ef279079cb5a3029f242838620f9debcfe3fcd42b029b
Initialising manager
Swarm initialized: current node (up1038772l2darfkf4i9yot95) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-4jmp9d1eng04ks5go2h5owgo44zncb2uurapk1fr6fctzzpq40-4yvvbnndi57kzgpqcjf13iqzk 172.17.0.2:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Swarm token is SWMTKN-1-4jmp9d1eng04ks5go2h5owgo44zncb2uurapk1fr6fctzzpq40-4yvvbnndi57kzgpqcjf13iqzk
Swarm master IP is 172.17.0.2
There will be 3 workers
Starting worker-1
168918df8ec8e043f5572a510f69d3f826f64dcb1f53bf1b4385051e38fc5e38
Joining worker-1
This node joined a swarm as a worker.
Starting worker-2
064efbacc8b69c565639093eed23edb2e3e41091ed6b889890f0e28839619066
Joining worker-2
This node joined a swarm as a worker.
Starting worker-3
913731b95277e689702a64555b06611f0a021a1a1a2dd5d4054eea1f78b370db
Joining worker-3
This node joined a swarm as a worker.
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
up1038772l2darfkf4i9yot95 * manager Ready Active Leader 25.0.5
3ju2p5efck7qcgze14zfp3jmw worker-1 Ready Active 25.0.5
zbdg3ciulaeyt8he28v2uu8v9 worker-2 Ready Active 25.0.5
p9e5hpqcijlrb9048lplhg4gy worker-3 Ready Active 25.0.5
Nota
Nella configurazione corrente tutti i comandi devono essere eseguiti sul container della macchina ospite che si chiama manager
.
Conviene creare un alias per risparmiare digitazione:
alias dk='docker exec -ti manager'
Con tale alias la lista dei nodi si ottiene con:
dk docker node ls