Ir al contenido

Monitoreo de contenedores Docker con Prometheus y Grafana en casa: métricas de CPU, memoria y alertas automáticas

Rogelio Guerra Riverón
Autor
Rogelio Guerra Riverón
Construyendo mi propia infraestructura web desde cero. Aquí documento cada paso: servidores, redes, contenedores y lo que vaya surgiendo.

El problema
#

Después de meses corriendo varios contenedores en mi servidor doméstico, me pasó lo inevitable: un servicio se fue al piso sin que me enterara. Necesitaba visibilidad sobre qué estaba pasando con mis contenedores. Así que arremangué y configuré Prometheus + Grafana + Alertmanager. Acá está cómo lo hice.

Qué necesitas
#

  • Docker y Docker Compose instalados
  • Un servidor con recursos suficientes (en mi caso un viejo i5 con 8GB de RAM)
  • Paciencia para debuggear YAML

Paso 1: Configurar cAdvisor
#

Primero necesitamos que Docker exponga métricas. Voy a usar cAdvisor, que es el exporter oficial de Google para contenedores.

cadvisor:
  image: gcr.io/cadvisor/cadvisor:latest
  volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:rw
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro
  ports:
    - "8080:8080"
  restart: unless-stopped

Accedé a http://localhost:8080 y verificá que las métricas estén disponibles en /metrics.

Paso 2: Instalar Prometheus
#

Prometheus es quien scrappea las métricas. Creé un prometheus.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']
  
  - job_name: 'docker'
    static_configs:
      - targets: ['localhost:9323']

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

rule_files:
  - '/etc/prometheus/alerts.yml'

En el docker-compose:

prometheus:
  image: prom/prometheus:latest
  volumes:
    - ./prometheus.yml:/etc/prometheus/prometheus.yml
    - ./alerts.yml:/etc/prometheus/alerts.yml
    - prometheus_data:/prometheus
  ports:
    - "9090:9090"
  command:
    - '--config.file=/etc/prometheus/prometheus.yml'
    - '--storage.tsdb.path=/prometheus'
  restart: unless-stopped

Paso 3: Reglas de alertas
#

Creé alerts.yml con reglas básicas:

groups:
  - name: docker
    interval: 30s
    rules:
      - alert: ContainerHighCPU
        expr: (rate(container_cpu_usage_seconds_total[5m]) * 100) > 80
        for: 5m
        annotations:
          summary: "{{ $labels.name }} tiene CPU alta"
          
      - alert: ContainerHighMemory
        expr: (container_memory_working_set_bytes / 1073741824) > 2
        for: 5m
        annotations:
          summary: "{{ $labels.name }} usa más de 2GB de RAM"

Paso 4: Alertmanager con correo
#

Alertmanager es quien envía las notificaciones. Configuré alertmanager.yml:

global:
  resolve_timeout: 5m
  smtp_smarthost: 'smtp.gmail.com:587'
  smtp_auth_username: 'tu-email@gmail.com'
  smtp_auth_password: 'tu-app-password'
  smtp_from: 'tu-email@gmail.com'

route:
  receiver: 'email'
  repeat_interval: 1h

receivers:
  - name: 'email'
    email_configs:
      - to: 'tu-email@gmail.com'
        headers:
          Subject: 'Alerta de Docker: {{ .GroupLabels.alertname }}'

Nota: Para Gmail necesitas una app password, no tu contraseña normal.

En docker-compose:

alertmanager:
  image: prom/alertmanager:latest
  volumes:
    - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
    - alertmanager_data:/alertmanager
  ports:
    - "9093:9093"
  restart: unless-stopped

Paso 5: Grafana para visualizar
#

grafana:
  image: grafana/grafana:latest
  ports:
    - "3000:3000"
  environment:
    - GF_SECURITY_ADMIN_PASSWORD=admin
  volumes:
    - grafana_data:/var/lib/grafana
  restart: unless-stopped

Accedé a http://localhost:3000, configuré Prometheus como datasource y descargué un dashboard público de Docker. Yo uso este.

Resultado
#

Ahora veo en tiempo real qué está pasando con mis contenedores. Cuando algo se dispara, recibo un correo en menos de un minuto. No es monitoreo de nivel enterprise, pero para casa funciona perfectamente.

Lo más importante: dormía mejor sabiendo que si algo explota, me entero.