# Decision: Capa de observabilidad avanzada (punto 7) ## Contexto Las Capas 1-6 proporcionan toda la telemetría: métricas (VictoriaMetrics), logs (Loki), seguridad (Wazuh), inventario (Netbox), alertas (Alertmanager → Telegram). La Capa 7 trata de qué hacemos con esos datos más allá de reaccionar a alertas: visibilidad por cliente, medición de niveles de servicio, planificación de capacidad, informes y correlación. No introduce herramientas nuevas. Todo se construye sobre Grafana + VictoriaMetrics + Loki + Netbox ya desplegados. 5 subcapas: - 7.1 Dashboards por cliente - 7.2 SLOs/SLIs (niveles de servicio) - 7.3 Capacity planning (planificación de capacidad) - 7.4 Status page e informes para clientes - 7.5 Correlación avanzada (métricas + logs + seguridad) --- ## 7.1 Dashboards por cliente ### El problema Hoy para ver el estado de un cliente hay que: 1. Entrar en Grafana → buscar métricas del PVE donde están sus VMs 2. Entrar en PBS → buscar su datastore y ver si los backups están bien 3. Entrar en Wazuh → filtrar eventos por sus hosts 4. Entrar en Netbox → buscar qué tiene contratado Para un técnico de soporte con un ticket abierto, esto son 4 herramientas y 5 minutos antes de saber qué pasa. Multiplicado por 50+ clientes. ### DECISION 7.1 (confirmada) **Dashboard Grafana por cliente**: una vista única que muestra todo lo relevante de un cliente. #### Contenido del dashboard ``` ┌─────────────────────────────────────────────────────────┐ │ CLIENTE: ACME Corp [Último refresh: 2m] │ ├─────────────────────────────────────────────────────────┤ │ │ │ 📊 RESUMEN │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │ │ VMs: 5/5 UP │ │ Backups: OK │ │ Storage: 234/600│ │ │ │ │ │ Último: 3h │ │ GB (39%) │ │ │ └─────────────┘ └─────────────┘ └─────────────────┘ │ │ │ │ 🖥️ VMs │ │ ┌──────────┬───────┬─────────┬──────────┬───────────┐ │ │ │ VM │ CPU │ RAM │ Disco │ Estado │ │ │ ├──────────┼───────┼─────────┼──────────┼───────────┤ │ │ │ web-01 │ 12% │ 2.1/4GB │ 18/50GB │ ✅ UP │ │ │ │ db-01 │ 45% │ 7.2/8GB │ 42/100GB │ ✅ UP │ │ │ │ mail-01 │ 3% │ 1.1/2GB │ 8/20GB │ ✅ UP │ │ │ │ app-01 │ 28% │ 3.5/4GB │ 22/50GB │ ✅ UP │ │ │ │ gw-01 │ 1% │ 0.3/1GB │ 2/10GB │ ✅ UP │ │ │ └──────────┴───────┴─────────┴──────────┴───────────┘ │ │ │ │ 💾 BACKUPS (PBS1) │ │ ┌──────────┬──────────────┬────────┬────────────────┐ │ │ │ VM │ Último backup│ Tamaño │ Verify │ │ │ ├──────────┼──────────────┼────────┼────────────────┤ │ │ │ web-01 │ Hoy 03:15 │ 12 GB │ ✅ OK (hace 5d)│ │ │ │ db-01 │ Hoy 03:22 │ 38 GB │ ✅ OK (hace 3d)│ │ │ │ mail-01 │ Hoy 03:18 │ 6 GB │ ✅ OK (hace 7d)│ │ │ │ app-01 │ Hoy 03:20 │ 15 GB │ ✅ OK (hace 2d)│ │ │ │ gw-01 │ Hoy 03:16 │ 1 GB │ ✅ OK (hace 6d)│ │ │ └──────────┴──────────────┴────────┴────────────────┘ │ │ │ │ 📈 STORAGE PBS │ │ [███████████████░░░░░░░░░░░░░░░░░░░░░░░] 39% (234/600) │ │ Tendencia: +2.1 GB/semana → lleno en ~174 semanas │ │ │ │ 🔄 SYNC PBS2 (archivo) │ │ Última sincronización: Hoy 06:00 ✅ │ │ Snapshots en PBS2: 16 (7d + 4w + 5m) │ │ │ │ 🔒 SEGURIDAD (últimas 24h) │ │ Eventos Wazuh: 23 (todos nivel bajo) │ │ Alertas activas: 0 │ │ │ │ 🌐 CONECTIVIDAD │ │ WG Hub: ✅ conectado (handshake hace 47s) │ │ DNS: ✅ resolviendo │ │ Servicios publicados: portal.acme.com ✅ (200 OK) │ │ │ └─────────────────────────────────────────────────────────┘ ``` #### Implementación técnica El dashboard usa **variables de Grafana** para filtrar por cliente: ``` Variable: $customer Type: Query Data source: VictoriaMetrics Query: label_values(pbs_datastore_size_bytes, datastore) O bien: API de Netbox (plugin Grafana-Netbox) ``` Cada panel filtra por el cliente seleccionado: ```promql # VMs del cliente (PVE exporter, filtrado por tags de Netbox) pve_guest_info{name=~"$customer.*"} # Storage PBS pbs_datastore_used_bytes{datastore="$customer"} pbs_datastore_size_bytes{datastore="$customer"} # Último backup pbs_snapshot_timestamp{datastore="$customer"} # Eventos Wazuh (via Loki) count_over_time({job="wazuh"} |= "$customer" [24h]) ``` La relación VM↔cliente viene de Netbox (custom field `tenant`). El plugin `grafana-netbox-datasource` permite usar Netbox como data source de variables. #### Un dashboard, todos los clientes No se crea un dashboard por cliente. Es **un solo dashboard con variable dropdown**. El técnico selecciona "ACME" y ve todo de ACME. Selecciona "BETA" y ve todo de BETA. Para clientes con acceso a Grafana (futuro): Grafana Organizations + RBAC limita cada cliente a ver solo sus datos. #### Prioridad | Paso | Qué | Cuándo | |------|-----|--------| | Construir dashboard base con paneles de VMs y backups | Mes 1 | | Añadir storage PBS y tendencia | Mes 1 | | Añadir sync PBS2 y verify | Mes 2 | | Añadir seguridad (Wazuh) y conectividad (WG) | Mes 2-3 | | Integrar variable de Netbox (automático al añadir clientes) | Mes 2 | --- ## 7.2 SLOs/SLIs (niveles de servicio medibles) ### El problema Hoy se dice al cliente "tus backups se hacen diariamente" pero no se mide. Si un backup falla 3 días seguidos y nadie mira, no se sabe. Cuando el cliente pregunta "¿cuál ha sido mi uptime este mes?" la respuesta es "no sé, creo que bien". Sin métricas de nivel de servicio: - No puedes definir SLAs con datos reales - No sabes si estás cumpliendo lo que prometes - No puedes detectar degradación gradual (funciona, pero cada vez peor) - No tienes datos para justificar precio o mejoras ### DECISION 7.2 (confirmada) **Definir SLIs medibles y trackearlos en Grafana.** No es necesario implementar un sistema de SLO formal (Google SRE style con error budgets). Es suficiente con métricas que respondan a las preguntas clave del negocio. #### SLIs definidos | SLI | Qué mide | Cómo se calcula | Objetivo | |-----|----------|----------------|----------| | **Backup freshness** | ¿El backup es reciente? | Tiempo desde último backup exitoso | < 24h | | **Backup success rate** | ¿Los backups funcionan? | Backups exitosos / backups programados (30 días) | > 99% | | **Verify pass rate** | ¿Los backups son íntegros? | Verificaciones OK / verificaciones ejecutadas | > 99.5% | | **Sync freshness** | ¿PBS2 está al día? | Tiempo desde última sincronización exitosa | < 48h | | **Storage headroom** | ¿Queda espacio? | % libre del quota del cliente | > 15% | | **VM availability** | ¿Las VMs están UP? | Tiempo UP / tiempo total (30 días) | > 99.5% | | **Restore time** | ¿Cuánto tarda un restore? | Tiempo medio de restore (medido en ejercicios) | < 2h | #### Implementación en Grafana ```promql # SLI: Backup freshness (horas desde último backup) (time() - pbs_snapshot_timestamp{datastore="$customer"}) / 3600 # SLI: Backup success rate (últimos 30 días) # Requiere recording rule que cuente éxitos/intentos pbs_backup_success_total{datastore="$customer"} / pbs_backup_attempts_total{datastore="$customer"} # SLI: VM availability (30 días) avg_over_time(up{job="pve", instance=~"$customer.*"}[30d]) # SLI: Storage headroom 1 - (pbs_datastore_used_bytes{datastore="$customer"} / pbs_datastore_size_bytes{datastore="$customer"}) ``` #### Panel SLO en Grafana ``` ┌──────────────────────────────────────────────────┐ │ SLOs - ACME Corp - Marzo 2026 │ ├──────────────────────────────────────────────────┤ │ │ │ Backup Freshness ████████████████████ 100% │ │ Objetivo: < 24h Actual: 3h ✅ │ │ │ │ Backup Success ████████████████████ 100% │ │ Objetivo: > 99% Actual: 30/30 días ✅ │ │ │ │ Verify Pass Rate ███████████████████░ 99.7% │ │ Objetivo: > 99.5% Actual: 1 warn en 30d ✅ │ │ │ │ Sync PBS2 ████████████████████ 100% │ │ Objetivo: < 48h Actual: 6h ✅ │ │ │ │ Storage Headroom █████████████░░░░░░░ 61% │ │ Objetivo: > 15% Actual: 366 GB libre ✅ │ │ │ │ VM Availability ████████████████████ 99.97% │ │ Objetivo: > 99.5% Actual: 12min down ✅ │ │ │ │ Score global: 6/6 SLOs cumplidos ✅ │ │ │ └──────────────────────────────────────────────────┘ ``` #### Alertas de SLO | Alerta | Condición | Severidad | |--------|-----------|-----------| | SLOBackupFreshnessBreach | Backup > 24h para cualquier VM | Critical | | SLOBackupSuccessLow | Success rate < 99% en ventana 7d | Warning | | SLOSyncFreshnessBreach | Sync PBS2 > 48h | Critical | | SLOStorageHeadroomLow | Storage headroom < 15% | Warning | | SLOVMAvailabilityLow | VM availability < 99.5% en ventana 7d | Warning | Estas alertas son **adicionales** a las de infraestructura (Capa 1). Las de Capa 1 dicen "algo falla ahora". Las de SLO dicen "estamos incumpliendo lo que prometimos". #### Prioridad | Paso | Qué | Cuándo | |------|-----|--------| | Definir SLIs de backup (freshness + success) | Mes 1 | | Panel SLO básico en Grafana | Mes 2 | | Añadir SLIs de sync, verify, storage | Mes 2 | | Añadir SLI de VM availability | Mes 3 | | Recording rules para cálculos eficientes | Mes 3 | --- ## 7.3 Capacity planning (planificación de capacidad) ### El problema - Un cliente llena su quota de PBS un viernes a las 22h → no hay backups del fin de semana → ticket el lunes - Un pool ZFS llega al 80% → rendimiento degrada → todos los clientes del pool sufren - Se contratan 10 clientes nuevos y no se sabe si caben en el PBS actual o hay que provisionar otro Hoy se reacciona cuando algo se llena. Con datos de tendencia se puede **anticipar semanas antes**. ### DECISION 7.3 (confirmada) **Dashboards de tendencia en Grafana con funciones de predicción de VictoriaMetrics.** VictoriaMetrics tiene funciones nativas de predicción que Prometheus no tiene: #### Predicción de llenado ```promql # ¿Cuándo se llena el datastore de ACME? # predict_linear: regresión lineal sobre los últimos 30 días predict_linear(pbs_datastore_used_bytes{datastore="acme"}[30d], 86400*90) # ¿Cuántos días quedan para llegar al 100% del quota? (pbs_datastore_size_bytes{datastore="$customer"} - pbs_datastore_used_bytes{datastore="$customer"}) / deriv(pbs_datastore_used_bytes{datastore="$customer"}[30d]) / 86400 ``` #### Panel de capacity planning ``` ┌──────────────────────────────────────────────────────────┐ │ CAPACITY PLANNING - Todos los clientes │ ├──────────────────────────────────────────────────────────┤ │ │ │ ⚠️ ATENCIÓN REQUERIDA (se llenan en < 60 días) │ │ ┌───────────┬──────────┬────────┬───────────────────┐ │ │ │ Cliente │ Usado │ Quota │ Días para llenarse│ │ │ ├───────────┼──────────┼────────┼───────────────────┤ │ │ │ DELTA │ 520/600 │ 87% │ ⚠️ 23 días │ │ │ │ GAMMA │ 380/500 │ 76% │ ⚠️ 45 días │ │ │ └───────────┴──────────┴────────┴───────────────────┘ │ │ │ │ ✅ SIN RIESGO (> 60 días) │ │ ┌───────────┬──────────┬────────┬───────────────────┐ │ │ │ ACME │ 234/600 │ 39% │ 174 días │ │ │ │ BETA │ 120/400 │ 30% │ 280 días │ │ │ │ ... (47 clientes más) │ │ │ └───────────────────────────────────────────────────┘ │ │ │ │ 📊 POOL ZFS GLOBAL │ │ pool9: 18.2 TB / 24 TB (76%) │ │ Tendencia: +120 GB/semana → lleno en ~48 semanas │ │ Recomendación: planificar ampliación antes del Q4 │ │ │ │ 📈 CRECIMIENTO POR CLIENTE (últimos 90 días) │ │ DELTA: +8.2 GB/semana (el que más crece) │ │ GAMMA: +5.1 GB/semana │ │ ACME: +2.1 GB/semana │ │ BETA: +1.3 GB/semana │ │ │ └──────────────────────────────────────────────────────────┘ ``` #### Alertas de capacity | Alerta | Condición | Severidad | |--------|-----------|-----------| | CapacityDatastoreFull30d | Datastore se llena en < 30 días (predicción) | Warning | | CapacityDatastoreFull7d | Datastore se llena en < 7 días (predicción) | Critical | | CapacityPoolFull90d | Pool ZFS se llena en < 90 días (predicción) | Warning | | CapacityPoolFull30d | Pool ZFS se llena en < 30 días (predicción) | Critical | Estas alertas permiten actuar **semanas antes**: contactar al cliente para ampliar quota, provisionar disco adicional, o redistribuir clientes entre pools. #### Prioridad | Paso | Qué | Cuándo | |------|-----|--------| | Panel básico de uso por cliente con tendencia | Mes 1-2 | | Predicción de llenado (predict_linear) | Mes 2 | | Alertas de capacity (30d, 7d) | Mes 2 | | Panel de crecimiento por cliente | Mes 3 | --- ## 7.4 Status page e informes para clientes ### El problema - El cliente no tiene visibilidad de su servicio: no sabe si sus backups funcionan, si su storage está bien, cuánto espacio le queda - Cuando hay una incidencia, el cliente se entera porque algo no funciona, no porque se le haya comunicado - No hay informes periódicos: "este mes todo fue bien" no tiene datos detrás ### DECISION 7.4 (confirmada) **Dos herramientas, dos públicos, dos momentos:** #### A) Status page per-client (tiempo real) Cada cliente puede ver el estado actual de sus servicios. Dos opciones: **Opción simple (mes 2): Grafana con permisos** - Grafana Organizations: una org por cliente - Dashboards de solo lectura con sus métricas - SSO con Authentik (el cliente entra con su cuenta) - Ve: VMs (UP/DOWN), backups (último, estado), storage (uso) - No ve: métricas de otros clientes, infra interna **Opción dedicada (mes 3+): página de diagnóstico custom** Ya documentada en Capa 4.2: Flask/FastAPI ligero, SSO Authentik, detecta IP WG del cliente, muestra checks en tiempo real. Complementa el dashboard Grafana con tests activos (WG conectado, DNS resolviendo, certificado válido, PBS accesible). #### B) Informes periódicos (mensuales) Informe mensual generado automáticamente y enviado al cliente: ``` ┌──────────────────────────────────────────────────┐ │ INFORME MENSUAL - ACME Corp - Marzo 2026 │ ├──────────────────────────────────────────────────┤ │ │ │ RESUMEN EJECUTIVO │ │ ✅ Todos los SLOs cumplidos │ │ ✅ 0 incidencias de seguridad │ │ ✅ Storage en niveles saludables │ │ │ │ BACKUPS │ │ - Backups exitosos: 150/150 (100%) │ │ - Último verify: OK (12/03/2026) │ │ - Copia archivo (PBS2): sincronizada │ │ │ │ STORAGE │ │ - Uso actual: 234 GB / 600 GB (39%) │ │ - Crecimiento mes: +8.4 GB │ │ - Estimación llenado: 174 semanas │ │ │ │ DISPONIBILIDAD │ │ - Uptime VMs: 99.97% (12 min downtime) │ │ - Downtime planificado: 10 min (actualización) │ │ - Downtime no planificado: 2 min (reinicio red) │ │ │ │ SEGURIDAD │ │ - Eventos Wazuh: 687 (todos nivel informativo) │ │ - Alertas críticas: 0 │ │ - Vulnerabilidades parcheadas: 3 │ │ │ └──────────────────────────────────────────────────┘ ``` Implementación: ``` Semaphore (cron mensual, día 1) → Playbook que consulta APIs: - VictoriaMetrics (métricas del mes) - Loki (eventos del mes) - PBS API (backups, verify) → Genera PDF/HTML con template Jinja2 → Envía por email o lo deja en Outline/Zammad ``` No es urgente. Es un diferenciador de servicio que se implementa cuando el stack está maduro. #### Prioridad | Paso | Qué | Cuándo | |------|-----|--------| | Grafana org por cliente (los que lo pidan) | Mes 3 | | Página de diagnóstico custom | Mes 3+ | | Template de informe mensual | Mes 4+ | | Automatización de generación y envío | Mes 4+ | --- ## 7.5 Correlación avanzada (métricas + logs + seguridad) ### El problema Las herramientas de las Capas 1-2 generan datos en silos: - VictoriaMetrics tiene métricas (CPU, disco, red) - Loki tiene logs (auth, syslog, PBS) - Wazuh tiene eventos de seguridad (FIM, rootkits, vulnerabilidades) Para investigar un incidente hay que saltar entre 3 herramientas y correlacionar mentalmente: "el disco subió a las 03:15, a ver qué hay en los logs a las 03:15, a ver si Wazuh detectó algo a las 03:15". ### DECISION 7.5 (confirmada) **Grafana como panel de correlación único.** Grafana ya soporta múltiples data sources en el mismo dashboard y la misma vista temporal. #### Dashboard de investigación Un dashboard dedicado a investigar incidentes, con todos los data sources sincronizados en el mismo rango temporal: ``` ┌─────────────────────────────────────────────────────────┐ │ INVESTIGACIÓN - Servidor: ns31787946 │ │ Rango temporal: [13/03/2026 02:00 - 04:00] │ ├─────────────────────────────────────────────────────────┤ │ │ │ 📊 MÉTRICAS (VictoriaMetrics) │ │ CPU: ─────────────────╱╲───────────── pico 92% 03:12 │ │ IO: ────────────────╱──╲──────────── pico 03:12-03:18│ │ Disco:────────────────────/──────────── subió 2GB 03:15│ │ Red: ─────────────────────────────── normal │ │ │ │ 📝 LOGS (Loki) │ │ 03:10 [syslog] proxmox-backup: starting GC datastore X │ │ 03:12 [syslog] proxmox-backup: GC phase1 marking... │ │ 03:15 [syslog] zfs: pool9: io error on sda │ │ 03:15 [auth] sshd: Accepted key for root from 83.50… │ │ 03:16 [syslog] proxmox-backup: GC failed: IO error │ │ 03:18 [syslog] zfs: pool9: scrub repaired 4K │ │ │ │ 🔒 SEGURIDAD (Wazuh via Loki o API) │ │ 03:15 [level 7] File integrity: /var/log changed │ │ 03:15 [level 3] SSH login from known IP (informativo) │ │ │ │ CORRELACIÓN AUTOMÁTICA: │ │ → GC empezó a las 03:10 │ │ → Error de IO en disco sda a las 03:15 │ │ → GC falló por el error de IO │ │ → ZFS reparó el error (scrub) │ │ → El login SSH fue del técnico investigando │ │ → Conclusión: problema de disco, no seguridad │ │ │ └─────────────────────────────────────────────────────────┘ ``` #### Cómo funciona en Grafana Grafana tiene la funcionalidad **Explore** que permite: - Seleccionar un rango temporal en una gráfica de métricas - Ver automáticamente los logs de Loki del mismo período - Usar **annotations** para marcar eventos de Wazuh en las gráficas de métricas - **Split view**: métricas a la izquierda, logs a la derecha, sincronizados ```yaml # Annotations automáticas en dashboards de métricas # Marca eventos de Wazuh como líneas verticales en las gráficas annotations: - name: Wazuh Alerts datasource: Loki expr: '{job="wazuh"} |= "level" | json | level >= 10' tagKeys: rule.description textFormat: "{{rule.description}}" ``` #### Wazuh en Grafana Dos opciones para tener datos de Wazuh en Grafana: | Opción | Cómo | Pros | Contras | |--------|------|------|---------| | **Wazuh logs → Loki** | Alloy recoge logs de Wazuh Manager y los envía a Loki | Consultas LogQL en Grafana, mismo data source que otros logs | Requiere parsear formato Wazuh | | **Wazuh API → Grafana** | Plugin Grafana o JSON datasource que consulta API de Wazuh | Datos estructurados, alertas con metadata | Plugin no oficial, mantenimiento | **Recomendación**: Wazuh logs → Loki (opción A). Los alertas de Wazuh van al JSON log de `/var/ossec/logs/alerts/alerts.json`. Alloy los recoge y envía a Loki con labels (level, rule_id, agent_name). Consultas LogQL funcionan directamente. #### Prioridad | Paso | Qué | Cuándo | |------|-----|--------| | Wazuh alerts.json → Alloy → Loki | Mes 1 (junto con despliegue Alloy) | | Dashboard de investigación básico (métricas + logs) | Mes 2 | | Annotations de Wazuh en dashboards de métricas | Mes 2 | | Dashboard de investigación completo con correlación | Mes 3 | --- ## Resumen Capa 7 completa (DECISIONES FINALES) ``` ┌─────────────────────────────────────────────────────┐ │ CAPA 7: OBSERVABILIDAD AVANZADA │ ├─────────────────────────────────────────────────────┤ │ │ │ 7.1 DASHBOARDS POR CLIENTE (confirmada) │ │ ┌───────────────────────────────────┐ │ │ │ Un dashboard Grafana con │ │ │ │ variable dropdown por cliente │ │ │ │ - VMs, backups, storage, sync │ │ │ │ - Seguridad, conectividad │ │ │ │ - Variables desde Netbox │ │ │ └───────────────────────────────────┘ │ │ │ │ 7.2 SLOs/SLIs (confirmada) │ │ ┌───────────────────────────────────┐ │ │ │ Métricas de nivel de servicio │ │ │ │ - Backup freshness < 24h │ │ │ │ - Backup success > 99% │ │ │ │ - VM availability > 99.5% │ │ │ │ - Storage headroom > 15% │ │ │ │ - Sync freshness < 48h │ │ │ │ Panel SLO en Grafana │ │ │ └───────────────────────────────────┘ │ │ │ │ 7.3 CAPACITY PLANNING (confirmada) │ │ ┌───────────────────────────────────┐ │ │ │ Predicción de llenado │ │ │ │ - predict_linear (VictoriaM.) │ │ │ │ - Alertas: lleno en <30d, <7d │ │ │ │ - Crecimiento por cliente │ │ │ │ - Panel pool ZFS global │ │ │ └───────────────────────────────────┘ │ │ │ │ 7.4 STATUS PAGE + INFORMES (confirmada) │ │ ┌───────────────────────────────────┐ │ │ │ Grafana org per-client (mes 3) │ │ │ │ Página diagnóstico custom (3+) │ │ │ │ Informes mensuales auto (mes 4+)│ │ │ │ - Template Jinja2 → PDF/HTML │ │ │ │ - Envío automático por email │ │ │ └───────────────────────────────────┘ │ │ │ │ 7.5 CORRELACIÓN AVANZADA (confirmada) │ │ ┌───────────────────────────────────┐ │ │ │ Grafana como panel único de │ │ │ │ investigación │ │ │ │ - Métricas + Logs + Wazuh │ │ │ │ - Mismo rango temporal │ │ │ │ - Annotations de seguridad │ │ │ │ - Wazuh alerts → Loki │ │ │ └───────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────┘ Recursos Capa 7: - Herramientas nuevas: NINGUNA - Todo se construye sobre Grafana + VictoriaMetrics + Loki + Wazuh + Netbox (ya desplegados en Capas 1-2) - Coste: 0 (dashboards, queries, recording rules) - Esfuerzo: configuración progresiva meses 1-4 ```