Dia 25: Monitoring com Prometheus e Grafana no Linux

Saber o estado de um servidor Linux não se resume a verificar se ele responde a ping. Monitorização é sobre CPU, memória, disco, rede, processos e serviços — de forma contínua, histórica e accionável. Prometheus recolhe métricas via exporters, armazena-as numa base de dados de séries temporais e permite consultas com PromQL. Grafana liga-se ao Prometheus e apresenta dashboards visuais com alertas. Este artigo mostra como instalar ambos, configurar o node_exporter, criar dashboards e definir regras de alerta num servidor Linux.

A stack Prometheus + Grafana é o padrão de facto para monitorização em infraestruturas modernas (Prometheus docs, Grafana docs). Funciona em qualquer distribuição Linux e é gratuita.

Nota: Os comandos abaixo usam apt (Debian/Ubuntu) e dnf (RHEL/Rocky/Alma). Se a distribuição usar um gestor diferente, adaptar o comando de instalação.

Arquitectura da Stack Prometheus + Grafana

A arquitectura divide-se em três camadas. O node_exporter corre em cada servidor monitorizado e expõe métricas do sistema (CPU, memória, disco, rede) num endpoint HTTP na porta 9100. O Prometheus é o servidor central que faz scrape desses endpoints em intervalos configuráveis (por defeito, 15 segundos), armazena as métricas localmente e permite consultas via PromQL. O Grafana é a camada de visualização que se liga ao Prometheus como datasource e apresenta os dados em dashboards.

O fluxo de dados é simples: exporters → Prometheus (scrape + store) → Grafana (query + display). Não há push de métricas dos servidores para o Prometheus — é o Prometheus que vai buscar os dados (modelo pull). Isto simplifica firewalls porque só é necessário permitir tráfego de saída do Prometheus para os exporters Prometheus docs.

Instalar o Prometheus

O Prometheus pode ser instalado via repositório ou binário directo. Para Debian/Ubuntu, o pacote oficial existe em repositórios de terceiros. Para RHEL/Rocky/Alma, há pacotes via copr. A forma mais universal é descarregar o binário da página oficial.

Descarregar e instalar o binário Prometheus (universal, qualquer distribuição):

# Criar utilizador do sistema para o Prometheus
sudo useradd --system --no-create-home --shell /usr/sbin/nologin prometheus

# Descarregar a versão mais recente (verificar a última em https://prometheus.io/download/)
wget https://github.com/prometheus/prometheus/releases/download/v3.2.1/prometheus-3.2.1.linux-amd64.tar.gz

# Extrair e instalar
tar xzf prometheus-3.2.1.linux-amd64.tar.gz
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo cp prometheus-3.2.1.linux-amd64/prometheus /usr/local/bin/
sudo cp prometheus-3.2.1.linux-amd64/promtool /usr/local/bin/
sudo cp -r prometheus-3.2.1.linux-amd64/consoles /etc/prometheus/
sudo cp -r prometheus-3.2.1.linux-amd64/console_libraries /etc/prometheus/
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus

Criar o ficheiro de configuração principal do Prometheus:

sudo tee /etc/prometheus/prometheus.yml > /dev/null << 'EOF'
global:
  scrape_interval: 15s
  evaluation_interval: 15s

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

rule_files:
  # - "alert_rules.yml"

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

  - job_name: "node_exporter"
    static_configs:
      - targets: ["localhost:9100"]
EOF

sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml

Criar o serviço systemd para o Prometheus arrancar automaticamente:

sudo tee /etc/systemd/system/prometheus.service > /dev/null << 'EOF'
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
  --config.file=/etc/prometheus/prometheus.yml \
  --storage.tsdb.path=/var/lib/prometheus \
  --web.console.templates=/etc/prometheus/consoles \
  --web.console.libraries=/etc/prometheus/console_libraries \
  --web.listen-address=0.0.0.0:9090

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
sudo systemctl status prometheus

Após iniciar, o Prometheus fica disponível em http://localhost:9090. O endpoint /targets mostra o estado de cada exporter configurado Prometheus configuration docs.

Instalar o node_exporter

O node_exporter é o exporter mais comum para métricas de sistema Linux. Expõe CPU, memória, disco, rede, filesystem e muito mais na porta 9100. Corre em cada servidor que se pretende monitorizar node_exporter no GitHub.

Instalar via pacote do sistema (mais simples, quando disponível):

# Debian/Ubuntu
sudo apt update && sudo apt install -y prometheus-node-exporter
sudo systemctl enable --now prometheus-node-exporter

# RHEL/Rocky/Alma (via EPEL)
sudo dnf install -y epel-release
sudo dnf install -y node_exporter
sudo systemctl enable --now node_exporter

Alternativa: instalar via binário directo (universal):

wget https://github.com/prometheus/node_exporter/releases/download/v1.9.0/node_exporter-1.9.0.linux-amd64.tar.gz
tar xzf node_exporter-1.9.0.linux-amd64.tar.gz
sudo cp node_exporter-1.9.0.linux-amd64/node_exporter /usr/local/bin/

sudo tee /etc/systemd/system/node_exporter.service > /dev/null << 'EOF'
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/node_exporter

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter

Verificar que o node_exporter está a exportar métricas: curl -s http://localhost:9100/metrics | head -20. O output deve mostrar linhas começadas com # HELP, # TYPE e métricas como node_cpu_seconds_total.

Instalar o Grafana

O Grafana corre como serviço web na porta 3000 por defeito. A instalação via repositório oficial garante actualizações automáticas Grafana docs.

Debian/Ubuntu:

sudo apt install -y apt-transport-https software-properties-common wget
sudo wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key
echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
sudo systemctl enable --now grafana-server

RHEL/Rocky/Alma:

sudo tee /etc/yum.repos.d/grafana.repo > /dev/null << 'EOF'
[grafana]
name=grafana
baseurl=https://rpm.grafana.com
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://rpm.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF

sudo dnf install -y grafana
sudo systemctl enable --now grafana-server

Após arrancar, aceder a http://localhost:3000. As credenciais por defeito são admin / admin. O Grafana pede para alterar a password no primeiro login.

Configurar Datasource e Dashboard no Grafana

O Grafana precisa de saber onde estão as métricas. Adicionar o Prometheus como datasource é o primeiro passo. Depois, importar um dashboard pronto evita construir gráficos do zero.

Passo 1 — Adicionar datasource Prometheus:

  1. No Grafana, ir a Connections → Data sources → Add data source.
  2. Seleccionar Prometheus.
  3. Em URL, inserir http://localhost:9090 (ou o IP do servidor Prometheus).
  4. Clicar em Save & test. O Grafana deve mostrar "Data source is working".

Passo 2 — Importar um dashboard pronto:

A comunidade Grafana mantém dashboards prontos. O dashboard Node Exporter Full (ID 1860) é o mais popular para métricas de sistema Linux Grafana dashboards.

  1. No Grafana, ir a Dashboards → New → Import.
  2. Inserir o ID 1860 e clicar em Load.
  3. Seleccionar o datasource Prometheus criado no passo 1.
  4. Clicar em Import. O dashboard mostra CPU, memória, disco, rede e muito mais.
Nota: O dashboard ID 1860 é mantido pela comunidade. Se não carregar correctamente, procurar dashboards alternativos em grafana.com/grafana/dashboards com a keyword "node exporter".

Consultas PromQL Essenciais

PromQL é a linguagem de consulta do Prometheus. Não é SQL — é uma linguagem funcional optimizada para séries temporais. Estas são as consultas mais úteis para monitorização de servidores Linux.

Métrica Consulta PromQL Descrição
CPU usage (%) 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) Percentagem de CPU usada nos últimos 5 min
Memória disponível node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 Percentagem de memória disponível
Disco usado (%) 100 - (node_filesystem_avail_bytes / node_filesystem_size_bytes * 100) Percentagem de disco usado por mount point
Tráfego de rede rate(node_network_receive_bytes_total[5m]) Bytes recebidos por segundo (rx)
Uptime node_time_seconds - node_boot_time_seconds Segundos desde o último boot

A função rate() é fundamental — converte counters (que só aumentam) em taxas por segundo. Sem rate(), um counter de CPU é inútil porque só mostra o total acumulado desde o boot.

Configurar Alertas no Prometheus

Os alertas permitem receber notificações quando uma métrica ultrapassa um limiar. No Prometheus, os alertas definem-se num ficheiro de regras (rule file) e são avaliados pelo próprio Prometheus. Para enviar notificações (email, Slack, etc.), é necessário o Alertmanager, mas neste artigo ficamos pelas regras e pelo estado dos alertas visível no próprio Prometheus Prometheus alerting docs.

Criar o ficheiro de regras de alerta:

sudo tee /etc/prometheus/alert_rules.yml > /dev/null << 'EOF'
groups:
  - name: servidor_linux
    rules:
      - alert: HighCpuUsage
        expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU acima de 80% em {{ $labels.instance }}"
          description: "Uso de CPU é {{ $value }}% nos últimos 5 minutos."

      - alert: HighMemoryUsage
        expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Memória acima de 85% em {{ $labels.instance }}"
          description: "Uso de memória é {{ $value }}%."

      - alert: DiskSpaceLow
        expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < 10
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "Espaço em disco abaixo de 10% em {{ $labels.instance }}"
          description: "Mount point {{ $labels.mountpoint }} tem {{ $value }}% livre."
EOF

Activar o ficheiro de regras no prometheus.yml (descomentar a linha rule_files) e recarregar a configuração:

# Editar prometheus.yml e garantir que rule_files inclui o ficheiro:
# rule_files:
#   - "alert_rules.yml"

# Validar a configuração antes de recarregar
sudo -u prometheus /usr/local/bin/promtool check config /etc/prometheus/prometheus.yml

# Recarregar sem reiniciar o serviço (se o Prometheus tiver --web.enable-lifecycle)
curl -X POST http://localhost:9090/-/reload

# Alternativa: reiniciar o serviço
sudo systemctl restart prometheus

Os alertas activos ficam visíveis em http://localhost:9090/alerts. A cláusula for: 5m significa que o alerta só dispara se a condição se mantiver durante 5 minutos consecutivos — evita falsos positivos por picos momentâneos.

Alertas no Grafana

O Grafana tem o seu próprio sistema de alertas, independente das regras do Prometheus. A vantagem é que os alertas do Grafana podem incluir notificações directas para email, Slack, Discord ou webhook sem precisar do Alertmanager Grafana alerting docs.

  1. No Grafana, ir a Alerting → Alert rules → New alert rule.
  2. Definir a consulta PromQL (por exemplo, a de CPU acima de 80%).
  3. Definir a condição (threshold): WHEN last() OF query IS ABOVE 80.
  4. Configurar o contact point (email, Slack, webhook) em Alerting → Contact points.
  5. Guardar e testar o alerta com o botão Test rule.
Atenção: Se tanto as regras do Prometheus como as do Grafana estiverem activas para a mesma métrica, vão disparar alertas duplicados. Recomenda-se escolher um dos sistemas para evitar ruído.

Erros Comuns

Problema Causa Solução
Prometheus mostra targets como "DOWN" node_exporter não está a correr ou firewall bloqueia porta 9100 Verificar systemctl status node_exporter e abrir a porta 9100 no firewall
Grafana: "Data source is not working" URL do Prometheus incorrecto ou Prometheus inacessível Confirmar que http://IP_DO_PROMETHEUS:9090 responde e que o Grafana consegue chegar ao Prometheus
Dashboard sem dados Datasource não seleccionado ou métricas com nomes diferentes Verificar o datasource do dashboard em Settings → Variables; validar nomes das métricas em http://localhost:9090/api/v1/label/__name__/values
Alertas não disparam Cláusula for: demasiado longa ou expressão PromQL errada Testar a expressão em http://localhost:9090/graph; reduzir for: para 1m temporariamente
Prometheus consome muito disco Retenção sem limite ou demasiados exporters Definir --storage.tsdb.retention.time=15d e --storage.tsdb.retention.size=10GB no ExecStart

Firewall e Segurança

Por defeito, o Prometheus escuta em 0.0.0.0:9090 e o Grafana em 0.0.0.0:3000. Ambos expõem interfaces web sem autenticação forte por defeito (Prometheus não tem autenticação nativa). É essencial proteger estas portas com firewall e, idealmente, colocar um reverse proxy com autenticação à frente.

Abrir apenas as portas necessárias (iptables/nftables ou UFW/firewalld):

# UFW (Debian/Ubuntu) — restringir acesso ao Prometheus e Grafana a uma rede interna
sudo ufw allow from 192.168.1.0/24 to any port 9090 proto tcp
sudo ufw allow from 192.168.1.0/24 to any port 3000 proto tcp
sudo ufw allow from 192.168.1.0/24 to any port 9100 proto tcp

# firewalld (RHEL/Rocky/Alma) — zona interna
sudo firewall-cmd --permanent --zone=internal --add-rich-rule='rule family=ipv4 source=192.168.1.0/24 port port=9090 protocol=tcp accept'
sudo firewall-cmd --permanent --zone=internal --add-rich-rule='rule family=ipv4 source=192.168.1.0/24 port port=3000 protocol=tcp accept'
sudo firewall-cmd --permanent --zone=internal --add-rich-rule='rule family=ipv4 source=192.168.1.0/24 port port=9100 protocol=tcp accept'
sudo firewall-cmd --reload
Atenção: Nunca expor a porta 9090 do Prometheus directamente à Internet sem um reverse proxy com autenticação. Qualquer pessoa com acesso ao Prometheus consegue ver métricas detalhadas do sistema, incluindo nomes de utilizadores, processos e configuração de rede.

Checklist de Verificação

Antes de considerar a stack de monitorização pronta para produção, verificar cada ponto:

  1. Prometheus a correr: systemctl status prometheus mostra active (running).
  2. Targets acessíveis: http://localhost:9090/targets mostra todos os endpoints como UP.
  3. node_exporter exporta métricas: curl -s http://localhost:9100/metrics | grep node_cpu devolve linhas.
  4. Grafana acessível: http://localhost:3000 carrega o login e a password foi alterada.
  5. Datasource configurado: Grafana → Connections → Data sources mostra Prometheus com estado "Connected".
  6. Dashboard importado: Dashboard ID 1860 mostra gráficos com dados (não vazios).
  7. Regras de alerta activas: http://localhost:9090/rules lista as regras sem erros.
  8. Firewall configurado: Portas 9090, 3000 e 9100 só acessíveis a partir de redes internas.
  9. Retenção definida: Prometheus tem --storage.tsdb.retention.time configurado para evitar disco cheio.
  10. Serviços arrancam no boot: systemctl is-enabled prometheus grafana-server node_exporter devolve "enabled" para os três.

Artigos Relacionados