↓ Ir al contenido

Recuperación de secretos y configuración en Docker Swarm tras corrupción de etcd

Rogelio Guerra Riverón
Autor
Rogelio Guerra Riverón
Construyendo mi propia infraestructura web desde cero. Aquí documento cada paso: servidores, redes, contenedores y lo que vaya surgiendo.

El problema que enfrenté
#

Hace poco pasé un mal rato cuando etcd en mi cluster Swarm se corrompió. Los servicios seguían corriendo, pero no podía acceder a secretos ni hacer cambios en la configuración. El estado de los contenedores estaba intacto, pero la base de datos distribuida que mantiene todo junto había fallado.

Documenté el proceso de recuperación porque fue más sencillo de lo que esperaba, pero requiere cuidado.

Diagnóstico inicial
#

Lo primero fue verificar el estado del cluster:

docker node ls
docker service ls
docker config ls
docker secret ls

En mi caso, los servicios estaban corriendo pero los últimos dos comandos fallaban. Era evidente que etcd estaba corrupto.

Paso 1: Identificar el nodo manager afectado
#

Ejecuté en un manager sano:

docker info | grep -A 5 "Swarm"

Luego revisé los logs del nodo afectado:

journalctl -u docker -n 100 -f

Los errores de etcd eran claros. El archivo /var/lib/docker/swarm/raft/snap/db estaba corrupto.

Paso 2: Respaldo de datos activos
#

Antes de tocar nada, extraje información de los servicios en ejecución:

docker service inspect --format='{{json .}}' $(docker service ls -q) > servicios_backup.json
docker ps --no-trunc > contenedores_activos.txt

Esto me permitió tener un registro de qué estaba corriendo y sus especificaciones.

Paso 3: Evacuación del nodo
#

Moví todos los contenedores a otros nodos:

docker node update --availability drain NOMBRE_NODO

Esperé a que los servicios se rebalancearan. Validé con docker service ps.

Paso 4: Recuperación de etcd
#

Aquí viene lo delicado. Necesitaba recuperar los secretos y configuraciones sin perder datos.

En el nodo afectado, detuve Docker:

sudo systemctl stop docker

Localicé el archivo corrupto:

sudo ls -la /var/lib/docker/swarm/raft/snap/

En lugar de borrarlo directamente, lo renombré:

sudo mv /var/lib/docker/swarm/raft/snap/db /var/lib/docker/swarm/raft/snap/db.corrupted

Reinicié Docker:

sudo systemctl start docker

Docker reconstruiría etcd desde cero, pero los servicios seguían corriendo en otros nodos.

Paso 5: Restauración de secretos y configuración
#

Este era el paso crítico. Los secretos no se sincronizaban automáticamente.

Desde un nodo manager sano, exporté lo que pude:

docker secret ls --format="table {{.Name}}"
docker config ls --format="table {{.Name}}"

Luego, en el nodo recuperado, recreé manualmente los secretos. Si tenía respaldos (lo cual recomiendo hacer):

docker secret create mi_secret - < /ruta/al/secret.txt
docker config create mi_config /ruta/al/config.txt

Paso 6: Reinserción del nodo al cluster
#

Cambié la disponibilidad del nodo:

docker node update --availability active NOMBRE_NODO

Los servicios comenzaron a rebalancearse. Monitorié:

watch docker service ps NOMBRE_SERVICIO

Lecciones aprendidas
#

  1. Respalda regularmente: Exporta tus secretos y configuraciones cada semana como mínimo. No están protegidos si solo existen en etcd.

  2. Ten múltiples managers: Con un solo manager, un fallo es crítico. Yo ahora mantengo tres.

  3. Supervisa etcd: Implementa alertas sobre el tamaño y salud de la base de datos Raft.

  4. Documenta tu setup: Tener las especificaciones de servicios en respaldo te ahorra tiempo.

El cluster tardó aproximadamente 15 minutos en recuperarse completamente. Los servicios nunca se cayeron, pero fue un recordatorio de por qué la redundancia importa en infraestructura.