En corto

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Prometheus Operator / kube-prometheus-stack
kubectl -n monitoring patch prometheus kube-prometheus-stack-prometheus --type merge \
  -p '{"spec":{"enableAdminAPI":true}}'
kubectl -n monitoring port-forward svc/prometheus-operated 9090 &

# crear el snapshot (la ruta es /api/v1, no /api/v2)
curl -s -XPOST http://localhost:9090/api/v1/admin/tsdb/snapshot
# {"status":"success","data":{"name":"20260926T101500Z-3f2b1c9a7d0e4b11"}}

# sacarlo del pod con tar por stdout, mucho más rápido que kubectl cp
SNAP=20260926T101500Z-3f2b1c9a7d0e4b11
kubectl -n monitoring exec prometheus-kube-prometheus-stack-prometheus-0 -c prometheus -- \
  tar cf - -C /prometheus/snapshots $SNAP | tar xf - -C ./backup/

Fuera de Kubernetes es lo mismo con el flag --web.enable-admin-api en la línea de comandos de Prometheus y el snapshot en <storage.tsdb.path>/snapshots/.

Por qué no vale copiar el directorio

La TSDB escribe en el head (WAL más el bloque en memoria) mientras compacta bloques de dos horas en bloques más grandes y borra los viejos. Un cp -r o un rsync de /prometheus en marcha pilla bloques a medio compactar, un WAL que ya no cuadra con los checkpoints, y con suerte arranca; con menos suerte, opening storage failed: … corrupted.

El snapshot lo hace Prometheus desde dentro: crea snapshots/<fecha>-<id>/ con hardlinks a los bloques ya compactados (ocupa casi nada y tarda segundos) y vuelca el head como un bloque más, así que la copia es consistente hasta el instante de la petición. Con ?skip_head=true se salta el head y solo incluye lo compactado, que basta si haces snapshots a diario y no te importan las últimas dos horas.

Restaurar

Un snapshot es un directorio de bloques (01HXYZ…/, cada uno con chunks/, index, meta.json, tombstones). Restaurar es ponerlos en la raíz del directorio de datos de la instancia destino:

1
2
3
4
# instancia nueva (StatefulSet o binario) parada, o al menos con el data dir vacío
kubectl -n newprom exec prometheus-new-0 -c prometheus -- rm -rf /prometheus/wal /prometheus/01*
tar cf - -C ./backup/$SNAP . | kubectl -n newprom exec -i prometheus-new-0 -c prometheus -- tar xf - -C /prometheus/
kubectl -n newprom delete pod prometheus-new-0     # reinicia para que lea los bloques

Prometheus carga los bloques al arrancar y los va compactando con los nuevos. Los bloques con etiquetas externas distintas (otro cluster, otro replica) se mezclan sin problema; lo que no puedes es restaurar bloques que se solapen en tiempo con datos que ya existen y esperar que se fusionen: se quedan duplicados hasta la siguiente compactación, y las consultas ven ambas series.

promtool tsdb list /prometheus y promtool tsdb analyze /prometheus <bloque> dicen qué rango cubre cada bloque y qué series pesan más.

Borrar series y liberar espacio

La misma API sirve para quitar métricas que no debían estar (un exporter con cardinalidad desbocada, datos de una prueba):

1
2
curl -s -XPOST -g 'http://localhost:9090/api/v1/admin/tsdb/delete_series?match[]={job="noisy-exporter"}&start=2026-09-01T00:00:00Z&end=2026-09-20T00:00:00Z'
curl -s -XPOST http://localhost:9090/api/v1/admin/tsdb/clean_tombstones

delete_series solo marca (tombstones); el espacio no se libera hasta clean_tombstones o la siguiente compactación. Los dos devuelven 204 sin cuerpo.

Trampas

  • La admin API no tiene autenticación: cualquiera que llegue al 9090 puede borrar toda la base. Actívala, haz el snapshot por port-forward, y vuelve a ponerla en false. Nunca detrás de un Ingress sin auth.
  • kubectl cp con miles de ficheros tarda una eternidad y a veces se corta; el tar por stdout de arriba es un solo flujo. Para snapshots de decenas de GB, monta un PVC de backup o usa un sidecar con mc/rclone hacia S3.
  • Borra los snapshots viejos de /prometheus/snapshots/: son hardlinks, pero mantienen vivos bloques que la retención ya habría eliminado, y el disco crece sin que la retención lo explique.
  • Thanos o Mimir con sidecar ya suben cada bloque a S3: ahí el snapshot solo sirve para el head. El backup son los buckets.
  • kube-prometheus-stack: prometheus.prometheusSpec.enableAdminAPI: true en los values si quieres que el patch sobreviva al siguiente helm upgrade.

Referencias: TSDB Admin APIs en la documentación de Prometheus.

Ver también