Arquitectura de Alta Disponibilidad: 24 Containers en Producción
Share
Arquitectura de Alta Disponibilidad: 24 Containers en Producción
Introducción
Cuando se escalan múltiples servicios en producción, la gestión de recursos se convierte en un arte. En este artículo exploramos una infraestructura real que maneja 24 containers Docker distribuidos en dos VPS, con uptime de hasta 124 días y optimización agresiva de memoria.
La arquitectura demuestra cómo es posible ejecutar 12 servicios simultáneos en apenas 7.8 GB de RAM, manteniendo disponibilidad del 83% en memoria y menos del 1% de uso de CPU en la mayoría de componentes.
Distribución de Carga: Dos VPS, Dos Estrategias
VPS1: Orquestación con Docker Swarm
El primer servidor ejecuta 12 containers activos usando Docker Swarm con Easypanel como panel de control. La distribución incluye:
- Traefik como reverse proxy (34 MB RAM, 0.14% CPU)
- 3 containers para un sistema CRM deportivo (PostgreSQL + API + nginx)
- WhatsApp Business API con Evolution API (3 containers: app + PostgreSQL + Redis)
- 2 aplicaciones cliente en puertos dedicados (5060, 5070)
La clave está en el uso de Traefik con file provider en lugar de Docker labels, permitiendo routing dinámico sin reiniciar el proxy.
VPS2: Simplicidad con Docker Compose
El segundo servidor, con el doble de RAM (15.6 GB), opera 12 containers usando Docker Compose directo:
services:
bot-api:
image: custom/bot-api
ports:
- "3000:3000"
bot-proxy:
image: custom/bot-proxy
ports:
- "3010:3010"
Esta configuración prioriza predictibilidad sobre flexibilidad, ideal para servicios críticos que requieren reinicio rápido.
Optimización de Recursos: El Arte de los Límites
Uno de los containers estudiados implementa límites estrictos:
deploy:
resources:
limits:
memory: 256M
Este contenedor CRM opera con apenas 28 MB de uso real contra un límite de 256 MB, demostrando que aplicaciones Flask bien optimizadas pueden servir interfaces React completas con consumo mínimo.
Estrategias de Despliegue Sin Downtime
Patrón 1: Bind Mounts para Hot Reload
Algunos containers usan bind mounts para actualizar código sin rebuild:
scp app.py vps:/opt/service/
docker restart service
Tiempo total de actualización: 3-5 segundos.
Patrón 2: Docker CP para Templates Cacheados
Cuando el framework cachea templates (Flask, Django), el patrón cambia:
docker cp chat.html container:/app/templates/
docker restart container
Esto invalida el cache interno sin reconstruir la imagen completa.
Patrón 3: Static HTML Deploy
Para SPAs con React/Babel in-browser:
scp index.html vps:/opt/service/public/
No restart needed - nginx sirve directamente
Downtime: 0 segundos.
Networking: Service Names vs Localhost
Un aprendizaje crítico en esta arquitectura:
❌ INCORRECTO en Docker networks
response = requests.post('http://localhost:3010/api')
✅ CORRECTO - usa service name
response = requests.post('http://bot-proxy:3010/api')
Docker Compose crea una red interna donde `localhost` apunta al propio container, no al host. Los service names resuelven automáticamente vía DNS interno.
Gestión de Uptime: 124 Días Sin Reinicio
El VPS1 mantiene 124 días de uptime continuo mediante:
- SSH en puerto no estándar (2222) - reduce ataques automatizados
- Fail2ban activo - 283 IPs baneadas acumuladas
- UFW configurado - solo puertos esenciales expuestos
- Actualizaciones sin reinicio - `apt-get upgrade` sin kernel updates
La estrategia de seguridad multicapa permite operar sin reiniciar el host, mientras los containers se actualizan individualmente.
Monitoreo de Recursos en Tiempo Real
La supervisión usa `docker stats` con formato personalizado:
docker stats --no-stream --format \
"table {{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}"
Esto genera snapshots exactos del consumo sin herramientas externas como Prometheus, ideal para infraestructuras pequeñas.
Reverse Proxy: Traefik File Provider vs Labels
File Provider (VPS1)
http:
routers:
varela-chat:
rule: "Host(`chat.varela.guru`)"
service: varela-chat
services:
varela-chat:
loadBalancer:
servers:
- url: "http://varela-chat:5000"
Ventajas: Actualizar routing sin reiniciar Traefik, ideal para Swarm.
Docker Labels (VPS2)
labels:
- "traefik.http.routers.bot.rule=Host(`bot.varelainsights.com`)"
- "traefik.http.services.bot.loadbalancer.server.port=3000"
Ventajas: Configuración junto al servicio, autodiscovery.
Estrategia de Backups: Apagar para Crecer
La arquitectura implementa "apagado estratégico":
- OpenProject (4 containers) - removido, liberó ~800 MB
- Metabase (2 containers) - removido, liberó 600 MB
- Bot inactivo - removido, liberó ~200 MB
Total recuperado: 1.6 GB sin pérdida de datos (backups en `tar.gz`).
Esta estrategia permite escalar horizontalmente solo cuando es necesario, manteniendo costos bajos.
Lecciones de Arquitectura
1. RAM Sobre CPU
La mayoría de containers usan <1% CPU pero requieren RAM fija. Optimizar para memoria es más crítico que para procesamiento.
2. Timezone Matters
Todos los containers usan `TZ=America/Mexico_City`. Inconsistencias de timezone causan bugs sutiles en logs y cronjobs.
3. Port Mapping Inteligente
Puertos dedicados (5060, 5070) permiten múltiples instancias del mismo servicio sin conflictos de Traefik.
Conclusión
Esta arquitectura demuestra que es posible ejecutar docenas de servicios en producción sin Kubernetes ni orquestadores complejos. Las claves son:
- Conocer el consumo real de cada componente (monitoring continuo)
- Elegir el patrón de deploy según el caso (bind mount vs docker cp vs static)
- Optimizar para el cuello de botella (RAM en este caso, no CPU)
Con 24 containers distribuidos, uptime de 124 días y apenas 23% de RAM usada en el servidor principal, esta infraestructura prueba que la simplicidad bien ejecutada supera a la complejidad prematura.