Un dels avantatges principals de Docker Swarm és la capacitat d’actualitzar serveis en producció sense interrompre el servei als usuaris. Això s’aconsegueix mitjançant les rolling updates: actualitzacions progressives que van substituint les tasques antigues per tasques noves de forma controlada.
Actualitzar un servei #
La comanda docker service update permet modificar qualsevol aspecte d’un servei en execució. Els canvis més habituals són:
- Canviar la imatge (nova versió de l’aplicació).
- Modificar variables d’entorn.
- Ajustar els recursos assignats (CPU, memòria).
- Canviar la configuració de xarxa o volums.
Per actualitzar la imatge a una nova versió usam el paràmetre --image:
docker service update --image nginx:1.26 webSwarm començarà a substituir les tasques antigues (amb nginx:1.25) per tasques noves (amb nginx:1.26) de forma progressiva.
Per a afegir o modificar una variable d’entorn usarem els paràmetres --env-add i --env-rm:
docker service update --env-add DEBUG=true web
docker service update --env-rm DEBUG webEl mateix es pot fer amb les etiquetes (labels):
docker service update \
--label-add environment=production \
--label-add version=2.1.0 \
--label-add team=backend \
web
docker service update --label-add prometheus.scrape=false web
docker service update --label-add traefik.enable=false webAmb la primera comanda hem aprofitat per crear o modificar múltiples etiquetes alhora. Amb la segona i la tercera hem canviat l’estat de la configuració de Prometheus i Traefik.
Anàlogament a --env-rm, el paràmetre --label-rm ens permet eliminar etiquetes, per exemple etiquetes temporals o obsoletes que ja no té sentit mantenir:
docker service update --label-rm canary webLa instrucció anterior podria tenir sentit després de promocionar un desplegament canari a estable.
Finalment, també podem, per exemple, canviar el port publicat per un servei:
docker service update --publish-rm 80:80 --publish-add 8080:80 webO canviar el número de rèpliques d’un servei, com ja vàrem veure a l’article anterior:
docker service update --replicas 5 webRolling updates #
Per defecte, quan actualitzes un servei, Swarm aplica una estratègia de rolling update: actualitza les tasques d’una en una, esperant que cada tasca nova estigui en execució abans de passar a la següent.
Pots configurar com es fan les actualitzacions amb els següents paràmetres de control:
| Paràmetre | Descripció | Valor per defecte |
|---|---|---|
--update-parallelism |
Nombre de tasques a actualitzar simultàniament | 1 |
--update-delay |
Temps d’espera entre actualitzacions de tasques | 0s |
--update-failure-action |
Què fer si una tasca falla (pause, continue, rollback) |
pause |
--update-order |
Ordre d’actualització (start-first, stop-first) |
stop-first |
Exemple amb paràmetres personalitzats:
docker service update \
--image nginx:1.26 \
--update-parallelism 2 \
--update-delay 10s \
--update-failure-action rollback \
webAquesta comanda:
- Actualitza 2 tasques simultàniament (
--update-parallelism 2). - Espera 10 segons entre cada lot de tasques (
--update-delay 10s). - Si alguna tasca falla, fa rollback automàtic (
--update-failure-action rollback).
El paràmetre --update-order controla com es substitueixen les tasques:
| Valor | Comportament |
|---|---|
stop-first |
Atura la tasca antiga abans de crear la nova (per defecte) |
start-first |
Crea la tasca nova abans d’aturar l’antiga (menys downtime) |
L’opció start-first és útil quan vols minimitzar el temps sense servei, però requereix que el node tingui recursos suficients per executar temporalment ambdues tasques.
docker service update \
--update-order start-first \
--image nginx:1.26 \
webResponsabilitats #
Docker Swarm no té coneixement del que passa dins el contenidor a nivell d’aplicació. No sap si hi ha peticions HTTP en curs, connexions de base de dades obertes, o processos a mig executar.
El que fa Swarm és:
- Deixa de dirigir noves peticions cap a la tasca que vol aturar (la treu del balancejador del routing mesh).
- Envia un senyal
SIGTERMal procés principal del contenidor. - Espera l’
stop-grace-period(10 segons per defecte) perquè l’aplicació es tanqui correctament. - Envia
SIGKILLsi el contenidor encara no s’ha aturat.
Per tant, l’aplicació ha d’estar preparada per gestionar el SIGTERM correctament:
- Deixar d’acceptar connexions noves.
- Esperar que les peticions en curs acabin (graceful shutdown).
- Tancar connexions de base de dades, alliberar recursos.
- Sortir amb codi 0.
Si l’aplicació ignora el SIGTERM o tarda massa, Swarm la matarà amb SIGKILL després del període de gràcia, provocant possibles talls en connexions actives.
A l’exemple amb NGINX usat a la secció anterior, NGINX gestiona SIGTERM fent un graceful shutdown: deixa d’acceptar connexions noves però espera que les actives acabin. Per això és relativament segur amb el stop-grace-period per defecte (és fàcil monitoritzar si, sovint, tenim peticions al sistema que tarden més de 10 segons en completar-se).
Les aplicacins problemàtiques, per exemple aquelles que no gestionen SIGTERM o que tenen un temps d’execució molt llarg, simplement moren quan reben SIGKILL, tallant qualsevol petició en curs.
En producció és important ajustar el
--stop-grace-periodsegons el temps màxim que pugui durar una petició a l’aplicació, i assegurar-se que l’aplicació implementa graceful shutdown.
Monitoritzar l’actualització #
Mentre s’executa una actualització, es conveinent monitoritzar el progrés. Podem fer-ho a través de l’estat de les tasques:
docker service ps webUn exemple de sortida seria:
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE
abc123 web.1 nginx:1.26 node1 Running Running 30 seconds ago
def456 web.2 nginx:1.26 node2 Running Running 45 seconds ago
ghi789 web.3 nginx:1.26 node3 Running Running 5 seconds ago
jkl012 \_ web.3 nginx:1.25 node3 Shutdown Shutdown 20 seconds agoLa sortida mostra:
- Les tasques actuals amb la nova imatge (
nginx:1.26). - Les tasques antigues en estat
Shutdown. - La tasca
web.3encara s’està actualitzant, per tant mostra l’antiga (IDjkl012) i la nova (IDghi789).
Per veure un resum bo de llegir de l’estat del servei:
docker service inspect --pretty webCerca la secció UpdateStatus per veure l’estat de l’actualització:
UpdateStatus:
State: completed
Started: 2 minutes ago
Completed: 30 seconds ago
Message: update completedEls estats possibles són:
| Estat | Descripció |
|---|---|
updating |
L’actualització està en curs |
paused |
L’actualització s’ha pausat (per fallada o manualment) |
completed |
L’actualització ha finalitzat correctament |
rollback_started |
S’està fent rollback |
rollback_completed |
El rollback ha finalitzat |
Rollback #
Si una actualització causa problemes, es pot tornar a la versió anterior amb un rollback:
docker service rollback webSwarm restaurarà la configuració anterior del servei, incloent la imatge, variables d’entorn, i qualsevol altre paràmetre que s’hagi modificat.
El rollback també es pot configurar, de forma similar a les actualitzacions:
| Paràmetre | Descripció |
|---|---|
--rollback-parallelism |
Tasques a revertir simultàniament |
--rollback-delay |
Temps d’espera entre reversions |
--rollback-failure-action |
Què fer si el rollback falla (pause, continue) |
Aquests paràmetres es defineixen en crear o actualitzar el servei:
docker service update \
--rollback-parallelism 1 \
--rollback-delay 5s \
--rollback-failure-action pause \
webAixí mateix, si configures --update-failure-action rollback, Swarm farà rollback automàticament quan detecti que una tasca nova no arrenca correctament:
docker service update \
--image myapp:broken \
--update-failure-action rollback \
webSi la imatge myapp:broken falla en arrencar, Swarm detectarà l’error i tornarà automàticament a la versió anterior.
Gestió de fallades #
Swarm monitoritza l’estat de les tasques i actua segons la configuració quan detecta fallades.
Durant una actualització, el paràmetre --update-failure-action controla el comportament:
| Valor | Comportament |
|---|---|
pause |
Pausa l’actualització per permetre investigar (per defecte) |
continue |
Ignora l’error i continua amb les altres tasques |
rollback |
Fa rollback automàtic a la versió anterior |
Quan Swarm atura una tasca, per defecte envia un senyal SIGTERM i espera 10 segons abans d’enviar SIGKILL. Es pot ajustar aquest període de gràcia:
docker service update --stop-grace-period 30s webAixò dona 30 segons a l’aplicació per tancar connexions i alliberar recursos de forma neta.
Quan una tasca falla (no durant una actualització, sinó en operació normal), Swarm la reinicia automàticament. Aquest comportament també és configurable:
docker service update \
--restart-condition on-failure \
--restart-delay 5s \
--restart-max-attempts 3 \
--restart-window 120s \
webLa següent taula explica els paràmetres de l’exemple:
| Paràmetre | Descripció |
|---|---|
--restart-condition |
Quan reiniciar: none, on-failure, any (defecte) |
--restart-delay |
Temps entre intents de reinici |
--restart-max-attempts |
Màxim d’intents dins la finestra |
--restart-window |
Finestra de temps per comptar intents |
Health checks #
Els health checks permeten a Swarm verificar que l’aplicació funciona correctament, no només que el contenidor està en execució. Per això és tant important fer-ne ús. Podem definir un health check de la següent forma:
docker service update \
--health-cmd "curl -f http://localhost/ || exit 1" \
--health-interval 30s \
--health-timeout 10s \
--health-retries 3 \
--health-start-period 60s \
webLa següent taula explica els paràmetres de l’exemple:
| Paràmetre | Descripció |
|---|---|
--health-cmd |
Comanda per verificar la salut del contenidor |
--health-interval |
Freqüència de comprovació |
--health-timeout |
Temps màxim per a la comprovació |
--health-retries |
Intents fallits abans de marcar com unhealthy |
--health-start-period |
Temps inicial abans de començar les comprovacions |
Quan un contenidor es marca com unhealthy, Swarm l’atura i en crea un de nou.
El més habitual és definir el health check al
Dockerfile, amb la instruccióHEALTHCHECK. Si es defineix tant alDockerfilecom al servei, la configuració del servei té prioritat.
Resum #
| Comanda | Funció |
|---|---|
docker service update --image IMATGE SERVEI |
Actualitza la imatge del servei |
docker service update --env-add VAR=VAL SERVEI |
Afegeix una variable d’entorn |
docker service update --env-rm VAR SERVEI |
Elimina una variable d’entorn |
docker service update --replicas N SERVEI |
Canvia el nombre de rèpliques |
docker service update --update-parallelism N |
Tasques a actualitzar simultàniament |
docker service update --update-delay TEMPS |
Espera entre actualitzacions |
docker service update --update-order ORDRE |
Ordre: stop-first o start-first |
docker service update --stop-grace-period TEMPS |
Temps de gràcia abans de SIGKILL |
docker service rollback SERVEI |
Torna a la versió anterior |
docker service ps SERVEI |
Monitoritza l’estat de les tasques |
Exercici pràctic #
L’objectiu d’aquest exercici és practicar les actualitzacions de serveis, configurar rolling updates i fer rollbacks.
Requisits:
- Un clúster Docker Swarm amb almanco 3 nodes.
- Connectivitat de xarxa entre els nodes.
Tasques:
-
Crear un servei inicial:
- Crea un servei anomenat
webappamb la imatgenginx:1.24i 4 rèpliques. - Publica el port 80.
- Verifica que totes les rèpliques s’estan executant correctament.
- Crea un servei anomenat
-
Actualització bàsica:
- Actualitza el servei a la imatge
nginx:1.25. - Observa el progrés amb
docker service ps webapp. - Verifica que totes les tasques usen la nova imatge.
- Actualitza el servei a la imatge
-
Rolling update controlat:
- Actualitza a
nginx:1.26amb els següents paràmetres:- 2 tasques simultànies.
- 15 segons d’espera entre lots.
- Monitoritza el progrés en temps real.
- Comprova la durada total de l’actualització.
- Actualitza a
-
Rollback manual:
- Executa un rollback del servei.
- Verifica que les tasques tornen a la versió anterior (
nginx:1.25). - Comprova l’estat del rollback amb
docker service inspect --pretty webapp.
-
Simular una fallada:
- Actualitza el servei a una imatge inexistent:
nginx:inexistent. - Observa com l’actualització es pausa.
- Executa un rollback per recuperar el servei.
- Actualitza el servei a una imatge inexistent:
-
Rollback automàtic:
- Configura el servei amb
--update-failure-action rollback. - Torna a intentar l’actualització a
nginx:inexistent. - Observa com Swarm fa rollback automàticament.
- Configura el servei amb
-
Health check:
- Actualitza el servei afegint un health check que comprovi que nginx respon.
- Verifica que les tasques es marquen com healthy.
- Consulta l’estat de salut amb
docker inspectsobre un dels contenidors.
-
Neteja:
- Elimina el servei
webapp.
- Elimina el servei