El patrón Sidecar: ampliar los microservicios sin modificar el código

El patrón Sidecar: ampliar los microservicios sin modificar el código

En los sistemas modernos nativos de la nube, se espera que los microservicios hagan mucho más que ejecutar la lógica empresarial. Deben gestionar el registro, gestionar certificados SSL/TLS, recopilar métricas, implementar mecanismos de reintento y coordinar comunicaciones seguras con otros servicios.

Si incorporamos toda esta funcionalidad transversal directamente dentro del código base de cada aplicación, terminamos con un código inflado, un acoplamiento estrecho y un bloqueo del lenguaje.

Aquí es donde entra en juego el patrón Sidecar. En esta guía, analizaremos qué es el patrón Sidecar, por qué es esencial para las arquitecturas de microservicios modernas y cómo funciona utilizando analogías simples y ejemplos de configuración de Kubernetes.


La analogía del mundo real: el sidecar de motocicleta

La forma más sencilla de entender este patrón es pensar en una motocicleta con sidecar.

Diagrama de arquitectura del patrón Sidecar que muestra los contenedores de aplicaciones y Sidecar dentro de un pod

Imagina que tienes una motocicleta de altas prestaciones. Está diseñado para hacer una cosa excepcionalmente bien: transportar a un pasajero rápidamente. Ahora supongamos que necesita llevar equipaje de pasajero o agregar un asiento adicional.

Podrías rediseñar completamente el chasis, el motor y las ruedas de la motocicleta para convertirla en un automóvil. Sin embargo, eso requiere un esfuerzo enorme, arruina la simplicidad de la bicicleta y dificulta su mantenimiento.

En su lugar, adjuntas un sidecar.

El sidecar es una unidad independiente y autónoma que se conecta a la motocicleta. Comparte el viaje de la motocicleta, va a donde quiera que vaya la motocicleta y opera en estrecho contacto. Sin embargo, el motor central de la motocicleta permanece intacto.

En arquitectura de software:

  • La motocicleta es su contenedor de aplicaciones principal (que ejecuta su lógica empresarial principal, como el pago o la autenticación de usuario).
  • Sidecar es un contenedor auxiliar independiente (que ejecuta tareas de utilidad, como terminación SSL, supervisión o envío de registros).
  • El viaje es el ciclo de vida de la implementación (por ejemplo, un Pod de Kubernetes).

El problema: preocupaciones transversales y exceso de código

Antes de los sidecars, los desarrolladores tenían que incluir bibliotecas auxiliares directamente en el código de su aplicación. Por ejemplo, si desea enviar registros a un servidor central, importa una biblioteca de registros. Si necesitaba métricas, agregó un SDK de métricas.

Este enfoque basado en bibliotecas creó varios desafíos importantes:

  • Bloqueo de idioma: si una biblioteca de monitoreo solo está escrita en Go, no podrá usarla fácilmente en un microservicio de Python o Java. Tienes que encontrar o crear una biblioteca para cada idioma en tu pila.
  • Contaminación de código: la lógica empresarial se satura con código específico de la infraestructura para reintentos, descubrimiento de servicios, cifrado y registro.
  • Actualizaciones complejas: si se encuentra una vulnerabilidad de seguridad en la biblioteca de comunicación, cada microservicio debe actualizar su dependencia, volver a compilar y volver a implementar.
  • Contención de recursos: el código auxiliar se ejecuta en el mismo proceso de ejecución que la aplicación principal, lo que significa que una pérdida de memoria en el registrador puede bloquear toda la aplicación principal.

La solución: el patrón Sidecar

El Patrón Sidecar resuelve estos problemas sacando las tareas auxiliares del proceso principal de la aplicación y colocándolas en un proceso separado e independiente que se ejecuta justo al lado de la aplicación.

En entornos en contenedores como Kubernetes, el contenedor de la aplicación y el contenedor sidecar se ejecutan dentro del mismo Pod. Porque comparten el mismo Pod:

  • Mismo espacio de nombres de red: comparten la misma dirección IP y puertos de red. Pueden hablar entre sí instantáneamente a través de localhost con una latencia prácticamente nula.
  • Volúmenes de almacenamiento compartido: pueden acceder exactamente al mismo almacenamiento en disco, lo que permite que el sidecar lea archivos de registro o cargue archivos de configuración escritos por la aplicación principal.
  • Ciclo de vida idéntico: el sidecar se implementa, inicia, detiene y escala junto con la aplicación principal.

Casos de uso clave del patrón Sidecar

Los sidecars son increíblemente versátiles. Algunas de las aplicaciones más comunes incluyen:

1. Proxy de malla de servicio (p. ej., Envoy, Linkerd)

En lugar de que su aplicación realice llamadas HTTP directas a otros servicios, envía solicitudes a su proxy sidecar local. El proxy sidecar maneja el enrutamiento, los reintentos, el equilibrio de carga, la interrupción del circuito y el cifrado TLS mutuo (mTLS) y luego reenvía la solicitud. La aplicación desconoce por completo estas complejidades de la red.

2. Recopilación y reenvío de registros (por ejemplo, Fluent Bit)

Su aplicación simplemente escribe sus declaraciones de registro en la salida estándar o en un archivo de registro local. Un contenedor complementario monitorea ese archivo, analiza los registros y los reenvía a un motor de análisis central como Elasticsearch o Datadog.

3. Configuración y recarga secreta

Un sidecar puede observar un servidor remoto (como Consul o Vault) en busca de actualizaciones de configuración o rotaciones de claves criptográficas. Cuando se detecta un cambio, descarga los archivos nuevos a un volumen compartido y le indica a la aplicación principal que los recargue, sin necesidad de reiniciar.


Ejemplo de implementación de Kubernetes

Configurar un sidecar es sencillo en Kubernetes. Aquí hay una configuración YAML simple que muestra un contenedor de aplicaciones que escribe registros en un volumen compartido y un contenedor complementario de Fluent Bit que lee y envía esos registros:

apiVersion: v1
kind: Pod
metadata:
  name: app-with-logging-sidecar
  labels:
    app: billing-service
spec:
  containers:
    # 1. Primary Application Container
    - name: web-app
      image: node:18-alpine
      command: ["/bin/sh", "-c"]
      args:
        - >
          while true; do
            echo "$(date) [INFO] Transaction processed successfully" >> /var/log/app/output.log;
            sleep 5;
          done
      volumeMounts:
        - name: shared-logs
          mountPath: /var/log/app

    # 2. Sidecar Container (Log Shipper)
    - name: log-shipper
      image: fluent/fluent-bit:latest
      volumeMounts:
        - name: shared-logs
          mountPath: /var/log/app
      # In a real setup, Fluent Bit config would read /var/log/app/output.log
      # and forward it to an external logging system.

  # Shared disk storage accessible by both containers
  volumes:
    - name: shared-logs
      emptyDir: {}

Pros y contras del patrón Sidecar

Como cualquier patrón de diseño, los sidecars tienen sus ventajas y desventajas:

Ventaja (Pro) Desventaja (Con)
Independiente del idioma: el sidecar se ejecuta en su propio entorno. Puede utilizar el mismo asistente auxiliar junto a las aplicaciones Go, Java, Python o Ruby. Sobrecarga de recursos: la ejecución de varios contenedores por módulo aumenta el consumo de CPU y memoria.
Ciclo de vida desacoplado: los equipos de infraestructura pueden actualizar los parches de seguridad del sidecar sin tocar el código de la aplicación. Mayor complejidad: administrar el doble de contenedores complica las configuraciones de implementación, la depuración y la programación.
Aislamiento de fallas independiente: si el contenedor sidecar falla, Kubernetes puede reiniciarlo automáticamente sin cerrar la aplicación principal. Ligera latencia de red: el enrutamiento del tráfico a través de un sidecar proxy local agrega un pequeño salto, aunque generalmente es insignificante (< 1ms).

Conclusión

El patrón Sidecar es un componente fundamental de las arquitecturas modernas nativas de la nube. Al aislar las preocupaciones transversales (como el proxy de red, la seguridad, el registro y la gestión de la configuración) en un proceso complementario independiente, permite a los desarrolladores centrarse exclusivamente en generar valor empresarial.

Si bien introduce una sobrecarga de recursos adicional y requiere que las plataformas de orquestación de contenedores como Kubernetes se administren de manera efectiva, los beneficios de bases de código más limpias, flexibilidad del lenguaje y escalamiento independiente lo convierten en un patrón indispensable para los microservicios empresariales.


Explore más conocimientos sobre desarrollo de software e ingeniería backend en el Blog de Ghaznix →