Metrics collection: cAdvisor, node-exporter e kube-state-metrics

1. Introdução à coleta de métricas no Kubernetes

Em ambientes Kubernetes, a observabilidade não é um luxo — é uma necessidade operacional. Sem métricas precisas, times de DevOps operam no escuro, incapazes de identificar gargalos, prever falhas ou dimensionar corretamente suas aplicações. A coleta de métricas no Kubernetes se divide em três camadas fundamentais: métricas no nível de contêiner, métricas no nível de nó e métricas do estado do cluster. Cada uma dessas camadas é atendida por uma ferramenta específica: cAdvisor, node-exporter e kube-state-metrics, respectivamente.

Enquanto métricas de infraestrutura (CPU, memória, disco) revelam a saúde dos recursos físicos e virtuais, métricas de aplicação (latência, throughput, erros) expõem o comportamento do software. A tríade que exploraremos neste artigo cobre o primeiro tipo, fornecendo a base sobre a qual qualquer estratégia de observabilidade deve ser construída.

2. cAdvisor: Métricas no nível de contêiner

O cAdvisor (Container Advisor) é um agente de código aberto desenvolvido pelo Google que coleta, agrega e exporta métricas de contêineres em execução. No Kubernetes, ele é integrado diretamente ao kubelet — cada nó do cluster executa uma instância do cAdvisor como parte do kubelet, expondo métricas no endpoint /metrics/cadvisor.

As métricas fornecidas pelo cAdvisor incluem:

  • CPU: uso por contêiner em cores e percentual
  • Memória: uso atual, limite, RSS e cache
  • Rede: bytes transmitidos/recebidos, pacotes e erros por interface
  • Disco: leitura/escrita por dispositivo e sistema de arquivos

Para consultar as métricas manualmente, você pode usar um pod de depuração:

kubectl run -it --rm debug --image=alpine/curl -- sh
curl http://<node-ip>:10250/metrics/cadvisor -k \
  --header "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"

No contexto do Prometheus, a configuração de scraping para cAdvisor utiliza o service do kubelet:

scrape_configs:
  - job_name: 'cadvisor'
    kubernetes_sd_configs:
      - role: node
    relabel_configs:
      - source_labels: [__meta_kubernetes_node_address_InternalIP]
        target_label: __address__
        replacement: '${1}:10250'
      - source_labels: [__meta_kubernetes_node_name]
        target_label: node
    scheme: https
    tls_config:
      ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
    metrics_path: /metrics/cadvisor

Uma consulta útil no PromQL para identificar contêineres com alto consumo de CPU:

rate(container_cpu_usage_seconds_total[5m]) > 0.8

3. node-exporter: Métricas no nível de nó

Enquanto o cAdvisor foca nos contêineres, o node-exporter coleta métricas do sistema operacional e hardware do nó subjacente. Desenvolvido pela equipe do Prometheus, ele expõe métricas como:

  • CPU: tempo em modo usuário, sistema, idle, iowait, steal
  • Memória: total, livre, buffers, cached, swap
  • Disco: I/O por dispositivo, espaço em disco, inodes
  • Rede: bytes, pacotes, erros, drops por interface
  • Load average: carga do sistema em 1, 5 e 15 minutos

O deploy recomendado é via DaemonSet para garantir um pod em cada nó:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostPID: true
      containers:
      - name: node-exporter
        image: prom/node-exporter:v1.7.0
        args:
          - --path.procfs=/host/proc
          - --path.sysfs=/host/sys
          - --path.rootfs=/host/root
        ports:
          - containerPort: 9100
        volumeMounts:
          - name: proc
            mountPath: /host/proc
            readOnly: true
          - name: sys
            mountPath: /host/sys
            readOnly: true
          - name: root
            mountPath: /host/root
            readOnly: true
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: sys
          hostPath:
            path: /sys
        - name: root
          hostPath:
            path: /

A configuração de scraping no Prometheus:

scrape_configs:
  - job_name: 'node-exporter'
    kubernetes_sd_configs:
      - role: endpoints
    relabel_configs:
      - source_labels: [__meta_kubernetes_namespace]
        regex: monitoring
        action: keep
      - source_labels: [__meta_kubernetes_service_name]
        regex: node-exporter
        action: keep

Para identificar nós com pouco espaço em disco:

node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} < 0.1

4. kube-state-metrics: Métricas do estado do cluster

O kube-state-metrics (KSM) gera métricas a partir do estado atual dos objetos da API do Kubernetes. Diferente do cAdvisor e node-exporter, ele não lê do sistema operacional ou do runtime de contêineres — ele consulta a API do Kubernetes e expõe métricas sobre o estado desejado e atual dos recursos.

Exemplos de métricas fornecidas:

  • kube_deployment_status_replicas: réplicas desejadas, atuais, disponíveis e não disponíveis
  • kube_pod_status_phase: pods em fase Running, Pending, Succeeded, Failed, Unknown
  • kube_node_status_condition: condições dos nós (Ready, DiskPressure, MemoryPressure)
  • kube_namespace_status_phase: namespaces ativos ou em terminação

O deploy do KSM requer permissões RBAC adequadas:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: kube-state-metrics
  namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kube-state-metrics
rules:
  - apiGroups: [""]
    resources: ["pods", "nodes", "namespaces", "persistentvolumes", "persistentvolumeclaims"]
    verbs: ["list", "watch"]
  - apiGroups: ["apps"]
    resources: ["deployments", "statefulsets", "daemonsets", "replicasets"]
    verbs: ["list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kube-state-metrics
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kube-state-metrics
subjects:
  - kind: ServiceAccount
    name: kube-state-metrics
    namespace: monitoring

Uma consulta que revela deployments com réplicas indisponíveis:

kube_deployment_status_replicas_unavailable > 0

5. Integração e pipeline de métricas com Prometheus

Para unificar a coleta, configure ServiceMonitors (se usar Prometheus Operator) ou targets estáticos para cada exporter. Um exemplo de ServiceMonitor para os três componentes:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: kube-state-metrics
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: kube-state-metrics
  endpoints:
  - port: http-metrics
    interval: 30s
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  endpoints:
  - port: http-metrics
    interval: 15s
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: cadvisor
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: cadvisor
  endpoints:
  - port: http-metrics
    interval: 15s
    scheme: https
    tlsConfig:
      caFile: /etc/prometheus/secrets/kubernetes-certs/ca.crt
    bearerTokenFile: /etc/prometheus/secrets/kubernetes-certs/token

Para correlacionar métricas entre os três coletores, utilize joins por labels comuns como node, pod e namespace. Exemplo de consulta que relaciona CPU do contêiner (cAdvisor) com o nó (node-exporter):

rate(container_cpu_usage_seconds_total{namespace="production"}[5m]) 
  * on(node) group_left()
node_load1

6. Boas práticas e otimização

Cardinalidade de métricas: Evite labels com alta cardinalidade como pod em consultas agregadas. Prefira labels como namespace e deployment para agrupamento. No kube-state-metrics, use o argumento --metric-labels-allowlist para controlar quais labels de recursos são expostos.

Intervalos de scraping: Ajuste conforme a criticidade. Para cAdvisor e node-exporter, 15 segundos é adequado. Para kube-state-metrics, 30 segundos é suficiente, pois o estado da API não muda com tanta frequência.

Segurança: Proteja os endpoints de métricas com autenticação e autorização. Para kube-state-metrics, o RBAC deve ser restrito ao mínimo necessário — apenas list e watch nos recursos monitorados. Para cAdvisor, o endpoint requer o token de serviço e TLS.

7. Troubleshooting e casos de uso comuns

Diagnóstico de pods com alto consumo: Use cAdvisor para identificar picos de CPU ou vazamento de memória:

topk(10, rate(container_cpu_usage_seconds_total{namespace="production"}[5m]))

Identificação de nós problemáticos: Node-exporter revela nós com disco cheio ou pressão de memória:

node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes < 0.1

Monitoramento de health de deployments: KSM alerta quando réplicas disponíveis divergem das desejadas:

kube_deployment_status_replicas_available / kube_deployment_spec_replicas < 1

8. Conclusão e próximos passos

A tríade cAdvisor + node-exporter + kube-state-metrics forma a espinha dorsal da observabilidade em Kubernetes. Enquanto o cAdvisor oferece visibilidade no nível de contêiner, o node-exporter expõe a saúde do hardware e sistema operacional, e o kube-state-metrics traduz o estado da API em métricas acionáveis. Juntos, eles permitem que times de DevOps monitorem proativamente seus clusters.

Os próximos passos naturais incluem a integração com tracing distribuído (Jaeger, OpenTelemetry) e agregação de logs (Loki, Elasticsearch). Para visualização, dashboards no Grafana usando as consultas apresentadas neste artigo fornecem uma interface consolidada. Explore o kube-prometheus-stack para uma solução completa que combina todos esses componentes.

Referências