↓ Ir al contenido

Recuperación ante fallos de red en Traefik: Circuit breakers y reintentos automáticos

·3 mins
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 real
#

Llevo años corriendo servicios en mi servidor doméstico. El problema más molesto no es que algo falle, sino que cuando falla, el usuario se queda esperando indefinidamente. Un contenedor que reinicia, una red que se corta temporalmente, un servicio saturado… todo genera páginas de error en lugar de intentar recuperarse.

Traefik tiene herramientas para esto: circuit breakers y reintentos automáticos. Las uso desde hace meses y han mejorado la experiencia notablemente.

Cómo funciona
#

Circuit breaker: Detiene de enviar tráfico a un backend que falla repetidamente. Pasado un tiempo, lo intenta de nuevo.

Reintentos automáticos: Prueba con otro backend si el primero falla.

Juntos hacen que tu infraestructura sea más tolerante a fallos temporales.

Configuración en Docker Compose
#

Aquí va mi setup típico con Traefik. Uso labels en los servicios para controlar el comportamiento:

version: '3.8'

services:
  traefik:
    image: traefik:v2.10
    container_name: traefik
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    networks:
      - traefik-net

  mi-servicio:
    image: mi-app:latest
    container_name: mi-servicio
    networks:
      - traefik-net
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.mi-servicio.rule=Host(`mi-app.local`)"
      - "traefik.http.routers.mi-servicio.entrypoints=web"
      - "traefik.http.services.mi-servicio.loadbalancer.server.port=8080"
      
      # Circuit breaker
      - "traefik.http.services.mi-servicio.loadbalancer.healthcheck.path=/health"
      - "traefik.http.services.mi-servicio.loadbalancer.healthcheck.interval=10s"
      - "traefik.http.services.mi-servicio.loadbalancer.healthcheck.timeout=3s"
      
      # Reintentos
      - "traefik.http.middlewares.reintentos.retry.attempts=3"
      - "traefik.http.middlewares.reintentos.retry.initialinterval=100ms"
      - "traefik.http.routers.mi-servicio.middlewares=reintentos@docker"

networks:
  traefik-net:
    driver: bridge

Usando archivo de configuración
#

Si prefieres separar la configuración, usa un archivo traefik.yml:

http:
  services:
    mi-servicio:
      loadBalancer:
        servers:
          - url: "http://mi-servicio:8080"
        healthCheck:
          path: /health
          interval: 10s
          timeout: 3s
      
  middlewares:
    reintentos:
      retry:
        attempts: 3
        initialInterval: 100ms
    
    circuit-breaker:
      circuitBreaker:
        expression: "NetworkErrorRatio() > 0.5"
        checkInterval: 10s
        fallbackDuration: 30s
  
  routers:
    mi-servicio:
      rule: "Host(`mi-app.local`)"
      service: mi-servicio
      middlewares:
        - reintentos
        - circuit-breaker
      entryPoints:
        - web

Parámetros clave explicados
#

  • attempts: Número de reintentos. Yo uso 3, que es un buen balance.
  • initialInterval: Tiempo entre intentos. 100ms funciona bien en LAN.
  • NetworkErrorRatio(): Abre el circuit si el 50% de las peticiones fallan.
  • checkInterval: Cada cuánto chequea si debe re-cerrar el circuit.
  • fallbackDuration: Tiempo esperando antes de intentar reconectar.

Lo que he visto en producción
#

Hace dos semanas un contenedor de Node.js consumió toda la RAM. Normalmente eso provocaría errores 502 durante 30 segundos hasta que Docker lo reiniciara. Con esto configurado, Traefik detectó el problema, intentó reintentar, y cuando eso falló, abrió el circuit breaker. Los usuarios vieron un error rápidamente en lugar de esperar.

También me ayuda cuando mi servidor tiene picos de red. El circuit breaker evita que Traefik siga bombardeando un servicio que está cayendo.

Lo que falta monitorear
#

Reviso los logs de Traefik regularmente:

docker logs traefik | grep -i circuit
docker logs traefik | grep -i retry

Si ves demasiados retries, probablemente el servicio tiene un problema real que necesita investigación.

Conclusión
#

Circuit breakers y reintentos no son magia. No cuentan como alta disponibilidad real. Pero en un servidor doméstico donde querés que las cosas sean resilientes sin infraestructura compleja, funcionan bien. Mi uptime subió notablemente desde que los implementé.