Prometheus HA: De discos llenos a retención infinita con Thanos Sidecar

Hace dos semanas, nuestro clúster de producción en Kubernetes (v1.28, ejecutándose sobre instancias AWS m5.xlarge) disparó una alerta crítica a las 3:00 AM: DiskPressure en el nodo que alojaba nuestro StatefulSet de Prometheus. El volumen de métricas había crecido exponencialmente tras un despliegue de microservicios con alta cardinalidad, saturando el PVC de 500GB que habíamos asignado. No era solo un problema de espacio; era un riesgo inminente de pérdida de datos históricos cruciales para nuestra auditoría.

El enfoque tradicional de simplemente "agrandar el disco" ya no era viable ni económica ni técnicamente. Necesitábamos desacoplar el almacenamiento del cómputo y garantizar que la caída de una réplica de Prometheus no nos dejara ciegos. Aquí es donde entra la Arquitectura Thanos con el patrón Sidecar.

Análisis del Cuello de Botella en Sistemas de Monitoreo

En su estado nativo, Prometheus es excelente para la recolección de métricas en tiempo real, pero es notoriamente difícil de escalar horizontalmente para Almacenamiento a largo plazo. Almacena los datos en series temporales (TSDB) en el disco local. Esto crea dos problemas graves en entornos de alto tráfico:

Primero, la retención de datos está estrictamente ligada al tamaño del disco. Si quieres guardar un año de métricas para cumplir con normativas de Observabilidad, el costo de almacenamiento en bloque (EBS/PD) se dispara. Segundo, no existe una vista global nativa unificada si decides fragmentar (shard) tu Prometheus; terminas con múltiples silos de datos desconectados.

Síntoma Crítico: Los logs mostraban wal: truncate checkpoint tardando más de 45 segundos, bloqueando la ingestión de nuevas métricas y creando "gaps" (huecos) en los gráficos de Grafana.

El Intento Fallido: Federación Jerárquica

Antes de llegar a Thanos, intentamos solucionar esto mediante "Prometheus Federation". Configuramos un Prometheus "Global" que hacía scrape de los Prometheus "Hojas" (Leafs). Fue un desastre. El servidor global se convirtió rápidamente en un cuello de botella masivo porque intentaba ingerir millones de muestras re-procesadas. Las consultas tardaban más de 20 segundos o terminaban en timeout. Aprendimos a la mala que la federación no es un sustituto para un almacenamiento de objetos distribuido.

La Solución: Implementación del Patrón Sidecar

El componente Sidecar de Thanos se ejecuta en el mismo Pod que Prometheus. Su función es leer los bloques de datos TSDB que Prometheus escribe en el disco (cada 2 horas por defecto) y subirlos a un Object Storage (S3, GCS, Azure Blob). Esto permite configurar el Prometheus local con una retención muy corta (ej. 6 horas) mientras mantenemos años de historia en la nube a bajo costo.

A continuación, muestro la configuración crítica del StatefulSet para inyectar el contenedor sidecar. Nótese el uso de argumentos específicos para manejar la concurrencia de subida.

# Configuración del contenedor Sidecar dentro del Pod de Prometheus
- name: thanos-sidecar
  image: quay.io/thanos/thanos:v0.32.5
  args:
    - "sidecar"
    - "--tsdb.path=/prometheus"
    - "--prometheus.url=http://127.0.0.1:9090"
    - "--objstore.config-file=/etc/thanos/objstore.yaml"
    # IMPORTANTE: Etiquetas para desduplicación global en la capa de Query
    - "--prometheus.external.labels.cluster=prod-us-east-1"
    - "--prometheus.external.labels.replica=$(POD_NAME)"
  env:
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
  ports:
    - name: http-sidecar
      containerPort: 10902
    - name: grpc
      containerPort: 10901
  volumeMounts:
    - name: prometheus-storage
      mountPath: /prometheus
    - name: thanos-config
      mountPath: /etc/thanos

Analicemos la lógica del código anterior. El argumento --tsdb.path debe apuntar exactamente al mismo volumen donde Prometheus escribe sus datos. Sin esto, el sidecar no puede ver los bloques compactados. Otro punto crucial es --prometheus.external.labels. Thanos Query utiliza estas etiquetas para identificar réplicas idénticas del mismo Prometheus (por ejemplo, prometheus-0 y prometheus-1) y realizar la desduplicación de datos en tiempo de consulta, logrando así una verdadera Prometheus HA sin duplicar datos visuales en los dashboards.

Configuración del Object Storage (S3)

El archivo objstore.yaml es el secreto que permite la magia del almacenamiento ilimitado. Asegúrate de usar roles de IAM (IRSA en EKS) en lugar de claves estáticas por seguridad.

type: S3
config:
  bucket: "empresa-metrics-longterm-retention"
  endpoint: "s3.us-east-1.amazonaws.com"
  sse_config:
    type: "SSE-S3"
  # Optimización para reducir llamadas a la API de AWS
  part_size: 134217728 

Verificación de Rendimiento y Comparativa

Tras desplegar el sidecar y configurar el componente Store Gateway (necesario para leer de S3), realizamos pruebas de carga. La diferencia en la gestión de recursos fue inmediata.

Métrica Prometheus Standalone Prometheus + Thanos Sidecar
Retención Local 15 Días (Límite de Disco) 6 Horas (Configurable)
Retención Total 15 Días Ilimitada (S3)
Uso de Memoria (RAM) 32 GB (Crash frecuentes) 18 GB (Estable)
Recuperación tras Fallo ~40 minutos (Replay WAL) < 5 minutos

La reducción en el uso de memoria se debe a que Prometheus ya no necesita mantener índices masivos de bloques antiguos en memoria; simplemente los descarga al almacenamiento de objetos. Esto libera recursos para procesar métricas entrantes, mejorando la estabilidad general de los Sistemas de monitoreo. Además, al mover los datos históricos a S3, el costo por GB almacenado se redujo en un 85% comparado con los volúmenes SSD de alto rendimiento (gp3).

Documentación Oficial de Thanos Sidecar

Casos Borde y Advertencias Operativas

Aunque Thanos soluciona el problema del almacenamiento, introduce complejidad. Un error común es la configuración del bloque de compactación (min_block_duration y max_block_duration) en Prometheus. Debes asegurarte de que Prometheus no intente compactar bloques que el Sidecar aún está subiendo, aunque el Sidecar generalmente maneja esto bien esperando a que los bloques se cierren.

Latencia de Red: Subir bloques a S3 consume ancho de banda de salida. En clusters con miles de Pods, el tráfico de salida del Sidecar puede saturar la interfaz de red si no se limita, afectando a la aplicación principal. Monitorea las métricas thanos_objstore_bucket_operations_total.

Finalmente, ten cuidado con la "Vista Global" en consultas muy pesadas (ej. rate() sobre 1 año de datos). Si no configuras correctamente el Thanos Store Gateway con suficiente caché local para los índices de los bloques remotos, las consultas pueden ser extremadamente lentas o causar OOM (Out Of Memory) en el componente Store.

Resultado: Logramos una disponibilidad del 99.99% en nuestras métricas y redujimos la factura de almacenamiento AWS en $1,200 mensuales.

Conclusión

Implementar el patrón Sidecar de Thanos transforma un Prometheus frágil y sobrecargado en una solución de observabilidad empresarial robusta. No solo resuelves la limitación física del disco, sino que habilitas una verdadera estrategia de recuperación ante desastres al tener tus métricas seguras en la nube. Si gestionas Kubernetes a escala, este paso no es opcional, es obligatorio.

Post a Comment