Перед тем как перейти к дебагу, хочу сразу уточнить одну вещь: в целом FDCServers мне понравился. Это не обзор с призывом избегать провайдера и не попытка оценить качество всей его инфраструктуры. У меня был один VPS, в конкретный период времени, с одной необычно сложной проблемой.
Довольно долго VPS работал нормально и обслуживал реальный production-трафик. Потом что-то изменилось. Обычные запросы начали выполняться абсурдно долго. Страницы сначала открывались медленно, а затем иногда переставали открываться вообще. В другие моменты сервер снова выглядел совершенно здоровым ещё до того, как я успевал нормально исследовать сбой.
В худшем состоянии я зафиксировал:
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+
Nginx работал. Backend работал. VM была онлайн. Но полезная работа почти не выполнялась.
Сбой в production, конечно, раздражал, но сам процесс диагностики был действительно интересным. За такие вещи я и люблю Linux: снаружи машина может выглядеть живой, а несколько независимых интерфейсов ядра постепенно показывают, на каком именно уровне перестала продвигаться полезная работа. Эта статья — о том, как я шёл по этим следам, а не о том, хороший FDCServers провайдер или плохой.
active (running) оказалось почти бессмысленным
Я начал с очевидных проверок:
top
free -h
df -h
systemctl status nginx
В здоровые периоды состояние выглядело примерно так:
D-state processes: 0
CPU iowait: ~0%
disk latency: ~2–4 ms
I/O PSI some: 0.04
I/O PSI full: 0.04
Если бы я подключился только в такой момент, легко можно было решить, что VPS полностью здоров. Затем возвращалась обычная нагрузка, и состояние менялось целиком. Нормальный snapshot системы с периодическим сбоем почти ничего не говорит о её состоянии во время самого сбоя. Нужны были данные, снятые именно в момент проблемы.
Сэмпл iostat, который изменил направление расследования
r_await = 18744 ms
f_await = 53561 ms
aqu-sz = 128.54
util ≈ 100%
read = 88 KB/s
Завершившиеся чтения занимали около 18,7 секунды. Flush-операции — около 53,6 секунды. Средняя очередь превышала 128, а полезный read throughput составлял всего 88 KB/s.
Это не было похоже на диск, который просто занят, потому что эффективно обслуживает тяжёлую нагрузку. Виртуальный block path был практически насыщен, при этом почти ничего не успевал завершать. Высокая utilization сама по себе не означает поломку. Но высокая utilization вместе с огромной latency, длинной очередью, зависшими task'ами, крошечным throughput и падающими запросами — уже совсем другой сигнал.
Я перестал считать iowait диагнозом
blocked processes: 4–9
CPU iowait: 97–100%
CPU idle: 0%
Очень хочется свести это к формулировке «CPU 100% времени ждал диск». Для интуитивного понимания это полезно, но accounting в Linux сложнее, а iowait не является прямым измерением самого диска. Поэтому я воспринимал его как один симптом и искал независимые подтверждения.
PSI показал, что I/O действительно останавливал полезную работу
cat /proc/pressure/io
В один из тяжёлых периодов:
some avg10=99.14
full avg10=95.55
В последующих воспроизведениях full приближался к 98%. Для I/O pressure значение some показывает время, когда хотя бы часть non-idle работы stalled на I/O, а full — время, когда одновременно stalled все non-idle task'и. Значение около 100% говорит гораздо больше, чем просто «диск занят»: workload почти не получает возможности продвигаться вперёд.
D-state заставил перестать обвинять один процесс
ps -eo state,pid,ppid,etime,wchan:50,comm,args | awk 'NR==1 || $1 ~ /^D/'
Один процесс, ненадолго попавший в D-state, ещё не доказывает проблему со storage. Важно было увидеть, какие процессы блокировались одновременно. Я видел jbd2, systemd-journald, worker'ы Nginx, cache-процессы Nginx и другую filesystem-активность.
Если завис только backend — я расследую backend. Если только Nginx — расследую Nginx. Но когда Nginx, системный журнал и EXT4 journal thread одновременно перестают продвигаться, намного интереснее становится их общая зависимость. В моём случае это были filesystem и storage path под ним.
Kernel stacks показали следующий слой
EXT4 journal thread оказывался в путях вроде:
wait_on_buffer
jbd2_log_wait_commit
jbd2_journal_commit_transaction
Worker'ы Nginx находились в обычных путях чтения файлов:
folio_wait_bit_common
filemap_read
generic_file_read_iter
ext4_file_read_iter
vfs_read
pread64
В какой-то момент ядро сообщило:
INFO: task nginx blocked for more than 122 seconds.
systemctl status nginx при этом всё ещё мог показывать active (running). Оба наблюдения были правдой: процесс существовал, но одна из задач Nginx больше двух минут не могла завершить полезную работу. Запущенный процесс и здоровый сервис — не одно и то же.
Самый чистый эксперимент занял около трёх миллисекунд
Запрос через Nginx падал:
HTTP=000
SSL connection timeout
Затем я обошёл Nginx и обратился напрямую к локальному backend:
connect = 0.000423 s
TTFB = 0.003063 s
total = 0.003139 s
Около 3 мс. Конкретный HTTP status для этого теста был неважен. Backend принимал соединение, выполнял запрос и почти мгновенно отдавал ответ. Примерно в то же время worker'ы Nginx были видны внутри EXT4 read path.
application execution → progressing normally
filesystem-backed web path → not progressing normally
Чем глубже я копал, тем менее правдоподобной становилась версия о проблеме на уровне приложения.
Тот же VPS мог развалиться примерно за 30 секунд
Перед одним воспроизведением:
HTTP: 200
D-state: 0
CPU iowait: 3%
r_await: ~1.18 ms
I/O PSI full: ~2.95%
Примерно через полминуты:
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
Позже становилось ещё хуже:
CPU iowait: 96–100%
I/O PSI full: ~98%
HTTPS queue: 512
HTTP: 000
После снятия нагрузки обратный переход мог произойти быстро:
D-state: 0
CPU iowait: 6%
r_await: ~0.98 ms
queue depth: ~0.07
HTTP: 200
Именно поэтому периодические инфраструктурные проблемы так тяжело диагностировать. Через десять минут другой человек может проверить ту же VM и честно увидеть latency меньше миллисекунды. Он не обязательно ошибается — он просто смотрит на другое состояние.
Нулевая latency может оказаться неожиданно бесполезной
Я видел и интервал iostat с r_await = 0, когда система явно была нездорова: высокий iowait, процессы в D-state, незавершённый I/O, почти никаких завершённых чтений и почти нулевой throughput.
Средние, рассчитываемые по завершившимся операциям, становятся менее информативными, когда за окно измерения почти ничего не завершается. Ноль не доказывает, что чтения завершались мгновенно; возможно, просто слишком мало полезных completion'ов, чтобы описать операции, которые продолжают висеть.
После этого инцидента я перестал смотреть на storage-метрики по одной. Мне нужны вместе latency, IOPS, throughput, queue depth, in-flight I/O, D-state, PSI и реальное завершение запросов.
Один инцидент превратился в гораздо более долгое расследование с поддержкой
Первый тяжёлый эпизод совпал с scheduled backup на исходной инфраструктуре, и FDCServers подтвердил, что backup действительно шёл. Это было разумной гипотезой. Но позже я воспроизвёл тот же класс storage stall после завершения backup и вне исходного backup window.
Проблема возвращалась в разные дни. Во время одного инцидента VPS позже был недоступен 4 часа 41 минуту и 15 секунд по моим service logs. Я не могу доказать, что именно storage stall привёл VM в это состояние; для этого понадобилась бы host-side информация, которой у меня не было.
application
↓
Linux VFS
↓
EXT4
↓
virtual block device
↓
?
За этим вопросительным знаком могут находиться virtualization, очереди хоста, storage networking, distributed storage, физические носители, schedulers и другие системы, которых guest не видит. Я видел, на каком уровне проявлялся сбой, но не видел физический root cause.
FDCServers эскалировал проблему внутри компании и в итоге перенёс VPS на другой node. После migration я снова зафиксировал тяжёлый storage stall со стороны guest. Это не доказывает, что у всех node'ов FDCServers были проблемы со storage. Это доказывает только то, что с моей точки зрения проблема моего VPS не была устранена.
Почему я всё равно не считаю это негативной историей про FDCServers
Инфраструктурный инцидент очень легко превратить в приговор всему провайдеру. Я не хочу этого делать.
Для меня есть разница между сервисом, чья нормальная модель работы в принципе несовместима с моим workload, и периодической инфраструктурной проблемой, которую тяжело воспроизвести и долго изолировать. Мой опыт с FDCServers больше был похож на второй случай.
До инцидента VPS нормально работал и обслуживал реальный production-трафик. Поддержка исследовала проблему и пыталась её исправить. В какой-то момент у меня уже было достаточно evidence, чтобы решить: я больше не хочу, чтобы production зависел именно от этого VPS.
Я попросил FDCServers отменить услугу и вернуть деньги. Они вернули деньги. Для моего общего впечатления это важно.
Их нынешнюю инфраструктуру я повторно не тестировал, поэтому не могу сказать, как VPS FDCServers работает сегодня. У меня также нет доказательств, что произошедшее с моим instance было характерно для всей их fleet. Инфраструктура постоянно меняется. Я не превращаю один сложный инцидент на одном VPS в постоянную оценку целого провайдера. И я не рекомендую FDCServers в этой статье — я просто описываю свой опыт.
Больше всего мне понравился сам Linux
Downtime раздражал, но расследование было интересным. Мне действительно нравилось находить границу проблемы.
Для определения физического root cause у меня не было достаточной видимости. Вопрос, на который я хотел ответить, был проще: на каком слое перестаёт завершаться полезная работа?
Backend отвечал примерно за три миллисекунды. Nginx говорил, что он active, а kernel stacks показывали ожидание внутри EXT4 reads. vmstat показывал blocked processes и экстремальный I/O wait. PSI показывал, что I/O stalls съедают почти весь workload. iostat показывал огромную latency и queueing. D-state показывал одновременно ожидающие несвязанные процессы. Ядро даже сообщало о task Nginx, заблокированном более чем на 122 секунды.
Ни одна отдельная метрика не решила проблему. Решило совпадение независимых сигналов. За это я и люблю Linux: можно начать с размытого «сайт иногда не открывается» и постепенно прийти к точному описанию слоя, где перестала продвигаться полезная работа.
Debugging workflow, который я использую теперь
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
Когда возможно, я отдельно проверяю каждый участок request path:
public request
↓
reverse proxy
↓
direct backend
↓
filesystem
↓
block device
Теперь я спрашиваю не просто «почему сервер медленный?», а: на каком слое перестаёт завершаться полезная работа? Такой вопрос приводит к намного более полезным экспериментам.
Последнее правило: соберите evidence до reboot
Reboot может быть именно тем, что нужно production, но он способен стереть самое ценное диагностическое состояние, которое вы вообще увидите.
Before reboot:
D-state: high
I/O PSI: ~97%
iowait: ~100%
queues: large
requests: failing
After reboot:
D-state: 0
latency: milliseconds
requests: healthy
Если availability и влияние на бизнес позволяют, я сначала фиксирую UTC timestamp, PSI, vmstat, iostat, D-state, wchan, сообщения ядра, socket queues и request timings. И только потом восстанавливаю машину.
Сервер работал. Workload — нет.
Я так и не узнал, какой именно host-side компонент в конечном счёте вызвал инцидент. Я не могу утверждать, что сломался конкретный SSD, назвать конкретный storage node или доказать, что происходило за virtual block device.
Но того, что я мог установить изнутри Linux, было достаточно:
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
Этого хватило, чтобы отделить приложение от проблемного слоя и принять эксплуатационное решение. FDCServers вернул деньги за VPS, я переехал, и один тяжёлый инфраструктурный инцидент не стал для меня приговором провайдеру.
Со мной осталось более полезное наблюдение: процесс может быть running, сервис active, VM online, ping может работать — и при этом машина почти не выполняет полезную работу.
Linux даёт достаточно evidence, чтобы увидеть разницу. Нужно только задать системе правильные вопросы, пока сбой ещё существует.