Skip to content

English · Español

Lab 00 — Levantar Prometheus + Grafana localmente

Objetivo: un bootstrap de una sola pasada del stack de observabilidad (observability) que los labs siguientes scrapean.

Tiempo estimado: 45-60 minutos (mayormente esperando a los pulls de imágenes).

Prerrequisito: Docker + docker-compose instalados en Fedora 43 (sudo dnf install docker docker-compose). Usuario añadido al grupo docker. El servidor de la Fase 33 corre localmente en un puerto conocido (default 8000).


Lo que produces

Un infra/compose/observability.yml funcional y un stack verificado y funcionando en:

  • UI de Prometheus: http://localhost:9090
  • UI de Grafana: http://localhost:3000 (admin/admin en el primer arranque)
  • Endpoint OTLP/gRPC del OTel-Collector: localhost:4317
  • Endpoint OTLP/HTTP del OTel-Collector: localhost:4318
  • UI de Tempo (vía data source de Grafana): backend en localhost:3200

Además:

  • infra/compose/prometheus.yml — configuración de scrape para el servidor local de la Fase 33 de Borja en el puerto 8000.
  • infra/compose/otel-collector.yaml — pipeline: receiver OTLP → processor (batching) → exporter a Tempo + logging.
  • infra/grafana/provisioning/datasources/all.yaml — auto-provisionar Prometheus y Tempo como data sources.
  • Receta de Justfile: just serve-obs levanta el stack; just stop-obs lo derriba.

TODOs

Bloque A — escribir el archivo de compose

  • Servicios a incluir:
  • prometheus (prom/prometheus:v2.54.0 o LTS actual)
  • grafana (grafana/grafana-oss:11.x)
  • tempo (grafana/tempo:2.x)
  • otel-collector (otel/opentelemetry-collector-contrib:0.x)
  • node-exporter (prom/node-exporter:v1.x) — scrapea las métricas USE del host
  • Todos los servicios en la misma red de docker (obs-net).
  • Prometheus monta ./prometheus.yml:/etc/prometheus/prometheus.yml.
  • Grafana monta ./grafana/provisioning:/etc/grafana/provisioning.
  • Tempo con la configuración mínima de almacenamiento local.
  • node-exporter con --path.rootfs=/host y el root del host bind-mounted (sólo lectura).

No uses la sintaxis docker-compose v1 — usa el plugin compose (sin la línea version: al inicio del archivo).

Bloque B — escribir prometheus.yml

Scrape jobs:

  • prometheus mismo (localhost:9090).
  • node-exporter (node-exporter:9100).
  • miniserve (el servidor de la Fase 33). La dirección depende de si el servidor corre en docker o en el host:
  • Si host: usa host.docker.internal:8000 (Linux: añade extra_hosts: host.docker.internal:host-gateway al servicio Prometheus).
  • Si docker: añade miniserve a la misma red y scrapea miniserve:8000.

Intervalo de scrape: 5 s (el default de 15 s está bien para producción; 5 s da feedback más rápido durante desarrollo).

Bloque C — escribir otel-collector.yaml

Pipeline:

receivers:  [otlp]      # gRPC :4317, HTTP :4318
processors: [batch]     # buffer para reducir la carga de exportación
exporters:  [otlp/tempo, debug]

El exporter otlp/tempo envía al endpoint OTLP de Tempo en tempo:4317. El exporter debug loggea spans a stdout (útil para el siguiente lab).

Bloque D — provisionar data sources de Grafana

En infra/grafana/provisioning/datasources/all.yaml:

  • Data source Prometheus: URL http://prometheus:9090.
  • Data source Tempo: URL http://tempo:3200.
  • Establece Prometheus como el default.

Ambos aparecerán bajo Connections → Data sources en el primer arranque de Grafana.

Bloque E — recetas del Justfile

serve-obs:
    docker compose -f infra/compose/observability.yml up -d
    @echo "Prometheus: http://localhost:9090"
    @echo "Grafana:    http://localhost:3000 (admin/admin)"
    @echo "Tempo:      via Grafana"

stop-obs:
    docker compose -f infra/compose/observability.yml down

Bloque F — smoke test

  • just serve-obs.
  • Abre http://localhost:9090/targets. Los cuatro scrape jobs (prometheus, node-exporter, miniserve, tempo) deberían estar UP (o sólo miniserve DOWN si el servidor de la Fase 33 aún no corre — está bien para este lab).
  • Abre http://localhost:3000. Inicia sesión admin/admin. Fuerza el cambio de contraseña a algo local (p. ej. localdev).
  • Navega a Connections → Data sources. Prometheus y Tempo ambos listados y "OK" en el test.
  • Ejecuta una query trivial de Prom: up. Debería devolver 3-4 series.
  • just stop-obs. Verifica un shutdown limpio.

Restricciones

  • Sin configuración grado producción. Sin TLS, sin auth en Prometheus, sin SMTP en Grafana. El stack es sólo localhost.
  • Sin volúmenes persistentes para los datos de Prometheus/Tempo. Cada reinicio borra. Está bien para un entorno de aprendizaje; el lab anota cómo añadir volúmenes si Borja quiere persistencia entre reinicios.
  • Sin dependencias externas tiradas en tiempo de ejecución. Todas las imágenes pinned por digest en el archivo de compose. Re-resuelve digests con docker pull si hace falta; comitea los digests.
  • Sin Loki todavía. Los logs estructurados aterrizan en stdout por ahora; la integración con Loki es un nice-to-have de la Fase 38.

Condiciones de parada

Hecho cuando:

  1. infra/compose/observability.yml levanta 4-5 servicios limpiamente.
  2. Los cuatro scrape jobs (menos miniserve si no corre) están UP.
  3. Grafana inicia sesión, lista ambos data sources, la query up devuelve datos.
  4. just stop-obs elimina todo limpiamente.

Trampas (lee antes de debuggear)

  • host.docker.internal en Linux no es automático. Necesitas extra_hosts: ["host.docker.internal:host-gateway"] en el servicio que necesita alcanzar el host.
  • Permisos de volumen de Grafana. El contenedor de Grafana corre como UID 472. Si haces bind-mount con el dueño equivocado, Grafana rechaza arrancar. O corre con el enfoque de bind-mount + chown correcto, o usa un volumen con nombre.
  • Prometheus rechaza arrancar si prometheus.yml tiene un error de sintaxis. Los errores aterrizan en docker compose logs prometheus. Común: tabs vs espacios en el YAML.
  • Drift en la configuración de almacenamiento de Tempo. La configuración de almacenamiento de Tempo 2.x difiere de la de 1.x — copia del ejemplo oficial actual single-binary, no de blog posts antiguos.
  • SELinux en Fedora deniega bind mounts. O corre con la flag :Z en cada mount, o setenforce 0 para la sesión de desarrollo (y documéntalo).

Cuándo consultar solutions/

Después de que tu stack de compose esté arriba. La solución en solutions/00-prom-grafana-up-ref.md (escrita al abrir la fase) muestra un archivo de compose funcional y el layout de provisionamiento estándar.


Siguiente lab: lab/01-instrument-server.md.