Monitoramento Avançado de Kubernetes com Prometheus

Visão Geral do Prometheus

O Prometheus é um ecossistema de monitoramento e alerta de código aberto, originalmente desenvolvido pelo SoundCloud. Desde 2016, integra a Cloud Native Computing Foundation (CNCF) como o segundo projeto graduado após o Kubernetes. Sua arquitetura é projetada especificamente para ambientes dinâmicos e microsserviços, destacando-se pelos seguintes pilares:

  • Modelo de Dados Multidimensional: Séries temporais identificadas por nomes de métricas e pares chave-valor (labels).
  • Linguagem de Consulta Poderosa (PromQL): Permite realizar agregações e cálculos complexos em tempo real.
  • Coleta via Pull: O servidor busca métricas via HTTP, eliminando a necessidade de agentes pesados.
  • Descoberta de Serviços: Integração nativa com Kubernetes para identificar alvos dinamicamente.
  • Armazenamento Eficiente: Banco de dados de séries temporais (TSDB) otimizado para gravação em disco local.

A arquitetura central consiste no Prometheus Server (coleta e armazenamento), Exporters (transforma métricas de terceiros), Pushgateway (para jobs de curta duração) e o Alertmanager (gestão de notificações).

Implementação no Kubernetes

Para gerenciar o Prometheus em um cluster, utilizamos ConfigMaps para as configurações e Deployments para a execução do binário. Abaixo, definimos o arquivo de configuração básico prometheus.yml encapsulado em um recurso Kubernetes:

apiVersion: v1
kind: ConfigMap
metadata:
  name: prom-core-config
  namespace: monitoring
data:
  prometheus.yml: |
    global:
      scrape_interval: 20s
      evaluation_interval: 20s

    scrape_configs:
      - job_name: 'cluster-monitor'
        static_configs:
          - targets: ['localhost:9090']

Configuração de RBAC

Como o Prometheus precisa consultar a API do Kubernetes para descobrir recursos (Nodes, Pods, Endpoints), é necessário configurar permissões específicas via ClusterRole:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prom-discovery-role
rules:
- apiGroups: [""]
  resources: ["nodes", "nodes/proxy", "services", "endpoints", "pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["extensions", "networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prom-discovery-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prom-discovery-role
subjects:
- kind: ServiceAccount
  name: prom-service-account
  namespace: monitoring

Deployment e Persistência

Ao implantar o Prometheus, um desafio comum é a permissão de escrita no volume de dados. O uso de securityContext resolve conflitos de propriedade de arquivos quando montamos volumes do host:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus-server
  namespace: monitoring
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prom-server
  template:
    metadata:
      labels:
        app: prom-server
    spec:
      serviceAccountName: prom-service-account
      securityContext:
        runAsUser: 0
      containers:
      - name: prom-container
        image: prom/prometheus:v2.35.0
        args:
        - "--config.file=/etc/prometheus/prometheus.yml"
        - "--storage.tsdb.path=/data/prom"
        - "--web.enable-lifecycle"
        ports:
        - containerPort: 9090
          name: api-port
        volumeMounts:
        - name: config-storage
          mountPath: /etc/prometheus
        - name: metrics-storage
          mountPath: /data/prom
      volumes:
      - name: config-storage
        configMap:
          name: prom-core-config
      - name: metrics-storage
        hostPath:
          path: /mnt/prom_data

Monitoramento de Nodes com Node Exporter

Para coletar métricas de hardware (CPU, Memória, Disco) dos nós físicos ou virtuais, utilizamos o node_exporter como um DaemonSet. Isso garante que cada instância do cluster execute um coletor.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-metrics-agent
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - name: exporter
        image: prom/node-exporter:latest
        ports:
        - containerPort: 9100
        volumeMounts:
        - name: proc-fs
          mountPath: /host/proc
          readOnly: true
        - name: sys-fs
          mountPath: /host/sys
          readOnly: true
      volumes:
      - name: proc-fs
        hostPath:
          path: /proc
      - name: sys-fs
        hostPath:
          path: /sys

Descoberta Automática de Nós

Em vez de listar IPs manualmente, configuramos o Prometheus para usar a kubernetes_sd_configs. Através do relabel_configs, mapeamos a porta padrão de monitoramento do Kubelet para a porta do Node Exporter (9100):

- job_name: 'kubernetes-nodes'
  kubernetes_sd_configs:
    - role: node
  relabel_configs:
    - source_labels: [__address__]
      regex: '(.*):10250'
      replacement: '${1}:9100'
      target_label: __address__
    - action: labelmap
      regex: __meta_kubernetes_node_label_(.+)

Monitoramento de Contêineres com cAdvisor

O cAdvisor fornece métricas detalhadas sobre o uso de recursos por contêiner. No Kubernetes, ele já vem integrado ao Kubelet. Para acessar eses dados, configuramos uma tarefa que consulta o proxy da API do nó:

- job_name: 'k8s-container-metrics'
  scheme: https
  tls_config:
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    insecure_skip_verify: true
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  kubernetes_sd_configs:
    - role: node
  relabel_configs:
    - action: labelmap
      regex: __meta_kubernetes_node_label_(.+)
    - target_label: __metrics_path__
      replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
      source_labels: [__meta_kubernetes_node_name]

Análise de Dados com PromQL

O PromQL permite transformar dados brutos em inteligência operacional. Entender os tipos de métricas é fundamental:

  • Counter: Valores que apenas crescem (ex: total de requisições). Usamos rate() para calcular a taxa por segundo.
  • Gauge: Valores que oscilam (ex: uso atual de memória). Usamos delta() para ver variações em um período.
  • Histogram/Summary: Utilizados para latência e distribuição de tamanhos (percentis).

Exemplo: Cálculo de Uso de CPU

Para calcular a porcentagem de uso de CPU de um Pod específico, comparamos a taxa de consumo de tempo de CPU com o limite definido (quota):

(
  sum(rate(container_cpu_usage_seconds_total{image!="",pod!=""}[2m])) by (pod, namespace)
  /
  sum(container_spec_cpu_quota{image!="",pod!=""}/100000) by (pod, namespace)
) * 100

Descoberta Baseada em Annotations

Uma prática comum é permitir que os desenvolvedores exponham métricas apenas adicionando anotações nos Services do Kubernetes. O Prometheus pode ser configurado para "ouvir" essas anotações:

- job_name: 'annotated-services'
  kubernetes_sd_configs:
    - role: endpoints
  relabel_configs:
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
      action: keep
      regex: true
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
      action: replace
      target_label: __metrics_path__
      regex: (.+)
    - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
      action: replace
      target_label: __address__
      regex: ([^:]+)(?::\d+)?;(\d+)
      replacement: $1:$2

Com essa configuração, qualquer Service que possua prometheus.io/scrape: "true" será automaticamente incluído no pipeline de monitoramento, garantindo escalabilidade e autonomia para as equipes de desenvolvimento.

Tags: Prometheus kubernetes monitoring PromQL devops

Publicado em 10-26 22:23