Grafana Mimir: Backend de Métricas Escalable
Grafana Mimir es una base de datos de métricas de series temporales horizontalmente escalable y compatible con Prometheus, diseñada para almacenar miles de millones de métricas activas con alta disponibilidad y multi-tenancy nativo. A diferencia de Thanos o VictoriaMetrics, Mimir está optimizado específicamente para entornos cloud-native donde los componentes escalan de forma independiente mediante Kubernetes o microservicios. Esta guía cubre la instalación en modo monolítico para empezar y la evolución hacia el modo distribuido.
Requisitos Previos
- Ubuntu 20.04/22.04 o CentOS 8+/Rocky Linux 8+
- 4 GB de RAM mínimo en modo monolítico
- Backend de almacenamiento de objetos: S3, GCS, Azure Blob o MinIO
- Puerto 8080 disponible
- Para modo distribuido: Kubernetes o múltiples servidores
Instalación en Modo Monolítico
El modo monolítico ejecuta todos los componentes de Mimir en un único proceso, ideal para empezar o para equipos pequeños:
# Descargar el binario de Mimir
MIMIR_VERSION=2.11.0
wget "https://github.com/grafana/mimir/releases/download/mimir-${MIMIR_VERSION}/mimir-linux-amd64" -P /tmp
sudo mv /tmp/mimir-linux-amd64 /usr/local/bin/mimir
sudo chmod +x /usr/local/bin/mimir
# Verificar la instalación
mimir --version
# Crear usuario y directorios
sudo useradd -r -s /bin/false mimir
sudo mkdir -p /etc/mimir /var/lib/mimir
sudo chown -R mimir:mimir /var/lib/mimir
Configuración del Backend de Almacenamiento
Crea el archivo de configuración principal en /etc/mimir/mimir.yaml:
# /etc/mimir/mimir.yaml
# Configuración para modo monolítico con MinIO como almacenamiento
# Objetivo: ejecutar todos los componentes en un proceso
target: all,alertmanager
# Configuración del servidor HTTP y gRPC
server:
http_listen_port: 8080
grpc_listen_port: 9095
log_level: info
# Configuración del anillo (para componentes distribuidos dentro del monolítico)
ingester:
ring:
instance_addr: 127.0.0.1
kvstore:
store: memberlist
replication_factor: 1
distributor:
ring:
instance_addr: 127.0.0.1
kvstore:
store: memberlist
# Descubrimiento de peers via gossip (memberlist)
memberlist:
join_members:
- 127.0.0.1
# Configuración del almacenamiento de bloques TSDB
blocks_storage:
backend: s3
s3:
bucket_name: mimir-blocks
endpoint: minio:9000
access_key_id: minio_access_key
secret_access_key: minio_secret_key
insecure: true # Deshabilitar si MinIO usa TLS
tsdb:
dir: /var/lib/mimir/tsdb
block_ranges_period: [2h]
retention_period: 48h # Retención local antes de subir a S3
bucket_store:
sync_dir: /var/lib/mimir/tsdb-sync
# Configuración del ruler (para alerting)
ruler:
rule_path: /var/lib/mimir/rules
alertmanager_url: http://localhost:8080/alertmanager
# Configuración de alertmanager embebido
alertmanager:
data_dir: /var/lib/mimir/alertmanager
sharding_ring:
replication_factor: 1
# Límites globales por tenant
limits:
# Máximo de métricas activas por tenant
max_global_series_per_user: 1500000
# Retención de datos
compactor_blocks_retention_period: 365d
# Máximo de muestras por consulta
max_fetched_samples_per_query: 50000000
# Configuración del compactador
compactor:
data_dir: /var/lib/mimir/compactor
sharding_ring:
kvstore:
store: memberlist
# Configuración del almacenamiento para reglas y alertas
ruler_storage:
backend: s3
s3:
bucket_name: mimir-ruler
endpoint: minio:9000
access_key_id: minio_access_key
secret_access_key: minio_secret_key
insecure: true
alertmanager_storage:
backend: s3
s3:
bucket_name: mimir-alertmanager
endpoint: minio:9000
access_key_id: minio_access_key
secret_access_key: minio_secret_key
insecure: true
# Proteger el archivo de configuración
sudo chmod 640 /etc/mimir/mimir.yaml
sudo chown mimir:mimir /etc/mimir/mimir.yaml
# Crear los buckets en MinIO
mc alias set local http://minio:9000 minio_access_key minio_secret_key
mc mb local/mimir-blocks
mc mb local/mimir-ruler
mc mb local/mimir-alertmanager
# Crear el servicio systemd
sudo tee /etc/systemd/system/mimir.service > /dev/null <<EOF
[Unit]
Description=Grafana Mimir
After=network.target
[Service]
Type=simple
User=mimir
Group=mimir
ExecStart=/usr/local/bin/mimir \
-config.file=/etc/mimir/mimir.yaml \
-usage-stats.enabled=false
Restart=on-failure
RestartSec=10
LimitNOFILE=65536
LimitNPROC=4096
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable mimir --now
# Verificar que Mimir está corriendo
sudo systemctl status mimir
curl http://localhost:8080/ready
curl http://localhost:8080/api/v1/status/config
Configurar Prometheus para Remote Write
# /etc/prometheus/prometheus.yml
global:
scrape_interval: 15s
external_labels:
cluster: produccion
replica: prometheus-1
remote_write:
- url: http://mimir:8080/api/v1/push
# Para multi-tenancy, especificar el tenant ID en la cabecera
headers:
X-Scope-OrgID: "mi-organizacion"
queue_config:
capacity: 10000
max_shards: 200
max_samples_per_send: 500
batch_send_deadline: 5s
min_backoff: 30ms
max_backoff: 5s
# Reiniciar Prometheus
sudo systemctl restart prometheus
# Verificar que los datos llegan a Mimir
curl "http://localhost:8080/prometheus/api/v1/query?query=up" \
-H "X-Scope-OrgID: mi-organizacion" | python3 -m json.tool
Multi-tenancy
Mimir soporta multi-tenancy de forma nativa mediante el header X-Scope-OrgID:
# Enviar datos como tenant "equipo-backend"
curl -X POST http://mimir:8080/api/v1/push \
-H "X-Scope-OrgID: equipo-backend" \
-H "Content-Type: application/x-protobuf" \
--data-binary @metricas.pb
# Consultar datos del tenant "equipo-backend"
curl "http://mimir:8080/prometheus/api/v1/query?query=up" \
-H "X-Scope-OrgID: equipo-backend"
# Consultar datos de múltiples tenants a la vez
curl "http://mimir:8080/prometheus/api/v1/query?query=up" \
-H "X-Scope-OrgID: equipo-backend|equipo-frontend|infraestructura"
Configurar límites personalizados por tenant:
# En mimir.yaml, sección overrides
overrides:
equipo-backend:
max_global_series_per_user: 5000000
compactor_blocks_retention_period: 730d # 2 años
equipo-frontend:
max_global_series_per_user: 500000
compactor_blocks_retention_period: 90d
Modo Distribuido
Para alta disponibilidad y mayor escala, Mimir separa sus componentes. Ejemplo con Docker Compose:
# docker-compose-mimir-distribuido.yml (estructura básica)
version: "3.8"
services:
# Ingestores (almacenamiento en memoria de datos recientes)
ingester-1:
image: grafana/mimir:latest
command: ["-config.file=/etc/mimir/mimir.yaml", "-target=ingester", "-ingester.ring.instance-id=ingester-1"]
volumes:
- ./mimir.yaml:/etc/mimir/mimir.yaml:ro
- ingester-1-data:/var/lib/mimir
ingester-2:
image: grafana/mimir:latest
command: ["-config.file=/etc/mimir/mimir.yaml", "-target=ingester", "-ingester.ring.instance-id=ingester-2"]
volumes:
- ./mimir.yaml:/etc/mimir/mimir.yaml:ro
- ingester-2-data:/var/lib/mimir
# Distribuidores (reciben el remote write y distribuyen entre ingestores)
distributor:
image: grafana/mimir:latest
command: ["-config.file=/etc/mimir/mimir.yaml", "-target=distributor"]
ports:
- "8080:8080"
volumes:
- ./mimir.yaml:/etc/mimir/mimir.yaml:ro
# Queriers (ejecutan consultas PromQL)
querier:
image: grafana/mimir:latest
command: ["-config.file=/etc/mimir/mimir.yaml", "-target=querier"]
volumes:
- ./mimir.yaml:/etc/mimir/mimir.yaml:ro
# Store Gateway (sirve bloques del object storage)
store-gateway:
image: grafana/mimir:latest
command: ["-config.file=/etc/mimir/mimir.yaml", "-target=store-gateway"]
volumes:
- ./mimir.yaml:/etc/mimir/mimir.yaml:ro
# Compactador
compactor:
image: grafana/mimir:latest
command: ["-config.file=/etc/mimir/mimir.yaml", "-target=compactor"]
volumes:
- ./mimir.yaml:/etc/mimir/mimir.yaml:ro
Integración con Grafana
# Añadir Mimir como datasource en Grafana
curl -X POST http://grafana:3000/api/datasources \
-u admin:contraseña_grafana \
-H "Content-Type: application/json" \
-d '{
"name": "Mimir",
"type": "prometheus",
"url": "http://mimir:8080/prometheus",
"access": "proxy",
"isDefault": true,
"jsonData": {
"timeInterval": "15s",
"httpMethod": "POST",
"customQueryParameters": "X-Scope-OrgID=mi-organizacion"
},
"httpHeaders": {
"X-Scope-OrgID": "mi-organizacion"
}
}'
Importa los dashboards oficiales de Mimir desde Grafana.com para monitorear el propio Mimir (IDs: 17564, 17565, etc.).
Solución de Problemas
Mimir no arranca:
# Revisar logs
sudo journalctl -u mimir -n 100 --no-pager
# Verificar acceso al bucket de almacenamiento
curl http://minio:9000/mimir-blocks -v
# El error más común es configuración incorrecta del bucket S3/MinIO
# Verificar las credenciales y el nombre del bucket
Error "context deadline exceeded" en remote write:
# Mimir puede estar sobrecargado o no disponible
# Verificar el estado de Mimir
curl http://mimir:8080/ready
curl http://mimir:8080/metrics | grep mimir_ingester
# Aumentar el timeout en Prometheus
remote_write:
- url: http://mimir:8080/api/v1/push
remote_timeout: 60s
Consultas lentas:
# Activar el Query Frontend como caché de consultas
# El Query Frontend divide las consultas largas en subconsultas más cortas
# y las cachea en Memcached o Redis
# Añadir al mimir.yaml:
query_frontend:
cache_results: true
results_cache:
backend: memcached
memcached:
addresses: dns+memcached:11211
Alto consumo de memoria en los ingestores:
# Los ingestores mantienen datos en memoria durante 2 horas antes de subirlos
# Limitar el número de series activas por ingester
limits:
max_global_series_per_user: 1000000
# Distribuir entre los ingestores (si hay 3 ingestores):
max_global_series_per_metric: 50000
Conclusión
Grafana Mimir es la solución más completa para entornos que requieren métricas a escala empresarial con multi-tenancy, alta disponibilidad y retención a largo plazo mediante almacenamiento en la nube. Su arquitectura de microservicios permite escalar cada componente de forma independiente según los cuellos de botella: más ingestores para mayor tasa de escritura, más queriers para mayor carga de consultas. El modo monolítico facilita enormemente el inicio y la evaluación antes de comprometerse con el despliegue distribuido completo.


