Docker Cluster - Swarm Parte II, Laboratorio.
Continuando con el tema de Clusters en Docker, ahora montaremos un entorno de pruebas con varios servidores.
Montaremos 4 servidores corriendo Docker, con distintos S.operativos y nos permitirá probar despliegue de contenedores entre ellos simulando una configuración real de un gran proyecto.
Los 5 Servidores corriendo son:
- Debian
- Centos 7
- Mac con OSX
- FreeBSD - GhostBSD
- Manager - Manajaro
DEBIAN - Xubuntu
Quitar versiones viejas
#apt-get remove docker docker-engine docker.io
Instalar con Repositorios
# apt-get install apt-transport-https ca-certificates curl software-properties-common
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# sudo apt-key fingerprint 0EBFCD88
# sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# apt update
# apt-get install docker-ce
# df -h
Filesystem Size Used Avail Use% Mounted on
udev 966M 0 966M 0% /dev
tmpfs 198M 8,6M 189M 5% /run
/dev/sda1 18G 11G 5,8G 66% /
tmpfs 987M 164K 987M 1% /dev/shm
tmpfs 5,0M 4,0K 5,0M 1% /run/lock
tmpfs 987M 0 987M 0% /sys/fs/cgroup
tmpfs 198M 44K 198M 1% /run/user/1000
# uname -a
Linux xubu 4.10.0-38-generic #42~16.04.1-Ubuntu SMP Tue Oct 10 16:32:20 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
# docker version
Client:
Version: 17.10.0-ce
API version: 1.33
Go version: go1.9.1
Git commit: f4ffd2511c
Built: Wed Oct 18 23:08:56 2017
OS/Arch: linux/amd64
Server:
Version: 17.10.0-ce
API version: 1.33 (minimum version 1.12)
Go version: go1.9.1
Git commit: f4ffd2511c
Built: Wed Oct 18 23:09:11 2017
OS/Arch: linux/amd64
Experimental: false
CENTOS 7
# yum remove docker docker-common docker-selinux docker-engine
# yum install -y yum-utils device-mapper-persistent-data lvm2
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# yum install docker-ce
# docker run hello-world
# systemctl enable docker
# systemctl start docker
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 16G 1.3G 14G 9% /
devtmpfs 486M 0 486M 0% /dev
tmpfs 497M 0 497M 0% /dev/shm
tmpfs 497M 6.7M 490M 2% /run
tmpfs 497M 0 497M 0% /sys/fs/cgroup
/dev/sda1 1014M 181M 834M 18% /boot
tmpfs 100M 0 100M 0% /run/user/0
tmpfs 100M 0 100M 0% /run/user/1000
# uname -a
Linux localhost.localdomain 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
# docker version
Client:
Version: 17.09.0-ce
API version: 1.32
Go version: go1.8.3
Git commit: afdb6d4
Built: Tue Sep 26 22:42:18 2017
OS/Arch: linux/amd64
Server:
Version: 17.09.0-ce
API version: 1.32 (minimum version 1.12)
Go version: go1.8.3
Git commit: afdb6d4
Built: Tue Sep 26 22:40:56 2017
OS/Arch: linux/amd64
Experimental: false
MAC OSX
Obtener el fichero DMG a instalarlo como siempre.
https://download.docker.com/mac/stable/Docker.dmg
FreeBSD - GhostBSD
# pkg install docker
Updating GhostBSD repository catalogue...
GhostBSD repository is up to date.
All repositories are up to date.
The following 1 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
docker: 17.06.1
Manjaro/Arch
# pacman -S docker-machine
# df -h
Filesystem Size Used Avail Use% Mounted on
dev 3,9G 0 3,9G 0% /dev
run 3,9G 1,6M 3,9G 1% /run
/dev/sdb2 229G 95G 123G 44% /
tmpfs 3,9G 154M 3,7G 4% /dev/shm
tmpfs 3,9G 0 3,9G 0% /sys/fs/cgroup
tmpfs 3,9G 144M 3,8G 4% /tmp
/dev/sda1 220G 189G 20G 91% /extras
/dev/sdb3 1022M 256K 1022M 1% /boot/efi
tmpfs 787M 36K 787M 1% /run/user/1000
# uname -a
Linux xxxx 4.9.60-1-MANJARO #1 SMP PREEMPT Thu Nov 2 13:08:20 UTC 2017 x86_64 GNU/Linux
# docker version
Client:
Version: 17.09.0-ce
API version: 1.32
Go version: go1.8.3
Git commit: afdb6d4
Built: Tue Sep 26 22:41:23 2017
OS/Arch: linux/amd64
Server:
Version: 17.09.0-ce
API version: 1.32 (minimum version 1.12)
Go version: go1.8.3
Git commit: afdb6d4
Built: Tue Sep 26 22:42:49 2017
OS/Arch: linux/amd64
Experimental: false
Poniendo a funcionar nuestro cluster
Usaremos tres equipos, Xubuntu, Centos y Manjaro. Todos deben estar en la misma red, IPs locales, se deben ver sin bloqueos de puertos y para facilitar el laboratorio creamos 3 sesiones bash contra cada uno de ellos.
Cluster:
En el nodo manager, creamos el cluster (Swarm) y nos indica que deben hacer los demas servidores para asociarse a él.
# docker swarm init
Swarm initialized: current node (wo3mvfeprxtpvl04jbjllithc) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-1mmvuqqg5yxkx1d97r6c9 192.168.0.200:2377
To add a manager to this swarm, run ‘docker swarm join-token manager’ and follow the instructions.
En uno de los nodos (Xubu), nos asociamos al cluster.
# docker swarm join --token SWMTKN-1-1mmvuqqg5yxkx1d97r6c9 192.168.0.200:2377
This node joined a swarm as a worker.
Por ahora nuestro cluster está formado por un nodo Manager y un nodo Worker. Recordemos que los nodos Manager también son clusters y pueden correr contenedores/Servicios.
Desde el nodo Manager podemos ver información del cluster creado.
# docker info
# ....
Swarm: active
NodeID: 7a2dnxwcnv7qjjpif5pktzzxx
Is Manager: true
ClusterID: mxar9yxib306voil6wu3vyopa
Managers: 1
Nodes: 2
Orchestration:
Task History Retention Limit: 5
Raft:
Snapshot Interval: 10000
Number of Old Snapshots to Retain: 0
Heartbeat Tick: 1
Election Tick: 3
Dispatcher:
Heartbeat Period: 5 seconds
CA Configuration:
Expiry Duration: 3 months
Force Rotate: 0
Autolock Managers: false
Root Rotation In Progress: false
Node Address: 192.168.0.220
Manager Addresses:
192.168.0.220:2377
# ....
Desde el nodo manager, también podemos ver información de todos los nodos.
# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
7a2dnxwcnv7qjjpif5pktzzxx * xxxx Ready Active Leader
vdor4zhtg9fmplim3bxcu3g7w xubu Ready Active
mxar9yxib306voil6wu3vyopa centos Ready Active
Ahora crearemos un servicio sencillo, que únicamente hará ping al sitio web de docker.com. Indicamos que solo requeremos una réplica, que representa tener un solo contenedor corriendo el ping.
# docker service create --replicas 1 --name helloworld alpine ping docker.com
i8ogtiui90csqddhybcmlmu6c
overall progress: 1 out of 1 tasks
1/1: running
verify: Service converged
Con el comando “service” podemos interactuar con los servicios. Veremos los que están corriendo. En este ejemplo solo uno llamado “helloworld”.
# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
i8ogtiui90cs helloworld replicated 1/1 alpine:latest
Se puede ver la información del servicoi de una manera detallada en modo texto.
# docker service inspect --pretty helloworld
ID: i8ogtiui90csqddhybcmlmu6c
Name: helloworld
Service Mode: Replicated
Replicas: 1
Placement:
UpdateConfig:
Parallelism: 1
On failure: pause
Monitoring Period: 5s
Max failure ratio: 0
Update order: stop-first
RollbackConfig:
Parallelism: 1
On failure: pause
Monitoring Period: 5s
Max failure ratio: 0
Rollback order: stop-first
ContainerSpec:
Image: alpine:latest@sha256:d6bfc3baf615dc9618209a8d607ba2a8103d9c8a405b3bd8741d88b4bef36478
Args: ping docker.com
Resources:
Endpoint Mode: vip
O obtener los mismos datos pero en formato JSON.
# docker service inspect helloworld
[
{
"ID": "i8ogtiui90csqddhybcmlmu6c",
"Version": {
"Index": 16
},
"CreatedAt": "2017-11-08T09:57:23.361027551Z",
"UpdatedAt": "2017-11-08T09:57:23.361027551Z",
]
El comando “ps” nos mostrará los procesos corriendo en el servicio “helloworld”, veremos que el nombre es “helloworld.1”, veremos mas adelante que al agregar mas contenedores incrementará ese número.
Este comando lo probamos en el nodo Manager, y como habíamos indicado que solo queríamos una intancia del servicio “ping”, el contenedor creado está corriendo en ese mismo nodo (Manager).
# docker service ps helloworld
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
ktbmgf618475 helloworld.1 alpine:latest manager Running Running about a minute ago
En uno nodo worker no hay actividad, no hay contenedores corriendo.
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Pasaremos de 1 a 5 instancias de ese servicio, con el comando “scale”.
# docker service scale helloworld=5
helloworld scaled to 5
overall progress: 5 out of 5 tasks
1/5: running
2/5: running
3/5: running
4/5: running
5/5: running
verify: Service converged
Ahora en el nodo Manager veremos que hay 2 instancias corriendo.
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad95a5fe459e alpine:latest "ping docker.com" 43 seconds ago Up 42 seconds helloworld.4.iwdgown6x41kvhc5beqqckypx
b0f565aa0937 alpine:latest "ping docker.com" 3 minutes ago Up 3 minutes helloworld.1.ktbmgf618475evjynopvfn64y
Y en el nodo worker adicional, veremos que estás las otras 3.
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8de17f7ee5fc alpine:latest "ping docker.com" 55 seconds ago Up 54 seconds helloworld.3.s77fgqan7n4giqafa43p1c58w
104f694db485 alpine:latest "ping docker.com" 55 seconds ago Up 54 seconds helloworld.2.mgtoebrd1buo0tip4df9odnsq
de1b481c0105 alpine:latest "ping docker.com" 55 seconds ago Up 54 seconds helloworld.5.s6jare34i637orand4bjvtb8p
En el nodo manager, nos dice en donde están corriendo cada instancia (.1 al .5). El proceso de despliegue de instancias demora unos segundos aún en el caso de una red óptima y sin problemas de recursos.
# docker service ps helloworld
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
ktbmgf618475 helloworld.1 alpine:latest xxxx Running Running 3 minutes ago
mgtoebrd1buo helloworld.2 alpine:latest xubu Running Running about a minute ago
s77fgqan7n4g helloworld.3 alpine:latest xubu Running Running about a minute ago
iwdgown6x41k helloworld.4 alpine:latest xxxx Running Running about a minute ago
s6jare34i637 helloworld.5 alpine:latest xubu Running Running about a minute ago
Si voy al nodo Worker y quiero matar el servicio llamado helloworld en un worker, me dice que está siendo manejado por un manager.
# docker service rm helloworld
Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.
Al correr el “RM” (remove) en el nodo Manager, unos segundos despues todos los contenedores (locales y en nodos worker) se matan y desaparecen, también es un proceso que demora varios segundos.
# docker service rm helloworld
Hemos matado ese servicio y ahora volveremos a hacer una prueba agregando otro nodo worker adicional.
Desde el manager, volvemos a crear 5 contenedores, ahora haciendo ping al IP local.
# docker service create --replicas 5 --name helloworld alpine ping 127.0.0.1
y800rpbkzms6fow2x66dkt0ob
overall progress: 5 out of 5 tasks
1/5: running
2/5: running
3/5: running
4/5: running
5/5: running
verify: Service converged
Desde el nodo manager (o equipo real donde corrimos el docker swam init) vemos esos procesos.
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fa64e5f32552 alpine:latest "ping 127.0.0.1" 54 seconds ago Up 52 seconds helloworld.4.f0bo5pasg42k4b9uukcf2bmd5
313c0ea7d8d1 alpine:latest "ping 127.0.0.1" 54 seconds ago Up 52 seconds helloworld.2.u4az3zrdhjvhe2blk32wusz0m
En el nodo worker hay 3 servicios corriendo.
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee4aeeafb26a alpine:latest "ping 127.0.0.1" 19 seconds ago Up 17 seconds helloworld.1.ygqtf1xaaxe4jelptpfnrir4m
347a727cc143 alpine:latest "ping 127.0.0.1" 19 seconds ago Up 17 seconds helloworld.5.trp457wgld4rvlcigncqbu4eg
ea6d8e609e5e alpine:latest "ping 127.0.0.1" 19 seconds ago Up 17 seconds helloworld.3.xiw1k5njk09jxmnse6g76inae
Ahora asociaremos otro servidor (Centos) como nodo worker al mismo cluster..
# docker swarm join --token SWMTKN-1-1b7mhfuqek3e0bogz5yckq42utmm52mzxt2cd49exhkiugcz9l-9z54i6yhvgghbpi524kpokax8 192.168.10.220:2377
Error response from daemon: error while validating Root CA Certificate: x509: certificate has expired or is not yet valid
Posible problema de diferencia de fechas entre nodos o causados por el Firewall de Centos, lo desactivamos.
# iptables -F
# iptables -Z
En el nodo Manager, el certificado parece valido.
# docker swarm ca | openssl x509 -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
57:ff:e6:b3:73:cf:92:49:a8:df:bf:76:e6:81:e5:60:e1:5f:14:f1
Signature Algorithm: ecdsa-with-SHA256
Issuer: CN = swarm-ca
Validity
Not Before: Nov 8 09:49:00 2017 GMT
Not After : Nov 3 09:49:00 2037 GMT
Subject: CN = swarm-ca
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:99:13:5c:40:f8:4b:9c:e0:b1:2a:25:42:bf:5b:
ea:92:0d:e4:ef:dc:88:bc:ab:d9:4a:35:48:a4:ff:
3e:6a:81:13:b9:ef:01:bb:83:a4:df:34:8b:84:59:
25:be:cf:dd:d6:38:bb:e1:fb:38:82:49:f5:c7:23:
72:a4:b2:cd:f0
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
80:B4:77:1E:0F:7B:41:CF:6D:3D:7E:5E:B7:01:FF:9C:43:69:3A:C0
Signature Algorithm: ecdsa-with-SHA256
30:45:02:20:2d:8e:b0:12:fc:64:a0:72:7c:ff:d8:d1:65:59:
15:db:f0:00:13:3d:b2:0e:77:7e:46:14:b2:a9:8b:26:01:37:
02:21:00:a7:91:45:b8:44:96:61:3d:e5:b2:b5:cf:8e:cd:32:
80:e9:8f:5d:ba:cf:07:1e:25:f7:20:8e:b9:a0:92:24:f6
Desde el nodo manager, pasaremos a tener 12 instancias de ese servicio (ping 127.0.0.1)
# docker service create --replicas 12 --name helloworld alpine ping 127.0.0.1
dei77zqlcgi9slct0480dd307
Since --detach=false was not specified, tasks will be created in the background.
In a future release, --detach=false will become the default.
Veremos que Docker ha balanceado las 12 instancias entre los 3 servidores (Manager y dos Workers). En el nodo manager tendremos 4 instancias corriendo.
Y en los nodos:
NODO 1
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fa55d5b7392d alpine:latest "ping 127.0.0.1" 19 seconds ago Up 16 seconds helloworld.10.lx08pcglw101m0i4fk7xt5071
40c114da3137 alpine:latest "ping 127.0.0.1" 19 seconds ago Up 16 seconds helloworld.1.efjsaifuzu3yg8z62uumramyl
a521533ffda5 alpine:latest "ping 127.0.0.1" 19 seconds ago Up 16 seconds helloworld.9.q8jjrg0xx962mw9lyqg2k2jax
a7f7e961e688 alpine:latest "ping 127.0.0.1" 19 seconds ago Up 16 seconds helloworld.11.0o7trps3n5cjzxeb8jbofwy1u
NODO 2
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d181e795ed3 alpine:latest "ping 127.0.0.1" 16 seconds ago Up 14 seconds helloworld.3.itwd8e1f0mbutmsbt3ec0lpg6
d469d9ca613e alpine:latest "ping 127.0.0.1" 16 seconds ago Up 15 seconds helloworld.8.nc1ic470bldl7lzyq9sthnojm
6603e22f437d alpine:latest "ping 127.0.0.1" 16 seconds ago Up 15 seconds helloworld.6.pytiqtq7ek745b3bhzcme4vxs
f2c2c86f83b7 alpine:latest "ping 127.0.0.1" 16 seconds ago Up 15 seconds helloworld.4.d0zt4yeur3jb7sah038kz0r7h
Reducimos los servicios corriendo a solo 5 (de 12 a 5)
# docker service scale helloworld=5
Ahora la distribución será 2,2 y 1. NODO MANAGER
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5a2e202072f6 alpine:latest "ping 127.0.0.1" 8 minutes ago Up 7 minutes helloworld.7.rmn5h3ve3wled16137j6c3xol
2e1c22009935 alpine:latest "ping 127.0.0.1" 8 minutes ago Up 7 minutes helloworld.5.bf8gov2pefhspvx7fg0ghtmxv
NODO 1
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fa55d5b7392d alpine:latest "ping 127.0.0.1" 7 minutes ago Up 6 minutes helloworld.10.lx08pcglw101m0i4fk7xt5071
40c114da3137 alpine:latest "ping 127.0.0.1" 7 minutes ago Up 6 minutes helloworld.1.efjsaifuzu3yg8z62uumramyl
NODO 2
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d469d9ca613e alpine:latest "ping 127.0.0.1" 7 minutes ago Up 7 minutes helloworld.8.nc1ic470bldl7lzyq9sthnojm
Veremos que cada contenedor corriendo en un equipo real, genera dos unidades montadas (3 Contenedores = 6 unidades).
overlay 229G 97G 121G 45% /var/lib/docker/overlay2/ca4862b746a55c417d6bdcefefb92f7ef3c1c9268c6de1486b9a3ebc7a407e8b/merged
shm 64M 0 64M 0% /var/lib/docker/containers/e6585f9886c3de279cb64055b19c5808f2e0864ab1ce50c86d4c660977454795/shm
overlay 229G 97G 121G 45% /var/lib/docker/overlay2/876ab5dce32173628c090625f20e0765ed8db5b1ca24d686c106f3d5a547ed83/merged
shm 64M 0 64M 0% /var/lib/docker/containers/ebaaa12db5675495922e1b8e8018dfd188b5bda1671267a900d83c9396a0e6e5/shm
overlay 229G 97G 121G 45% /var/lib/docker/overlay2/3e2b2ef636d78b552c10274029d79fb3487bee0cb9c2263f1214724c1714fc8f/merged
shm 64M 0 64M 0% /var/lib/docker/containers/b0bd710db0843e4553407efca307dc815ac4c0e372805241e737d0bbed7be17a/shm
En los nodos no es posible pedir un “service” estan gestionados desde el manager.
# docker service ls
Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.
Desde el manager podemos pedir mas detalles de los servicios corriendo.
# docker service ps helloworld
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
efjsaifuzu3y helloworld.1 alpine:latest xxxxxxxxxx Running Running less than a second ago
bf8gov2pefhs helloworld.5 alpine:latest localhost.localdomain Running Running 9 minutes ago
rmn5h3ve3wle helloworld.7 alpine:latest localhost.localdomain Running Running 9 minutes ago
nc1ic470bldl helloworld.8 alpine:latest xubu Running Running less than a second ago
lx08pcglw101 helloworld.10 alpine:latest xxxxxxxxxx Running Running less than a second ago
Para revisar el log de un contenedor, solo se puede hacer localmente desde el propio nodo. Desde el manager no es posible ver el log de un contenedor corriendo en un Nodo worker distinto.
# docker logs d469d9ca613e
Error response from daemon: No such container: d469d9ca613e
Si un nodo deja el cluster, unos segundos despues el Manager arrancará nuevos contenedores en otros nodos, para mantener la cantidad definida.
# docker swarm leave
Node left the swarm.