Rastreando gargalos de armazenamento no Linux com eBPF: além do iostat
Abandone as médias do iostat. Aprenda a usar eBPF, biolatency e biosnoop para visualizar a latência de cauda (p99) e identificar gargalos de disco invisíveis em tempo real.
Você está olhando para o painel do Grafana. O cliente está reclamando de timeouts intermitentes na aplicação. Você abre o terminal, digita iostat -x 1 e vê uma latência média (await) de 2ms. O disco parece estar dormindo. No entanto, os logs da aplicação mostram transações demorando 500ms para commitar no banco de dados.
O que está acontecendo? Você está sendo enganado pela média.
Ferramentas tradicionais como iostat e sar foram projetadas em uma era onde discos giravam a 5400 RPM e latências eram medidas em dezenas de milissegundos. Hoje, com arrays All-Flash e dispositivos NVMe capazes de centenas de milhares de IOPS, olhar para médias de um segundo é como tentar assistir a uma corrida de Fórmula 1 através de uma apresentação de slides: você perde tudo o que acontece entre os quadros.
Para ver o invisível, precisamos parar de contar estatísticas globais e começar a rastrear eventos individuais. É aqui que o eBPF (Extended Berkeley Packet Filter) muda o jogo da observabilidade de armazenamento.
Resumo em 30 segundos
- Médias mentem: O
iostatmostra a média de latência em um intervalo (ex: 1s), escondendo picos de latência (tail latency) que causam timeouts na aplicação.- Custo do contexto: Ferramentas antigas de trace (como
blktrace) podem derrubar a performance de discos NVMe rápidos devido ao overhead de enviar eventos para o espaço do usuário.- Agregação no Kernel: O eBPF permite medir cada I/O individualmente e gerar histogramas dentro do kernel, com custo computacional quase zero, permitindo identificar qual processo (PID) exato está saturando o disco.
O mito da média: por que o iostat ignora sua latência de cauda
O iostat lê dados de /proc/diskstats. O kernel mantém contadores simples: quantos reads, quantos writes, quantos setores e quanto tempo total foi gasto. Quando você roda iostat 1, ele pega o delta desses contadores e divide pelo tempo.
O problema matemático é simples: se você tem 99 requisições que levam 0.1ms (NVMe rápido) e 1 requisição que leva 100ms (um garbage collection do SSD ou contenção de lock), a média será aproximadamente 1ms.
Para o iostat, o disco está voando. Para o usuário que caiu na requisição de 100ms, o sistema travou. Isso é a latência de cauda (tail latency). Em sistemas distribuídos e bancos de dados de alta performance, o P99 (o 99º percentil) importa muito mais que a média.
Figura: Comparativo visual: A ilusão da média estável versus a realidade caótica dos picos de latência revelada por histogramas.
💡 Dica Pro: Se o seu
avgqu-sz(tamanho médio da fila) no iostat estiver alto, mas a latência baixa, você tem paralelismo. Se a latência subir linearmente com a fila, você atingiu o limite físico do dispositivo ou do link SATA/SAS/PCIe.
A falácia do blktrace e o custo do context switch
Antigamente, quando precisávamos de detalhes, usávamos o blktrace. Ele é poderoso, mas funciona enviando eventos de trace do kernel para o userspace para serem processados.
Em um HDD fazendo 150 IOPS, isso é trivial. Em um SSD NVMe Gen4 capaz de 1.000.000 IOPS, o blktrace tenta gerar e transferir um milhão de eventos por segundo. Isso causa uma tempestade de interrupções e trocas de contexto (context switches) que podem consumir 20-30% da CPU apenas para observar o disco.
É o princípio da incerteza de Heisenberg aplicado à infraestrutura: a ferramenta de medição altera o resultado da medição. Você pode causar um incidente tentando diagnosticar um.
Anatomia de um I/O: dissecando a struct bio no kernel
Para entender como o eBPF resolve isso, precisamos descer ao nível do kernel Linux. Todo I/O de bloco no Linux é representado por uma estrutura chamada struct bio.
Quando um banco de dados (como PostgreSQL ou MySQL) pede para ler um bloco, o fluxo simplificado é:
VFS Layer: O sistema de arquivos recebe o pedido.
Block Layer: O pedido é transformado em uma
struct bio.Driver NVMe/SCSI: O bio é enviado para a fila do dispositivo.
Com eBPF, podemos anexar "sondas" (kprobes ou tracepoints) em pontos específicos desse ciclo de vida sem recompilar o kernel e sem parar o sistema.
Os pontos de trace mais críticos para storage são:
block_rq_issue: Quando o pedido é enviado ao driver do disco.block_rq_complete: Quando o disco confirma que terminou.
A diferença de tempo entre esses dois eventos é a latência real do hardware (service time), livre de ruídos de filas do sistema operacional ou agendadores de I/O.
Figura: O caminho do dado: Onde o eBPF intercepta a struct bio para medir a latência real do dispositivo, ignorando a latência do sistema de arquivos.
Observabilidade granular: rastreando latência por PID
A mágica do eBPF é a agregação no kernel. Em vez de enviar 1 milhão de eventos para o userspace, o programa eBPF captura o evento, calcula a latência (delta de tempo), atualiza um mapa de histograma na memória do kernel e descarta o evento. O userspace lê apenas o resumo final a cada poucos segundos. O overhead é insignificante.
Isso nos permite usar ferramentas do pacote BCC (BPF Compiler Collection) ou bpftrace para diagnósticos cirúrgicos.
1. Biolatency: A verdade em histogramas
Em vez de uma média, o biolatency mostra a distribuição de probabilidade da latência.
Tracing block device I/O... Hit Ctrl-C to end.
^C
disk = 'nvme0n1'
usecs : count distribution
0 -> 1 : 0 | |
2 -> 3 : 0 | |
4 -> 7 : 152 | |
8 -> 15 : 4582 |************* |
16 -> 31 : 12400 |****************************************|
32 -> 63 : 6201 |******************** |
64 -> 127 : 98 | |
128 -> 255 : 2 | |
256 -> 511 : 0 | |
512 -> 1023 : 1 | |
1024 -> 2047 : 0 | |
2048 -> 4095 : 0 | |
4096 -> 8191 : 5 | |
Note o detalhe acima: a maioria dos I/Os está entre 16-31 microssegundos (excelente para NVMe). Mas temos 5 operações na faixa de 4-8ms (4096-8191 usecs). O iostat diria que a média é 0.02ms. O biolatency mostra que alguém esperou 8ms.
2. Biosnoop: Isolando o vizinho barulhento
Em um servidor de virtualização (Proxmox, KVM) ou um storage server (TrueNAS Scale), muitas vezes o disco está lento porque um processo específico está abusando. O iostat não mostra PIDs. O iotop mostra throughput, mas não latência.
O biosnoop imprime cada I/O com o PID responsável:
TIME(s) COMM PID DISK T SECTOR BYTES LAT(ms)
0.000000 kworker/u32:1 189 nvme0n1 W 2341234 4096 0.01
0.000451 postgres 4521 nvme0n1 R 9928112 16384 0.02
0.000912 backup-job 9912 nvme0n1 R 123123 1048576 155.00
⚠️ Perigo: O
biosnoopimprime cada evento. Em discos muito rápidos, use-o por poucos segundos e redirecione para um arquivo, ou você será inundado por texto, o que paradoxalmente pode causar lentidão no terminal.
Comparativo: ferramentas de análise de storage
Para situar onde o eBPF brilha, vamos comparar as abordagens.
| Característica | iostat / sar | blktrace | eBPF (biolatency/biosnoop) |
|---|---|---|---|
| Fonte de Dados | /proc/diskstats (Contadores) |
Tracepoints (Raw) | Tracepoints + Mapas BPF |
| Overhead | Muito Baixo | Alto (em NVMe rápido) | Muito Baixo |
| Granularidade | Média do dispositivo | Evento individual | Evento individual ou Histograma |
| Visibilidade | Dispositivo inteiro | Dispositivo + Metadados | Processo (PID), Latência, Flags |
| Segurança em Prod | Segura | Risco de travar CPU | Segura (Sandbox) |
| Caso de Uso | Monitoramento geral | Debug profundo (lab) | Análise de latência em produção |
Dados de alta cardinalidade: o cenário real
Imagine um cenário comum em Home Labs ou Enterprise: Um pool ZFS com 6 discos. A performance de escrita cai drasticamente a cada 10 minutos.
Usando zpool iostat, você vê a banda cair. Usando iostat -x, você vê a utilização dos discos em 100%.
Ao rodar um script eBPF customizado que rastreia zfs_write, você descobre que não é o throughput que está saturando, mas sim a latência de sync de um disco específico que está morrendo silenciosamente. Ele não falhou no SMART, mas está tentando recuperar setores (retries), elevando a latência de gravação de 0.1ms para 200ms.
O ZFS espera o disco mais lento. O eBPF aponta exatamente qual disco (pelo identificador do dispositivo) e qual tipo de operação (flush/sync) está causando o gargalo, algo que métricas agregadas jamais mostrariam com clareza.
Figura: Diagnóstico preciso: O eBPF atua como um scanner de raio-x, identificando qual processo específico está entupindo o fluxo de dados em um ambiente compartilhado.
O fim da adivinhação
A era de adivinhar performance de storage baseada em médias acabou. Discos modernos são rápidos demais e complexos demais para serem resumidos em um único número a cada segundo.
Se você gerencia storage, seja um cluster Ceph de petabytes ou um TrueNAS em casa, a transição para ferramentas baseadas em eBPF não é apenas uma melhoria incremental; é a diferença entre saber que "o sistema está lento" e saber que "o processo de backup está causando latência de 45ms no disco sdb durante operações de flush".
Instale o bcc-tools ou bpftrace na sua distro hoje. Comece a ver o que você estava perdendo.
Referências & Leitura Complementar
Gregg, Brendan. BPF Performance Tools. Addison-Wesley Professional, 2019. (A bíblia do eBPF).
Kernel.org. Linux Block Layer IO accounting. Documentação oficial sobre como o kernel contabiliza estatísticas de disco.
Jens Axboe. fio - Flexible I/O Tester. (Ferramenta essencial para gerar cargas de trabalho controladas para testar sua observabilidade).
NVMe Express. NVM Express Base Specification. (Para entender as filas de comando e latências nativas do protocolo).
Qual é o overhead de usar eBPF em produção comparado ao blktrace?
O eBPF é projetado para ser extremamente leve. Enquanto o blktrace pode causar degradação significativa de performance ao enviar todos os eventos para o userspace (context switching), o eBPF agrega os dados dentro do próprio kernel (in-kernel aggregation), gerando overhead quase imperceptível, ideal para ambientes de produção sensíveis.Preciso recompilar meu kernel para usar ferramentas como biolatency?
Geralmente não. A maioria das distribuições Linux modernas (kernel 4.9+) já vem com suporte a eBPF habilitado (CONFIG_BPF). Você precisará apenas instalar o pacote de ferramentas BCC (BPF Compiler Collection) ou bpftrace disponíveis nos repositórios oficiais da sua distro.Como o eBPF ajuda a identificar problemas em discos NVMe rápidos?
Discos NVMe modernos têm latências na casa dos microssegundos. Ferramentas tradicionais que amostram a cada segundo perdem esses eventos rápidos. O eBPF permite capturar e medir cada operação individual de I/O na granularidade de nanossegundos, permitindo visualizar 'micro-stutters' que passariam despercebidos.
Lucas Ferreira
Engenheiro de Observabilidade
"Transformo o caos de logs, métricas e traces em clareza operacional. Minha missão é eliminar pontos cegos e garantir que nada permaneça invisível na infraestrutura."