Stack de monitoring completa en 2026: Prometheus + Grafana + Loki paso a paso

Tutorial honesto para subir métricas, logs y dashboards de tu cluster — en 4 horas, sin Datadog. Stack open-source que cabe en 1 VPS de R$80/mes.

Equipo HeroCtl··16 min· Leer en portugués →

La primera vez que tu sitio caiga a las tres de la mañana, vas a descubrir una cosa incómoda: no tienes cómo saber qué pasó. No hay gráfico de CPU, no hay log del contenedor que murió, no hay alerta que avisó antes. Vas a abrir una terminal, conectar a los servidores uno por uno, correr top, df, journalctl, e intentar reconstituir una escena de crimen que ya se enfrió.

Este post es el atajo para que no pases por eso. En cuatro horas, con R$80 a R$120 al mes de hardware, se puede montar la stack de observabilidad open-source que sustituye Datadog, New Relic y CloudWatch en 95% de los casos para startup. Las herramientas son las mismas que corren dentro de empresas con decenas de miles de servidores — y caben confortablemente en una VPS pequeña para el equipo que está empezando.

TL;DR

La stack de monitoring open-source estándar en 2026 — Prometheus + Grafana + Loki + Alertmanager — cabe en una única VPS de 4 GB de RAM y cubre métricas, logs centralizados, dashboards y alertas. Este tutorial muestra setup paso a paso para un cluster de 4 a 5 servidores en aproximadamente cuatro horas, usando docker-compose o job specs del orquestador.

Para startup brasileña, eso significa R$80 a R$120 al mes de hardware contra R$1.000 a R$2.000 al mes de SaaS de observabilidad equivalente. El costo de tiempo es honesto: cuatro horas de setup inicial más dos a cuatro horas al mes de mantenimiento continuo.

Resultado entregable al final del tutorial: dashboards de CPU, RAM, disco, red y métricas HTTP; logs buscables con retención de 30 días; alertas ruteadas a Slack, Discord o e-mail. Prerrequisitos: 1 VPS Linux con 4 GB de RAM y 50 GB de SSD, Docker instalado, y un dominio con DNS controlado por ti.

La elección entre correr esta stack en una VPS dedicada fuera del cluster de producción o como job dentro del propio orquestador es una decisión arquitectural — cubrimos las dos opciones en el paso 8 y en "Cómo correr esto dentro de HeroCtl".

Qué hace cada componente, en una frase

Antes de instalar cualquier cosa, vale la pena entender el papel de cada pieza. La stack tiene seis componentes; la confusión generalmente viene de pensar que alguno de ellos es "el sistema de monitoring". No lo es. Cada uno hace una cosa.

  • Prometheus es una base de datos de series temporales (TSDB) que recolecta métricas vía HTTP scrape — él jala los números, nadie los empuja. Retiene 15 días por default.
  • Grafana es la capa de visualización. Conecta a Prometheus, a Loki, a Postgres, a casi cualquier fuente estructurada, y dibuja gráficos.
  • Loki es la pieza de logs. Sintaxis similar a la de Prometheus, indexa solo labels (no el contenido de los logs), y por eso queda cerca de diez veces más barato que ELK para correr.
  • Promtail (o el Grafana Agent, que está sustituyendo al Promtail en 2026) es el recolector que lee los archivos de log de cada servidor y envía a Loki.
  • node_exporter corre en cada nodo monitoreado y expone un endpoint HTTP con CPU, RAM, disco y red en formato Prometheus.
  • Alertmanager recibe reglas de alerta de Prometheus y cuida del ruteo — Slack, e-mail, PagerDuty, webhook arbitrario.

Quien diseña la primera stack suele confundir Prometheus con "monitoring" y Grafana con "dashboards bonitos". La separación real es: Prometheus guarda números, Loki guarda texto, Grafana muestra ambos, Alertmanager grita cuando algún número queda mal.

¿Cuál es la arquitectura recomendada?

Para un cluster de 3 a 5 servidores corriendo aplicaciones de producción, la topología que viene funcionando en la práctica es separar el servidor de observabilidad del resto. Un nodo dedicado, fuera del cluster que él monitorea, con dos objetivos: no morir junto cuando el cluster muera, y no competir por CPU/RAM con la aplicación real.

  • 1 servidor "observability" dedicado, 4 GB de RAM, 50 GB de SSD. Corre Prometheus, Grafana, Loki, Alertmanager.
  • Cada servidor monitoreado corre solo dos procesos livianos: node_exporter (métricas de sistema) y Promtail (envío de logs).
  • Tus aplicaciones exponen un endpoint /metrics en formato Prometheus. Si usas un framework popular, existe un cliente listo. Si no, es una biblioteca de pocas decenas de líneas.
  • Grafana queda accesible vía subdominio (monitor.tudominio.com) con TLS automático y autenticación básica al frente.

Esa separación tiene un costo: pagas por una VPS más. A cambio, cuando el cluster principal caiga, todavía logras mirar los gráficos para entender qué pasó. Para startup, ese trade-off compensa casi siempre — el peor escenario en monitoring es descubrir que la única cosa que paró junto con el sitio fue el sistema que iba a avisarte que el sitio paró.

Paso 1 — ¿Cómo provisionar la VPS de observabilidad?

Tiempo estimado: 10 minutos.

Cualquier proveedor barato sirve. Los dos con mejor costo-beneficio para el caso brasileño hoy son Hetzner (CPX21 a 7,99 EUR al mes con 3 vCPUs y 4 GB de RAM, datacenter en Alemania) y DigitalOcean (Basic Droplet de US$24 al mes con la misma configuración, datacenters más cercanos a Brasil). Para workload de monitoring, latencia de scrape en datacenter europeo no causa problema — Prometheus jala cada 15 segundos por default, entonces 200ms de RTT entre Hetzner y tus servidores no estorba.

Provisionando:

  1. Crea la VPS con Ubuntu 24.04 LTS o Debian 12.
  2. Agrega tu clave SSH pública en la creación. Deshabilita login por contraseña.
  3. Instala Docker y el plugin de compose: curl -fsSL https://get.docker.com | sh && apt install docker-compose-plugin.
  4. Configura el firewall: puerto 22 (SSH) abierto, puerto 443 (HTTPS) abierto, todos los demás cerrados. Los puertos internos (3000, 9090, 3100, 9093) solo quedan accesibles por el localhost de la propia VPS — el reverse proxy expone Grafana vía 443.
  5. Apunta el DNS: crea un registro A monitor.tudominio.com para la IP de la VPS.

Validación: docker --version retorna 26.x o superior; dig monitor.tudominio.com retorna la IP correcta; ssh root@monitor.tudominio.com conecta sin pedir contraseña.

Paso 2 — ¿Cómo subir la stack vía docker-compose?

Tiempo estimado: 45 minutos.

Crea el directorio de trabajo en /opt/observability/ con la siguiente estructura:

/opt/observability/
├── docker-compose.yml
├── prometheus/
│   ├── prometheus.yml
│   └── alerts.yml
├── alertmanager/
│   └── alertmanager.yml
├── loki/
│   └── loki-config.yml
└── grafana/
    └── provisioning/
        └── datasources/
            └── datasources.yml

El docker-compose.yml abreviado pero funcional:

services:
  prometheus:
    image: prom/prometheus:v2.55.0
    volumes:
      - ./prometheus:/etc/prometheus
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.retention.time=30d'
      - '--web.enable-lifecycle'  # permite reload via HTTP POST
    ports:
      - '127.0.0.1:9090:9090'
    restart: unless-stopped

  grafana:
    image: grafana/grafana:11.3.0
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
      - GF_USERS_ALLOW_SIGN_UP=false
    ports:
      - '127.0.0.1:3000:3000'
    restart: unless-stopped

  loki:
    image: grafana/loki:3.2.0
    volumes:
      - ./loki/loki-config.yml:/etc/loki/config.yml
      - loki-data:/loki
    command: -config.file=/etc/loki/config.yml
    ports:
      - '127.0.0.1:3100:3100'
    restart: unless-stopped

  alertmanager:
    image: prom/alertmanager:v0.27.0
    volumes:
      - ./alertmanager:/etc/alertmanager
    ports:
      - '127.0.0.1:9093:9093'
    restart: unless-stopped

volumes:
  prometheus-data:
  grafana-data:
  loki-data:

Tres puntos importantes en ese archivo. Primero, todos los puertos están atados a 127.0.0.1 — ninguno de los servicios es accesible directamente de internet. Segundo, los volúmenes son nombrados (no bind mounts), así que sobreviven a docker-compose down. Tercero, la contraseña de Grafana viene de variable de ambiente: crea un .env al lado del compose con GRAFANA_PASSWORD=algo_largo_aleatorio y nunca commitees eso.

Sube la stack:

cd /opt/observability
docker compose up -d
docker compose ps  # todos deben estar "Up" / healthy

Validación rápida: curl localhost:9090/-/ready retorna Prometheus Server is Ready; curl localhost:3100/ready retorna ready; curl localhost:3000/api/health retorna JSON con "database": "ok".

Paso 3 — ¿Cómo configurar los scrapes de Prometheus?

Tiempo estimado: 30 minutos.

El prometheus/prometheus.yml es donde dices a Prometheus qué endpoints raspar. Para un cluster de 4 servidores, queda así:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['alertmanager:9093']

rule_files:
  - 'alerts.yml'

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node'
    static_configs:
      - targets:
          - 'server-1.tudominio.internal:9100'
          - 'server-2.tudominio.internal:9100'
          - 'server-3.tudominio.internal:9100'
          - 'worker-1.tudominio.internal:9100'
        labels:
          environment: 'production'

  - job_name: 'apps'
    static_configs:
      - targets:
          - 'api.tudominio.internal:8080'
          - 'worker.tudominio.internal:8080'
        labels:
          environment: 'production'
    metrics_path: '/metrics'

Para clusters mayores o que cambian de composición con frecuencia, cambia static_configs por file_sd_configs apuntando a un JSON que generas automáticamente. Para 4 servidores estáticos, el archivo de arriba resuelve.

Reload: curl -X POST localhost:9090/-/reload. Verifica en localhost:9090/targets si todos los jobs están UP. Los que estén DOWN todavía no fueron instrumentados — ese es el paso 4.

Paso 4 — ¿Cómo instalar el node_exporter en cada servidor?

Tiempo estimado: 15 minutos para 4 servidores.

En cada servidor monitoreado, corre el node_exporter. Hay dos formas: binario directo vía systemd, o contenedor Docker. En 2026 el consenso es container — facilita actualización y aislamiento. En cada nodo:

docker run -d \
  --name node-exporter \
  --restart unless-stopped \
  --net="host" \
  --pid="host" \
  -v "/:/host:ro,rslave" \
  prom/node-exporter:v1.8.2 \
  --path.rootfs=/host

El --net=host es necesario para que vea las interfaces de red reales. El bind mount en /host permite leer /proc, /sys y /etc/passwd del host (read-only) sin correr el contenedor con privilegios de root.

Firewall: abre el puerto 9100 solo para la IP del servidor de observabilidad. En Ubuntu con ufw:

ufw allow from <IP_DEL_OBSERVABILITY> to any port 9100

Validación: del servidor de observability, curl http://server-1.tudominio.internal:9100/metrics debe retornar cientos de líneas empezando con # HELP node_cpu_seconds_total....

Paso 5 — ¿Cómo configurar Loki + Promtail?

Tiempo estimado: 30 minutos.

Loki ya está corriendo en el compose del paso 2. Falta el loki-config.yml:

auth_enabled: false

server:
  http_listen_port: 3100

common:
  path_prefix: /loki
  storage:
    filesystem:
      chunks_directory: /loki/chunks
      rules_directory: /loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory

schema_config:
  configs:
    - from: 2024-01-01
      store: tsdb
      object_store: filesystem
      schema: v13
      index:
        prefix: index_
        period: 24h

limits_config:
  retention_period: 720h  # 30 días
  reject_old_samples: true
  reject_old_samples_max_age: 168h

Storage en filesystem es suficiente para empezar. Cuando pases de 50 GB de logs por día o quieras retención de 90+ días, migra a S3 (o compatible). No migres antes — complica la operación sin ganancia real.

En cada servidor monitoreado, instala Promtail (o Grafana Agent) también vía container:

# /opt/promtail/promtail-config.yml en cada servidor
server:
  http_listen_port: 9080

clients:
  - url: http://monitor.tudominio.com:3100/loki/api/v1/push

scrape_configs:
  - job_name: system
    static_configs:
      - targets: [localhost]
        labels:
          job: varlogs
          host: ${HOSTNAME}
          __path__: /var/log/*.log

  - job_name: docker
    docker_sd_configs:
      - host: unix:///var/run/docker.sock
    relabel_configs:
      - source_labels: ['__meta_docker_container_name']
        target_label: 'container'

Importante: el endpoint http://monitor.tudominio.com:3100/loki/api/v1/push necesita estar accesible desde los servidores. Si seguiste el paso 2 y ataste Loki en 127.0.0.1, tienes dos opciones: exponer el 3100 vía reverse proxy con autenticación básica, o abrir un túnel SSH/WireGuard entre los servidores. La segunda opción es más segura y la que recomendamos.

Validación: en Grafana, ve a Explore, selecciona la fuente de datos Loki, corre {job="varlogs"} y ve los logs apareciendo en tiempo real.

Paso 6 — ¿Cómo importar los dashboards de Grafana?

Tiempo estimado: 20 minutos.

Accede a https://monitor.tudominio.com (después de configurar el reverse proxy del paso 8 — puedes saltar para allá ahora si quieres). Login admin con la contraseña del .env.

Agrega las dos fuentes de datos vía provisioning automático. En grafana/provisioning/datasources/datasources.yml:

apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
  - name: Loki
    type: loki
    access: proxy
    url: http://loki:3100

Reinicia Grafana con docker compose restart grafana y las fuentes aparecen automáticamente.

Importa los dashboards listos. En Dashboards → New → Import, pega el ID del dashboard:

  • 1860 — Node Exporter Full. CPU, RAM, disco, red, sistema de archivos. Es el dashboard más usado de la comunidad Prometheus, con razón.
  • 13639 — Logs / App. Visualización básica de logs de Loki con filtros por job, container, host.
  • 15172 — Cluster overview. Visión consolidada por servidor, útil para cluster pequeño.

Customiza cada uno para usar environment="production" en el filtro default. Después de dos semanas usándolos, vas a querer crear dashboards propios para workloads específicos — no hay atajo ahí, es tiempo de silla.

Paso 7 — ¿Cómo configurar alertas básicas?

Tiempo estimado: 45 minutos.

Alertas son donde 80% de los equipos tropiezan: o ponen poquísimos y descubren incidentes por los clientes, o ponen decenas y desensibilizan al equipo.

Empieza con seis alertas esenciales. En prometheus/alerts.yml:

groups:
  - name: essentials
    interval: 30s
    rules:
      - alert: ServerDown
        expr: up{job="node"} == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Servidor {{ $labels.instance }} está fuera del aire"

      - alert: HighCPU
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 10m
        labels:
          severity: warning

      - alert: DiskAlmostFull
        expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 15
        for: 5m
        labels:
          severity: critical

      - alert: HighMemory
        expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
        for: 10m
        labels:
          severity: warning

      - alert: HighHTTPErrorRate
        expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.05
        for: 5m
        labels:
          severity: critical

      - alert: HighLatency
        expr: histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) > 2
        for: 10m
        labels:
          severity: warning

Y el alertmanager/alertmanager.yml apuntando a un webhook de Slack o Discord:

route:
  group_by: ['alertname', 'severity']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'slack-default'
  routes:
    - match:
        severity: critical
      receiver: 'slack-critical'
      repeat_interval: 1h

receivers:
  - name: 'slack-default'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/TU/WEBHOOK/AQUI'
        channel: '#alerts'
        send_resolved: true

  - name: 'slack-critical'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/TU/WEBHOOK/AQUI'
        channel: '#alerts-critical'
        send_resolved: true

Dos detalles que ahorran noche de sueño. El for: 10m en CPU evita que picos cortos se vuelvan alertas — el servidor puede llegar a 95% por 30 segundos y eso ser normal. El repeat_interval: 4h para warnings garantiza que un warning resuelto en una hora no se vuelva 60 mensajes — el Alertmanager agrupa.

Recarga Prometheus (curl -X POST localhost:9090/-/reload) y prueba forzando una alerta: stress --cpu 4 --timeout 700s en algún servidor debe disparar HighCPU en 10 minutos.

Paso 8 — ¿Cómo poner reverse proxy y TLS al frente?

Tiempo estimado: 20 minutos.

Para acceder a Grafana vía https://monitor.tudominio.com con certificado válido, necesitas algo al frente del puerto 3000. Dos opciones:

  1. Router integrado del orquestador — si ya tienes el cluster HeroCtl corriendo, basta declarar Grafana como job con ingress: { host: monitor.tudominio.com, tls: true }. Certificado Let's Encrypt automático, sin herramienta adicional.
  2. Caddy standalone en la propia VPS de observabilidad — también emite Let's Encrypt automáticamente. Caddyfile mínimo:
    monitor.tudominio.com {
      reverse_proxy localhost:3000
      basicauth /login {
        admin <hash_bcrypt>
      }
    }
    

Para defensa en profundidad, mantén autenticación básica del Caddy/router al frente del login de Grafana — dos barreras, no una. La segunda es especialmente importante porque el login default de Grafana es admin/admin y la primera cosa que los bots hacen en un Grafana expuesto es probar esa combinación.

Paso 9 — ¿Cómo instrumentar métricas de aplicación?

Tiempo estimado: varía según número de aplicaciones.

Métricas de sistema son la mitad de la historia. La otra mitad es lo que tu aplicación está haciendo — cuántas requests por segundo, cuál la latencia p99, cuántos errores, cuál el tamaño de la cola de jobs en background.

Cada lenguaje popular tiene cliente Prometheus oficial:

  • Node.js: prom-client
  • Python: prometheus-client
  • Ruby: prometheus-client
  • Go: github.com/prometheus/client_golang

El estándar mínimo son tres métricas por endpoint HTTP:

  • http_requests_total — counter, con labels method, path, status.
  • http_request_duration_seconds — histogram, mismo set de labels.
  • app_errors_total — counter, con label kind ("validation", "db", "external_api", etc).

Expone todo eso en /metrics. Agrega el endpoint en el scrape_configs de Prometheus. En horas tienes dashboards por endpoint, alertas por tasa de error, y la capacidad de responder "qué estaba ocurriendo a las 3:14 de ayer" con un gráfico en lugar de un tiro al aire.

Cuidado con cardinalidad. Cada combinación única de labels se vuelve una serie temporal separada. Si pones user_id como label, con 100k usuarios creas 100k series — y Prometheus va a consumir 8+ GB de RAM solo para indexar eso. Regla práctica: labels tienen valores en conjuntos pequeños (status code: 5 valores; método: 5 valores; path: decenas). Identificadores únicos van en logs, no en métricas.

¿Cómo correr esto dentro de HeroCtl en lugar de VPS dedicada?

Para clusters que ya corren el orquestador, tiene sentido considerar la stack como un job más. Trade-off: ahorras una VPS, pero pierdes aislamiento (si el cluster muere, el monitoring muere junto).

La topología queda así:

  • 1 job spec único con 4 tasks: prometheus, grafana, loki, alertmanager.
  • Volúmenes replicados en el cluster — los datos sobreviven a falla de un nodo.
  • Router integrado hace el TLS automático vía subdominio. No necesita Caddy adicional.
  • Métricas del propio cluster ya son expuestas en formato Prometheus en la API administrativa, entonces el scrape es directo.

Para producción crítica, recomendamos la separación física (VPS dedicada fuera del cluster). Para proyecto personal, MVP, o equipo pequeño donde "todo cae junto" es aceptable, correr dentro es más barato y operacionalmente más simple. El job spec entero queda en torno de 80 líneas de manifiesto.

¿Cuánto cuesta esa stack al mes en Brasil?

ÍtemCosto mensual (BRL)
VPS observability dedicada (4 GB RAM)R$40 a R$80
Object storage para retención larga de logs (opcional)R$30
Tiempo de mantenimiento (2 a 4h × valor de la hora)R$200 a R$400
Total operacionalR$300 a R$500

Para comparación, una suscripción de Datadog o New Relic con cobertura equivalente (5 hosts, retención de logs de 30 días, alertas, dashboards) sale en torno de R$1.500 a R$2.000 al mes — sin contar el overage automático que aparece al final del mes cuando alguien olvida un log verboso encendido.

La diferencia no es pequeña: en un año, la stack open-source self-hosted ahorra entre R$12.000 y R$18.000. Para startup en etapa inicial, eso es medio ingeniero júnior.

Tabla de puertos, recursos y características por componente

ComponentePuertoRAM mínimaDiscoRetención defaultFormato de los datos
Prometheus9090512 MB10 GB15 díasTSDB binario
Grafana3000256 MB1 GBN/ASQLite o Postgres
Loki3100512 MB30 GB30 días (configurable)chunks comprimidos
Promtail / Agent9080128 MBmínimoN/Apasa por valor
Alertmanager9093128 MB1 GBN/Alog de notificaciones
node_exporter910064 MBmínimoN/Aendpoint de scrape

Esas son las mínimas viables para cluster pequeño. En producción con 30 servidores y tráfico real, multiplica RAM por 3 y disco por 5.

Los cuatro errores que matan stack de monitoring nueva

Equipos montando observabilidad por primera vez tropiezan casi siempre en los mismos cuatro errores. Saber sobre ellos antes ahorra meses.

No monitorear el monitoring. Prometheus paró de scrape el jueves; nadie vio. El miércoles de la semana siguiente un servidor cayó de verdad y descubrieron que no había alerta porque Prometheus estaba muerto hace 6 días. Solución: configura un cron externo simple (hasta un Pingdom gratuito sirve) que pegue en https://monitor.tudominio.com/api/health cada 5 minutos y te avise cuando el propio Grafana caiga.

Sin estrategia de retención. Disco se llena en tres meses, Prometheus para de grabar, alguien borra todo en la desesperación, pierde 90 días de historial. Configura --storage.tsdb.retention.time=30d desde el día uno y establece un job de housekeeping.

Cardinalidad alta en labels. Ya cubrimos en el paso 9, pero vale la pena repetir: cada user_id, request_id o UUID que se vuelve label es un número que multiplica explosivamente el consumo de RAM de Prometheus. Identificadores únicos van a Loki, no a Prometheus.

Alertas ruidosas. El equipo recibe 200 alertas por día. En dos semanas, nadie mira más. Cuando el sitio caiga de verdad, la alerta va a estar en medio de otras 199. Solución: empieza con seis alertas (las del paso 7), audita cada dos semanas, y excluye todo lo que disparó pero no exigió acción humana. Alerta sin acción es ruido.

FAQ

¿Puedo correr todo en una VPS de 2 GB? Técnicamente sí, para cluster de hasta 3 servidores y pocas aplicaciones. En la práctica vas a chocar contra el techo de RAM en 2 a 3 meses, especialmente si importas dashboards densos en Grafana. Paga los 50 reales más y ve directo a la VPS de 4 GB — el tiempo que ahorras no peleando con OOM kills se paga solo.

¿Cuánto disco para 30 días de logs? Depende totalmente del volumen de logs de tu aplicación. Regla gruesa para startup pequeña: cluster de 4 servidores con aplicaciones web normales genera 1 a 5 GB de logs por día después de compresión de Loki. Treinta días da entre 30 y 150 GB. Empieza con 50 GB de SSD, monitorea el crecimiento por dos semanas, expande si es necesario. Si vas mucho más allá de eso, es hora de ir a object storage.

Grafana Cloud vs self-hosted, ¿cuál elegir? Grafana Cloud free tier es generoso (10k series, 50 GB de logs, retención de 14 días) y elimina el trabajo de mantener el servidor. Para proyecto solo o equipo muy pequeño, tiene sentido. A partir del momento en que pasas del free tier, los precios escalan rápido — a partir de US$50/mes — y pierdes el control sobre los datos. Self-hosted cuesta hardware + tiempo, Cloud cuesta dinero + lock-in. Para empresa que pretende crecer y tiene un dev DevOps en el equipo, self-hosted gana.

¿Promtail o Grafana Agent? En 2026, Grafana Agent (rebautizado a Grafana Alloy) está sustituyendo al Promtail oficialmente. Para setup nuevo, ve directo a Alloy. Para setup que ya corre Promtail hace tiempo, no hay urgencia en migrar — Promtail va a seguir funcionando por años.

¿OpenTelemetry encaja dónde en esa stack? OTel es el estándar de instrumentación de aplicación que está consolidando. En lugar de usar prom-client directo, usas el SDK de OTel y él exporta a Prometheus, Loki y Tempo simultáneamente. La ventaja grande es portabilidad — si quieres cambiar Prometheus por otra cosa de aquí a 3 años, tu aplicación no cambia una línea. Para startup empezando hoy, recomendamos OTel desde el día uno.

¿Cómo hago backup de Prometheus? Prometheus tiene snapshot vía API: curl -X POST localhost:9090/api/v1/admin/tsdb/snapshot crea un snapshot en el directorio de datos. Hazlo una vez al día vía cron, haz tar.gz y envíalo a object storage. En caso de desastre, lo que pierdes son métricas — y métricas, diferente de logs, son típicamente recuperables en horas (vuelves a recolectar y los dashboards vuelven). Logs perdidos están perdidos para siempre, entonces invierte más en backup de Loki.

¿Tempo (traces distribuidos) vale la pena instalar ahora? No. Traces se vuelven útiles a partir del momento en que tienes 5+ servicios conversando entre sí y depurar latencia involucra seguir una request por varios hops. Para arquitectura monolítica o pocos servicios, traces dan trabajo desproporcional al valor. Agrégalos cuando la complejidad lo pida.

¿Loki indexa full-text como ELK? No, y esa es la feature, no bug. Loki indexa solo labels (job, host, container, severity) y el contenido del log queda comprimido sin índice. Para buscar texto, filtras por labels primero y después haces grep en los chunks resultantes. Eso es lo que vuelve a Loki diez veces más barato que ELK en RAM y CPU. A cambio, queries de texto libre en todo el historial son más lentas. Para 90% de los casos de debugging, filtrar por job + host + ventana de tiempo ya reduce a decenas de MB donde el grep vuela.

Próximos pasos

¿Subiste la stack, tienes dashboard, tienes alerta, tienes log buscable? Bien. Las próximas tres cosas que valen la inversión son, en orden:

  1. Custom dashboards por aplicación — métricas de negocio (suscripciones creadas/hora, jobs procesados, cola de e-mails) en lugar de solo infraestructura.
  2. Runbooks linkados en las alertas — toda regla en alerts.yml debe tener annotations.runbook_url apuntando a una página explicando qué hacer. Cuando la alerta dispare a las 3 de la mañana, el sueño no piensa.
  3. Revisión mensual de alertas — 30 minutos una vez al mes auditando lo que disparó en el mes anterior, eliminando lo que se volvió ruido, ajustando thresholds.

Para quien quiere ir más allá y entender por qué elegimos esta stack en lugar de SaaS gestionado, lee Observabilidad sin Datadog: la stack de la startup. Y para cerrar el ciclo de operación — porque no sirve saber que la base cayó si no logras restaurar — vale la pena leer Backup de base en cluster: estrategias para las 3 de la mañana.

Si quieres saltarte ese montaje todo y correr la stack como job dentro de un orquestador que ya cuida de TLS, rolling update y replicación de volumen:

curl -sSL get.heroctl.com/install.sh | sh

Cuatro horas se vuelven cuarenta minutos. El resto es el mismo trabajo de pensar qué alertas importan — y en esa parte nadie te libra.

#prometheus#grafana#loki#monitoring#tutorial#engineering