Voltar ao blog
31 de agosto de 2026Sergei Solod11 min de leitura

Meu VPS estava online. Então o Linux começou a esperar 18 segundos por leituras do disco

Um caso real de debugging Linux em produção: o VPS permanecia online enquanto o trabalho útil quase parava. A pressão de I/O chegou perto de 100%, as leituras levaram até 18,7 segundos e o Nginx ficou bloqueado no EXT4, embora o backend ainda respondesse em cerca de 3 ms.

LinuxDevOpsVPSDesempenhoDebugging

Antes de entrar no debugging, quero deixar uma coisa clara: minha impressão geral da FDCServers não é negativa. Este texto não é uma avaliação dizendo às pessoas para evitarem o provedor e não é uma tentativa de julgar toda a infraestrutura da empresa. Eu tinha um VPS, durante um período específico, com um problema incomum e bastante difícil.

Durante bastante tempo, o VPS funcionou normalmente e atendeu tráfego real de produção sem problemas. Então alguma coisa mudou. Requests comuns começaram a levar um tempo absurdo. As páginas passaram a abrir devagar e, às vezes, deixavam de abrir completamente. Em outros momentos, a máquina voltava a parecer normal antes que eu conseguisse investigar a falha direito.

No pior momento, registrei:

CPU iowait:       97–100%
I/O PSI full:     ~95–98%
read latency:     up to 18.7 seconds
flush latency:    up to 53.6 seconds
I/O queue depth:  128+

O Nginx estava rodando. O backend estava rodando. A VM estava online. E, ainda assim, quase nenhum trabalho útil avançava.

A falha em produção foi frustrante, mas o debugging em si foi genuinamente interessante. É exatamente esse tipo de problema que me faz gostar do Linux: uma máquina pode parecer viva por fora enquanto várias interfaces independentes do kernel mostram onde o progresso útil realmente parou. Este artigo é sobre seguir essas pistas, não sobre decidir se a FDCServers é um provedor bom ou ruim.

active (running) acabou significando muito pouco

Comecei pelas verificações óbvias:

top
free -h
df -h
systemctl status nginx

Em períodos saudáveis, eu via aproximadamente:

D-state processes: 0
CPU iowait:        ~0%
disk latency:      ~2–4 ms
I/O PSI some:      0.04
I/O PSI full:      0.04

Se eu tivesse conectado apenas nesses momentos, teria concluído facilmente que o VPS estava saudável. Depois o tráfego normal voltava e o estado podia mudar completamente. Um snapshot saudável de um sistema com falha intermitente diz muito pouco sobre seu estado durante a falha. Eu precisava coletar evidências enquanto o problema estava acontecendo.

A amostra de iostat que mudou a investigação

r_await = 18744 ms
f_await = 53561 ms
aqu-sz  = 128.54
util    ≈ 100%
read    = 88 KB/s

As leituras concluídas levavam cerca de 18,7 segundos. As operações de flush chegavam a 53,6 segundos. A fila média passava de 128, enquanto o throughput útil de leitura era de apenas 88 KB/s.

Isso não parecia storage simplesmente ocupado por estar atendendo eficientemente um workload exigente. O caminho de bloco virtual estava praticamente saturado e concluía muito pouco trabalho. Utilização alta sozinha não é falha; mas utilização alta junto de latência enorme, fila longa, tasks bloqueadas, throughput mínimo e requests falhando é um sinal completamente diferente.

Parei de tratar iowait como diagnóstico

blocked processes: 4–9
CPU iowait:        97–100%
CPU idle:          0%

É tentador resumir isso dizendo que a CPU passava 100% do tempo esperando pelo disco. Como intuição, ajuda, mas o accounting do Linux é mais complexo e iowait não mede diretamente o disco. Por isso usei esse valor como um sintoma e procurei evidências independentes.

PSI mostrou que o I/O estava parando o trabalho útil

cat /proc/pressure/io

Durante um período severo:

some avg10=99.14
full avg10=95.55

Em reproduções posteriores, full chegou perto de 98%. Em I/O pressure, some representa o tempo em que pelo menos parte do trabalho non-idle está bloqueada por I/O, enquanto full representa o tempo em que todas as tasks non-idle estão bloqueadas por I/O simultaneamente. Perto de 100%, não estamos falando apenas de um disco ocupado: o workload quase não encontra oportunidade para avançar.

D-state me fez parar de culpar um único processo

ps -eo state,pid,ppid,etime,wchan:50,comm,args | awk 'NR==1 || $1 ~ /^D/'

Ver um processo por pouco tempo em D-state não comprova problema de storage. O importante era quais processos ficavam bloqueados juntos. Observei componentes sem relação direta, incluindo jbd2, systemd-journald, workers do Nginx, processos de cache do Nginx e outras atividades do filesystem.

Se só o backend trava, investigo o backend. Se só o Nginx trava, investigo o Nginx. Mas, quando Nginx, system journal e journal thread do EXT4 deixam de avançar ao mesmo tempo, a dependência compartilhada se torna muito mais interessante. Neste caso, era o filesystem e o caminho de storage abaixo dele.

Os kernel stacks mostraram a próxima camada

O journal thread do EXT4 aparecia em caminhos como:

wait_on_buffer
jbd2_log_wait_commit
jbd2_journal_commit_transaction

Os workers do Nginx apareciam em caminhos comuns de leitura do filesystem:

folio_wait_bit_common
filemap_read
generic_file_read_iter
ext4_file_read_iter
vfs_read
pread64

Em um momento, o kernel relatou:

INFO: task nginx blocked for more than 122 seconds.

systemctl status nginx ainda podia mostrar active (running). As duas observações eram verdadeiras: o processo existia, mas uma task do Nginx ficou por mais de dois minutos sem conseguir concluir trabalho útil. Processo em execução não é a mesma coisa que serviço saudável.

Meu experimento mais limpo levou cerca de três milissegundos

Uma request via Nginx falhou:

HTTP=000
SSL connection timeout

Depois ignorei o Nginx e acessei diretamente o backend local:

connect = 0.000423 s
TTFB    = 0.003063 s
total   = 0.003139 s

Cerca de 3 ms. O status HTTP exato não era importante nesse teste. O backend aceitava a conexão, executava a request e retornava a resposta quase imediatamente. Ao mesmo tempo, os workers do Nginx apareciam dentro de caminhos de leitura do EXT4.

application execution       → progressing normally
filesystem-backed web path  → not progressing normally

Quanto mais eu investigava, menos plausível parecia uma explicação no nível da aplicação.

O mesmo VPS podia colapsar em cerca de 30 segundos

Antes de uma reprodução:

HTTP:          200
D-state:       0
CPU iowait:    3%
r_await:       ~1.18 ms
I/O PSI full:  ~2.95%

Cerca de meio minuto depois:

D-state:       4
CPU iowait:    91%
CPU idle:      0%
I/O PSI some:  86.11%
I/O PSI full:  78.02%
r_await:       236.50 ms
HTTP:          000

Depois piorava ainda mais:

CPU iowait:    96–100%
I/O PSI full:  ~98%
HTTPS queue:   512
HTTP:          000

Ao remover o workload, a transição oposta podia acontecer rapidamente:

D-state:      0
CPU iowait:   6%
r_await:      ~0.98 ms
queue depth:  ~0.07
HTTP:         200

É por isso que falhas intermitentes de infraestrutura são tão difíceis. Dez minutos depois alguém pode medir honestamente latência abaixo de um milissegundo na mesma VM. Essa pessoa não precisa estar errada; está apenas observando outro estado.

Latency zero pode ser surpreendentemente pouco útil

Também vi um intervalo de iostat com r_await = 0 enquanto o sistema estava claramente ruim: iowait alto, processos em D-state, I/O pendente, quase nenhuma leitura concluída e throughput quase zero.

Médias baseadas em operações concluídas ficam menos informativas quando quase nada termina durante a janela de amostragem. Zero não prova necessariamente que as leituras terminaram instantaneamente; pode simplesmente haver poucas conclusões úteis para representar as operações que continuam travadas.

Desde esse incidente passei a observar juntos latency, IOPS, throughput, queue depth, in-flight I/O, D-state, PSI e conclusão real das requests.

Um incident virou uma investigação de suporte muito mais longa

O primeiro evento grave coincidiu com um backup agendado na infraestrutura original e a FDCServers confirmou que ele estava rodando. Era uma explicação candidata razoável. Mas depois reproduzi o mesmo tipo de storage stall após o fim do backup e fora da janela original.

O problema voltou em vários dias. Durante um incidente, o VPS depois ficou indisponível por 4 horas, 41 minutos e 15 segundos segundo meus service logs. Não posso provar que o storage stall causou aquele estado da VM; isso exigiria informações host-side que eu não tinha.

application
    ↓
Linux VFS
    ↓
EXT4
    ↓
virtual block device
    ↓
?

Depois desse ponto de interrogação podem existir virtualização, host queues, storage networking, distributed storage, mídia física, schedulers e outros sistemas invisíveis para o guest. Eu conseguia ver onde a falha se manifestava, mas não a causa física final.

A FDCServers escalou o problema internamente e depois migrou o VPS para outro node. Após a migração registrei outro storage stall severo pelo guest. Isso não prova que todos os nodes da FDCServers tinham problema de storage. Prova apenas que, do meu ponto de vista, o problema que afetava meu VPS não havia sido eliminado.

Por que ainda não considero isso uma história negativa sobre a FDCServers

É fácil transformar um incidente de infraestrutura em um veredito sobre um provedor inteiro. Não quero fazer isso.

Eu diferencio um serviço cujo modelo operacional normal é fundamentalmente incompatível com meu workload de um problema de infraestrutura intermitente, difícil de reproduzir e demorado de isolar. Minha experiência com a FDCServers pareceu o segundo caso.

Antes do incident, o VPS havia funcionado normalmente e atendido tráfego real de produção. O suporte investigou e tentou resolver o problema. No fim eu já tinha evidências suficientes para decidir que não queria mais depender daquele VPS específico em produção.

Pedi o cancelamento e o reembolso. A FDCServers me devolveu o dinheiro. Isso importa na minha impressão geral.

Não testei novamente a infraestrutura atual deles, então não posso dizer como um VPS da FDCServers funciona hoje. Também não tenho evidências de que o que ocorreu na minha instância representasse toda a plataforma. Infraestrutura muda o tempo todo. Eu não transformaria um incident difícil em um VPS em uma conclusão permanente sobre o provedor. E também não estou recomendando a FDCServers aqui; estou apenas descrevendo o que aconteceu comigo.

A parte que mais gostei foi o próprio Linux

O downtime foi frustrante, mas a investigação foi divertida. Eu realmente gostei de encontrar o limite do problema.

Não tinha visibilidade suficiente para identificar a causa física final. A pergunta que eu queria responder era mais simples: em qual camada o trabalho útil para de ser concluído?

O backend respondia em cerca de três milissegundos. O Nginx aparecia como ativo, enquanto kernel stacks mostravam que ele esperava dentro de leituras EXT4. vmstat mostrava processos bloqueados e I/O wait extremo. PSI mostrava que os stalls de I/O consumiam quase todo o workload. iostat mostrava latência enorme e queueing. D-state mostrava processos sem relação esperando juntos. O kernel chegou a relatar uma task do Nginx bloqueada por mais de 122 segundos.

Nenhuma métrica isolada resolveu o incident. A concordância entre elas resolveu. Esse é um dos motivos pelos quais gosto de Linux: você pode começar com algo vago como “meu site às vezes não abre” e gradualmente chegar a uma descrição precisa da camada onde o trabalho útil deixa de avançar.

O workflow de debugging que uso agora

top
free -h
df -h

date -u
uptime
cat /proc/pressure/io
cat /proc/pressure/memory
cat /proc/pressure/cpu
vmstat 1 10
iostat -x 1 10
ps -eo state,pid,ppid,etime,wchan:50,comm,args | awk 'NR==1 || $1 ~ /^D/'
ss -lntp
journalctl -k --since "30 min ago" --no-pager

Quando possível, também testo cada parte do caminho da request separadamente:

public request
      ↓
reverse proxy
      ↓
direct backend
      ↓
filesystem
      ↓
block device

Já não pergunto apenas por que o servidor está lento. Pergunto: em qual camada o trabalho útil para de ser concluído? Essa pergunta produz experimentos muito melhores.

Uma última regra: colete evidências antes do reboot

Um reboot pode ser exatamente o que produção precisa, mas também pode apagar o estado de diagnóstico mais valioso que você verá.

Before reboot:
D-state:     high
I/O PSI:     ~97%
iowait:      ~100%
queues:      large
requests:    failing

After reboot:
D-state:     0
latency:     milliseconds
requests:    healthy

Quando disponibilidade e impacto de negócio permitem, primeiro capturo UTC timestamp, PSI, vmstat, iostat, D-state, wchan, mensagens do kernel, socket queues e request timings. Depois recupero a máquina.

O servidor estava rodando. O workload não.

Nunca descobri qual componente host-side causou finalmente o incident. Não posso afirmar que um SSD específico falhou, apontar um storage node concreto ou provar o que aconteceu atrás do virtual block device.

O que consegui estabelecer a partir do Linux foi suficiente:

read latency:       up to 18.7 s
flush latency:      up to 53.6 s
I/O PSI full:       almost 100%
iowait:             almost 100%
I/O queue:          128+
Nginx:              blocked in filesystem reads
EXT4/jbd2:          blocked waiting for I/O
direct backend:     ~3 ms
HTTP through Nginx: timing out

Foi suficiente para separar minha aplicação da camada que estava falhando e tomar uma decisão operacional. A FDCServers reembolsou o VPS, eu segui em frente e não transformo um incident de infraestrutura difícil em um veredito sobre o provedor.

O que ficou comigo é mais útil: um processo pode estar running, um serviço active, uma VM online e o ping pode funcionar, enquanto a máquina praticamente não conclui trabalho útil.

Linux fornece evidências suficientes para perceber a diferença. Basta fazer as perguntas certas enquanto a falha ainda está presente.