Prometheus guarda las métricas en disco local y no está pensado para conservarlas durante años ni para consultar varias instancias a la vez. Thanos resuelve ambas cosas: sube los bloques TSDB de Prometheus a un almacenamiento de objetos compatible con S3, los compacta y reduce su resolución (downsampling), y ofrece un endpoint de consulta PromQL que une datos recientes e históricos. En este tutorial desplegarás Thanos en un único servidor Ubuntu 24.04 junto a Prometheus, con cada componente como servicio systemd, y conectarás Grafana al resultado.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 2 vCPU y 4 GB de RAM.
- Un usuario no root con privilegios
sudo. - Un bucket en un almacenamiento de objetos compatible con S3 (AWS S3, MinIO, Wasabi, Cloudflare R2...) y unas credenciales con permisos de lectura, escritura, listado y borrado sobre ese bucket. Necesitarás el nombre del bucket, el endpoint y la región.
- Opcional: Grafana instalado para visualizar las métricas.
En esta guía todos los componentes corren en el mismo servidor, así que cada uno usa puertos distintos:
| Componente | gRPC | HTTP | Función |
|---|---|---|---|
| Sidecar | 10901 | 10902 | Sube bloques al bucket y expone los datos recientes de Prometheus |
| Store Gateway | 10905 | 10906 | Sirve los bloques históricos del bucket |
| Query | 10903 | 10904 | API y UI PromQL que une todas las fuentes |
| Compactor | - | 10907 | Compacta, aplica downsampling y retención en el bucket |
Paso 1: Instalar y preparar Prometheus
Si ya tienes Prometheus funcionando, adapta este paso a tu instalación. Aquí se usa el paquete de Ubuntu, que crea el usuario prometheus, guarda los datos en /var/lib/prometheus/metrics2 y lee sus opciones de /etc/default/prometheus:
sudo apt update
sudo apt install prometheus
Thanos necesita dos cambios en Prometheus. El primero es fijar la duración de los bloques TSDB en 2 horas, para que Prometheus no los compacte localmente (esa tarea pasa a ser del Compactor de Thanos). Edita el archivo de opciones:
sudo nano /etc/default/prometheus
Sustituye la línea ARGS por la siguiente:
ARGS="--storage.tsdb.min-block-duration=2h --storage.tsdb.max-block-duration=2h --storage.tsdb.retention.time=2d"
La retención local se reduce a 2 días porque el histórico vivirá en el bucket.
El segundo cambio es añadir etiquetas externas (external_labels). El Sidecar se niega a arrancar si Prometheus no las tiene, ya que identifican de qué instancia viene cada serie. Abre la configuración:
sudo nano /etc/prometheus/prometheus.yml
Añade o completa el bloque global al principio del archivo:
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
cluster: produccion
replica: prometheus-1
Comprueba la configuración y reinicia Prometheus:
promtool check config /etc/prometheus/prometheus.yml
sudo systemctl restart prometheus
Checking /etc/prometheus/prometheus.yml
SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntax
Verifica que las etiquetas externas están activas consultando la API de Prometheus:
curl -s http://localhost:9090/api/v1/status/config | grep -A3 external_labels
Paso 2: Descargar el binario de Thanos
Thanos es un único binario que actúa como cualquiera de sus componentes según el subcomando. Consulta la última versión en la página de releases de GitHub (github.com/thanos-io/thanos/releases) y ajusta la variable:
THANOS_VERSION=0.39.2
cd /tmp
curl -fLO "https://github.com/thanos-io/thanos/releases/download/v${THANOS_VERSION}/thanos-${THANOS_VERSION}.linux-amd64.tar.gz"
tar xzf "thanos-${THANOS_VERSION}.linux-amd64.tar.gz"
sudo install -m 0755 "thanos-${THANOS_VERSION}.linux-amd64/thanos" /usr/local/bin/thanos
En un servidor arm64 sustituye linux-amd64 por linux-arm64. Comprueba la instalación:
thanos --version
thanos, version 0.39.2 (branch: HEAD, revision: ...)
Crea un usuario de sistema para el Store Gateway, el Query y el Compactor, y los directorios de trabajo:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin thanos
sudo mkdir -p /etc/thanos /var/lib/thanos/store /var/lib/thanos/compact
sudo chown -R thanos:thanos /var/lib/thanos
El Sidecar, en cambio, correrá como el usuario prometheus, porque necesita leer el directorio TSDB de Prometheus.
Paso 3: Configurar el almacenamiento de objetos
Todos los componentes que acceden al bucket leen la misma configuración. Crea el archivo:
sudo nano /etc/thanos/bucket.yaml
Rellena los valores de tu proveedor. Sustituye your_bucket, your_s3_endpoint, your_region, your_access_key y your_secret_key:
type: S3
config:
bucket: "your_bucket"
endpoint: "your_s3_endpoint"
region: "your_region"
access_key: "your_access_key"
secret_key: "your_secret_key"
insecure: false
El endpoint va sin https://, por ejemplo s3.eu-west-1.amazonaws.com para AWS o minio.your_domain:9000 para MinIO. Usa insecure: true solo si tu endpoint no tiene TLS.
El archivo contiene credenciales, así que limita quién puede leerlo. Tanto thanos como prometheus lo necesitan, por lo que se usa un grupo común:
sudo usermod -aG thanos prometheus
sudo chown root:thanos /etc/thanos/bucket.yaml
sudo chmod 640 /etc/thanos/bucket.yaml
Comprueba que Thanos puede acceder al bucket. El comando lista los bloques; de momento la lista estará vacía, pero no debe mostrar errores de autenticación:
sudo -u thanos thanos tools bucket ls --objstore.config-file=/etc/thanos/bucket.yaml
Paso 4: Ejecutar Thanos Sidecar
El Sidecar vigila el directorio TSDB de Prometheus, sube cada bloque de 2 horas al bucket en cuanto se cierra y expone por gRPC los datos que aún no se han subido. Crea la unidad systemd:
sudo nano /etc/systemd/system/thanos-sidecar.service
[Unit]
Description=Thanos Sidecar
After=network-online.target prometheus.service
Wants=network-online.target
[Service]
User=prometheus
Group=prometheus
ExecStart=/usr/local/bin/thanos sidecar \
--tsdb.path=/var/lib/prometheus/metrics2 \
--prometheus.url=http://localhost:9090 \
--grpc-address=127.0.0.1:10901 \
--http-address=127.0.0.1:10902 \
--objstore.config-file=/etc/thanos/bucket.yaml
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Las direcciones escuchan solo en 127.0.0.1 porque Query corre en el mismo servidor. Si en el futuro consultas este Sidecar desde otra máquina, cambia la dirección gRPC y protege el puerto con el firewall.
Arranca el servicio:
sudo systemctl daemon-reload
sudo systemctl enable --now thanos-sidecar
sudo systemctl status thanos-sidecar --no-pager
Revisa los logs. Debes ver que el Sidecar ha encontrado las etiquetas externas de Prometheus y que el componente shipper está activo:
sudo journalctl -u thanos-sidecar -n 30 --no-pager
El primer bloque se sube al bucket cuando Prometheus lo cierra, lo que puede tardar hasta 2 horas. Pasado ese tiempo, thanos tools bucket ls mostrará al menos un bloque.
Paso 5: Ejecutar Thanos Store Gateway
El Store Gateway lee los bloques del bucket y los sirve a Query. Guarda en local una caché de índices en su directorio de datos. Crea la unidad:
sudo nano /etc/systemd/system/thanos-store.service
[Unit]
Description=Thanos Store Gateway
After=network-online.target
Wants=network-online.target
[Service]
User=thanos
Group=thanos
ExecStart=/usr/local/bin/thanos store \
--data-dir=/var/lib/thanos/store \
--objstore.config-file=/etc/thanos/bucket.yaml \
--grpc-address=127.0.0.1:10905 \
--http-address=127.0.0.1:10906
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now thanos-store
Comprueba que está listo. El endpoint /-/ready devuelve 200 cuando ha terminado de sincronizar los metadatos del bucket:
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:10906/-/ready
200
Paso 6: Ejecutar Thanos Query
Query es la pieza que consultan tus usuarios y Grafana. Expone la misma API HTTP que Prometheus y reparte cada consulta entre el Sidecar (datos recientes) y el Store Gateway (histórico). Crea la unidad:
sudo nano /etc/systemd/system/thanos-query.service
[Unit]
Description=Thanos Query
After=network-online.target thanos-sidecar.service thanos-store.service
Wants=network-online.target
[Service]
User=thanos
Group=thanos
ExecStart=/usr/local/bin/thanos query \
--grpc-address=127.0.0.1:10903 \
--http-address=0.0.0.0:10904 \
--endpoint=127.0.0.1:10901 \
--endpoint=127.0.0.1:10905 \
--query.replica-label=replica \
--query.auto-downsampling
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
--endpointapunta a cada fuente de datos: añade una línea por cada Sidecar si tienes más instancias de Prometheus.--query.replica-label=replicadeduplica las series cuando dos Prometheus en alta disponibilidad solo se diferencian en la etiquetareplica.--query.auto-downsamplingusa automáticamente datos de menor resolución en consultas de rangos largos.
sudo systemctl daemon-reload
sudo systemctl enable --now thanos-query
Comprueba que Query ve las dos fuentes:
curl -s http://localhost:10904/api/v1/stores | python3 -m json.tool | grep -E '"name"|"lastError"'
"name": "127.0.0.1:10901",
"lastError": null,
"name": "127.0.0.1:10905",
"lastError": null,
Lanza una consulta PromQL a través de Thanos:
curl -s 'http://localhost:10904/api/v1/query?query=up' | python3 -m json.tool | head -20
La respuesta debe incluir las series up de tus targets con las etiquetas cluster y sin replica (eliminada por la deduplicación).
La interfaz web queda en http://your_server_ip:10904. No la expongas a Internet sin autenticación: permite el acceso solo desde tu IP con UFW, sustituyendo your_admin_ip:
sudo ufw allow from your_admin_ip to any port 10904 proto tcp
En la pestaña Stores de la interfaz verás el estado de cada endpoint y el rango de tiempo que cubre.
Paso 7: Ejecutar Thanos Compactor
El Compactor une los bloques de 2 horas en bloques más grandes, genera versiones con resolución de 5 minutos y de 1 hora, y borra los datos que superan la retención. Solo debe haber un Compactor por bucket; dos a la vez corrompen los datos.
sudo nano /etc/systemd/system/thanos-compact.service
[Unit]
Description=Thanos Compactor
After=network-online.target
Wants=network-online.target
[Service]
User=thanos
Group=thanos
ExecStart=/usr/local/bin/thanos compact \
--wait \
--data-dir=/var/lib/thanos/compact \
--objstore.config-file=/etc/thanos/bucket.yaml \
--http-address=127.0.0.1:10907 \
--retention.resolution-raw=30d \
--retention.resolution-5m=180d \
--retention.resolution-1h=2y
Restart=on-failure
RestartSec=30
[Install]
WantedBy=multi-user.target
Con esta retención conservas la resolución original 30 días, la de 5 minutos 6 meses y la de 1 hora 2 años. --wait mantiene el proceso en marcha y repite la compactación periódicamente. El Compactor necesita espacio temporal en disco del orden del tamaño de los bloques que procesa, así que reserva varias decenas de GB en /var/lib/thanos/compact si tienes mucho volumen.
sudo systemctl daemon-reload
sudo systemctl enable --now thanos-compact
sudo journalctl -u thanos-compact -n 20 --no-pager
El downsampling a 5 minutos solo se aplica a bloques de más de 40 horas y el de 1 hora a bloques de más de 10 días, así que no verás resultados inmediatos.
Paso 8: Conectar Grafana a Thanos Query
Grafana trata a Thanos Query como un servidor Prometheus normal. En Grafana, ve a Connections > Data sources > Add data source, elige Prometheus y configura:
- Prometheus server URL:
http://localhost:10904si Grafana está en el mismo servidor, ohttp://your_server_ip:10904si no (permitiendo esa IP en UFW). - En Performance, el tipo
Thanosen Prometheus type, si tu versión de Grafana lo muestra.
Pulsa Save & test. Grafana debe indicar que ha consultado la API correctamente. A partir de aquí, los paneles con rangos de semanas o meses leerán el histórico del bucket de forma transparente.
Solución de problemas
El Sidecar no arranca con un error sobre external labels. Prometheus no tiene external_labels en el bloque global o no se ha recargado. Revisa el paso 1 y reinicia Prometheus antes que el Sidecar.
El Sidecar arranca pero nunca sube bloques. Comprueba que Prometheus usa los flags de bloques de 2 horas (ps aux | grep prometheus), que el usuario prometheus puede leer /etc/thanos/bucket.yaml y los errores de subida en journalctl -u thanos-sidecar. Un AccessDenied indica que las credenciales no tienen permisos de escritura en el bucket.
Query muestra un endpoint con lastError. El servicio correspondiente no está escuchando en esa dirección. Comprueba con sudo ss -tlnp | grep thanos que los puertos coinciden con los de las unidades.
Series duplicadas en Grafana. Tienes varias réplicas de Prometheus y la etiqueta que las diferencia no coincide con --query.replica-label. Usa el mismo nombre de etiqueta en ambos sitios.
El Compactor se detiene con un error de solapamiento de bloques. Suele deberse a dos Prometheus con las mismas etiquetas externas escribiendo en el mismo bucket. Cada instancia debe tener un conjunto de external_labels único.
Conclusión
Ya tienes Prometheus enviando sus bloques a un bucket S3, con Thanos Query sirviendo datos recientes e históricos en una única API PromQL y el Compactor aplicando downsampling y retención. Como siguientes pasos, puedes añadir una segunda réplica de Prometheus con su propio Sidecar para alta disponibilidad, poner Thanos Query Frontend delante de Query para cachear consultas largas, y publicar la interfaz de Query detrás de un proxy inverso con TLS y autenticación.
