Operar nodos blockchain sin monitoreo es como volar a ciegas. Un nodo que pierde sincronización, se queda sin peers o consume todo el disco disponible puede generar perdidas economicas directas, especialmente si esta involucrado en validación o staking. Prometheus, combinado con Grafana y Alertmanager, proporciona el stack de observabilidad necesario para mantener nodos blockchain en condiciones optimas. En esta guía cubrimos la configuración completa desde cero, las métricas criticas, dashboards y alertas para nodos Ethereum.

Por que Prometheus para blockchain

Prometheus es el estandar de facto para monitoreo de infraestructura en el ecosistema cloud-native, y los clientes de Ethereum lo adoptaron nativamente:

  • Geth, Nethermind, Besu y Erigon (clientes de ejecución) exponen métricas en formato Prometheus.
  • Lighthouse, Prysm, Teku, Lodestar y Nimbus (clientes de consenso) también incluyen endpoints de métricas Prometheus.
  • Model pull: Prometheus hace scrape de los endpoints, lo que simplifica la configuración en comparación con modelos push.
  • PromQL: El lenguaje de consultas permite crear alertas y dashboards sofisticados.

Configuración de Prometheus para nodos Ethereum

Arquitectura del stack

El stack de monitoreo completo consiste en:

Nodos Ethereum (EL + CL)
    |-- metricas --> Prometheus (recoleccion + almacenamiento)
                        |-- consultas --> Grafana (visualizacion)
                        |-- alertas --> Alertmanager (notificaciones)

Configuración base de Prometheus

# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "alerts/*.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets:
            - alertmanager:9093

scrape_configs:
  # Cliente de ejecucion - Geth
  - job_name: 'geth'
    metrics_path: /debug/metrics/prometheus
    static_configs:
      - targets: ['localhost:6060']
        labels:
          client: 'geth'
          layer: 'execution'

  # Cliente de ejecucion - Nethermind
  - job_name: 'nethermind'
    static_configs:
      - targets: ['localhost:9091']
        labels:
          client: 'nethermind'
          layer: 'execution'

  # Cliente de consenso - Lighthouse
  - job_name: 'lighthouse-beacon'
    static_configs:
      - targets: ['localhost:5054']
        labels:
          client: 'lighthouse'
          layer: 'consensus'

  # Lighthouse validator client
  - job_name: 'lighthouse-validator'
    static_configs:
      - targets: ['localhost:5064']
        labels:
          client: 'lighthouse'
          component: 'validator'

  # Node exporter para metricas del sistema
  - job_name: 'node-exporter'
    static_configs:
      - targets: ['localhost:9100']

Habilitar métricas en los clientes

Cada cliente expone métricas de forma diferente. Es necesario habilitar los endpoints al iniciar el nodo:

# Geth - habilitar metricas Prometheus
geth \
  --metrics \
  --metrics.addr 0.0.0.0 \
  --metrics.port 6060 \
  --pprof \
  --pprof.addr 0.0.0.0 \
  --pprof.port 6061

# Lighthouse - habilitar metricas
lighthouse bn \
  --metrics \
  --metrics-address 0.0.0.0 \
  --metrics-port 5054 \
  --metrics-allow-origin "*"

# Nethermind - metricas habilitadas por defecto en puerto 9091
nethermind \
  --Metrics.Enabled true \
  --Metrics.ExposePort 9091 \
  --Metrics.PushGatewayUrl ""  # Usar pull, no push

# Prysm - habilitar metricas
prysm-beacon-chain \
  --monitoring-host 0.0.0.0 \
  --monitoring-port 8080

Métricas criticas para nodos blockchain

Métricas de sincronización

La sincronización es la métrica mas fundamental. Un nodo desincronizado es un nodo inutilizable:

# Diferencia entre el bloque local y el bloque mas reciente de la red (Geth)
ethereum_blockchain_height - ethereum_blockchain_head_header

# Porcentaje de sincronizacion completada
(ethereum_blockchain_head_header / ethereum_blockchain_height) * 100

# Estado de sincronizacion del beacon node (Lighthouse)
beacon_head_slot
beacon_finalized_epoch

Métricas de peers

La conectividad con la red determina la capacidad del nodo para recibir y propagar información:

# Numero de peers conectados (Geth)
p2p_peers

# Peers del beacon node (Lighthouse)
libp2p_peers

# Alertar si los peers caen por debajo de un umbral
# (ver seccion de alertas)

Métricas de bloques y transacciones

# Altura del bloque actual (Geth)
chain_head_block

# Transacciones pendientes en el mempool
txpool_pending

# Transacciones en cola
txpool_queued

# Tasa de bloques procesados
rate(chain_inserts_total[5m])

Métricas del sistema

El node exporter proporciona métricas del servidor que son igualmente criticas:

# Uso de CPU
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# Memoria disponible
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100

# Disco disponible (critico para nodos blockchain)
node_filesystem_avail_bytes{mountpoint="/data"} / node_filesystem_size_bytes{mountpoint="/data"} * 100

# I/O de disco (los nodos blockchain son intensivos en I/O)
rate(node_disk_read_bytes_total[5m])
rate(node_disk_written_bytes_total[5m])

Métricas de validadores

Si el nodo opera como validador, estas métricas adicionales son esenciales:

# Atestaciones exitosas (Lighthouse validator)
validator_successful_attestations

# Propuestas de bloque
validator_successful_block_proposals

# Balance del validador
validator_balance_gwei

# Efectividad de atestacion
validator_attestation_hit_percentage

Dashboards de Grafana

Dashboard para cliente de ejecución

Un dashboard efectivo para el cliente de ejecución debe incluir estos paneles:

  • Resumen de sincronización: Bloque actual vs bloque de la red, con indicador de estado.
  • Peers: Grafico de lineas con el número de peers en las ultimas 24 horas.
  • Mempool: Transacciones pending y queued.
  • Rendimiento de RPC: Latencia y tasa de peticiones por método JSON-RPC.
  • Recursos del sistema: CPU, memoria, disco, I/O.

Dashboard para cliente de consenso

  • Slot y epoch actual: Con diferencia respecto al head de la red.
  • Finalización: Ultimo epoch finalizado y distancia al head.
  • Atestaciones: Tasa de éxito y efectividad de inclusion.
  • Participación de la red: Porcentaje de validadores activos.
  • Peers P2P: Conexiones entrantes y salientes.

Existen dashboards comunitarios publicados en grafana.com/dashboards para los principales clientes. Por ejemplo:

  • Geth dashboard: ID 13877
  • Lighthouse dashboard: ID 16214
  • Prysm dashboard: ID 13457
# Importar un dashboard desde la CLI de Grafana
curl -X POST http://admin:admin@localhost:3000/api/dashboards/import \
  -H "Content-Type: application/json" \
  -d '{
    "dashboard": { "id": null },
    "overwrite": true,
    "inputs": [],
    "folderId": 0,
    "pluginId": "grafana-piechart-panel",
    "path": "dashboards/geth.json"
  }'

Reglas de alertas

Las alertas deben cubrir tanto las métricas blockchain como las del sistema:

# alerts/blockchain.yml
groups:
  - name: blockchain-node-alerts
    rules:
      # Sincronizacion
      - alert: NodeOutOfSync
        expr: (ethereum_blockchain_height - chain_head_block) > 50
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Nodo desincronizado por mas de 50 bloques"
          description: "El nodo {{ $labels.instance }} esta {{ $value }} bloques detras de la red."

      # Peers
      - alert: LowPeerCount
        expr: p2p_peers < 5
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Peers por debajo del minimo"
          description: "El nodo {{ $labels.instance }} tiene solo {{ $value }} peers."

      # Disco
      - alert: DiskSpaceLow
        expr: (node_filesystem_avail_bytes{mountpoint="/data"} / node_filesystem_size_bytes{mountpoint="/data"}) < 0.10
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Espacio en disco critico"
          description: "Menos del 10% de disco disponible en {{ $labels.instance }}."

      # Finalizacion (consenso)
      - alert: FinalizationStalled
        expr: (beacon_head_slot - beacon_finalized_epoch * 32) > 128
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "Finalizacion detenida"
          description: "Han pasado mas de 4 epochs sin finalizar en {{ $labels.instance }}."

      # Mempool saturado
      - alert: MempoolOverflow
        expr: txpool_pending > 10000
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "Mempool con acumulacion excesiva"

Configuración de Alertmanager

# alertmanager.yml
global:
  resolve_timeout: 5m

route:
  group_by: ['alertname', 'instance']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'devops-team'

  routes:
    - match:
        severity: critical
      receiver: 'devops-critical'
      repeat_interval: 1h

receivers:
  - name: 'devops-team'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/TU/WEBHOOK/URL'
        channel: '#blockchain-alerts'
        title: '{{ .CommonAnnotations.summary }}'
        text: '{{ .CommonAnnotations.description }}'

  - name: 'devops-critical'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/TU/WEBHOOK/URL'
        channel: '#blockchain-critical'
    pagerduty_configs:
      - service_key: 'TU_PAGERDUTY_KEY'

Automatización de salud del nodo

Complementar Prometheus con scripts de health check permite implementar acciones automaticas:

#!/bin/bash
# health_check.sh - verificacion de salud del nodo

GETH_RPC="http://localhost:8545"
THRESHOLD_BLOCKS=30

# Obtener bloque local y bloque de la red
LOCAL_BLOCK=$(curl -s -X POST $GETH_RPC \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
  | jq -r '.result' | xargs printf "%d\n")

NETWORK_BLOCK=$(curl -s "https://api.etherscan.io/api?module=proxy&action=eth_blockNumber" \
  | jq -r '.result' | xargs printf "%d\n")

DIFF=$((NETWORK_BLOCK - LOCAL_BLOCK))

if [ "$DIFF" -gt "$THRESHOLD_BLOCKS" ]; then
  echo "ALERTA: Nodo desincronizado por $DIFF bloques"
  # Reiniciar servicio si la diferencia es critica
  if [ "$DIFF" -gt 100 ]; then
    systemctl restart geth
    echo "Servicio geth reiniciado automaticamente"
  fi
fi

# Verificar espacio en disco
DISK_USAGE=$(df /data --output=pcent | tail -1 | tr -d ' %')
if [ "$DISK_USAGE" -gt 90 ]; then
  echo "ALERTA: Disco al ${DISK_USAGE}%"
fi

Este script puede ejecutarse via cron o como un servicio systemd con timer para complementar las alertas de Prometheus.

Mejores prácticas

  • Scrape interval adecuado: 15 segundos es un buen balance entre granularidad y carga. Para métricas de validadores, 10 segundos puede ser necesario.
  • Retention policy: Los nodos blockchain generan muchas métricas. Configurar retención adecuada (30-90 dias) y considerar almacenamiento remoto (Thanos, VictoriaMetrics) para datos historicos.
  • Separar métricas por capa: Usar labels para distinguir métricas de ejecución, consenso y validador.
  • Alertas con contexto: Incluir en las anotaciones información suficiente para diagnosticar sin necesidad de investigar inmediatamente.
  • Proteger los endpoints de métricas: No exponer los puertos de métricas a internet. Usar firewalls o bind a localhost.

Conclusion

Prometheus es la herramienta natural para monitorear nodos blockchain gracias a su adopción nativa por los clientes de Ethereum. La combinación de métricas de sincronización, peers, mempool, validadores y recursos del sistema proporciona la visibilidad completa necesaria para operar nodos de forma confiable. Las alertas bien configuradas permiten responder rápidamente ante desincronización, perdida de peers o problemas de disco, que son los escenarios mas comunes en la operación de infraestructura blockchain.

Recursos