Я не пишу это как негативный отзыв о FDCServers. Я не пытаюсь объяснить другим, стоит или не стоит покупать у них VPS. У меня был один сервер, одна нагрузка и одна конкретная последовательность проблем. Этого недостаточно, чтобы судить о всей хостинговой компании.
Это просто один из моих будней как разработчика. VPS некоторое время нормально работал и уже успел передать больше 3 ТБ трафика. Затем обычная нагрузка начала вызывать огромные задержки. Страницы могли очень долго отвечать или полностью уходить в timeout. Сначала я подозревал привычные вещи: приложение, Nginx, память, сеть, лимиты соединений или просто слишком большую нагрузку. Но метрики Linux указывали в другую сторону.
VPS не был медленным с самого начала
Между инцидентами машина могла выглядеть совершенно здоровой. В один из нормальных периодов процессов в D-state не было, CPU iowait был около 0%, задержка диска составляла примерно 2–4 ms, а I/O PSI был почти нулевым:
D-state processes: 0
CPU iowait: ~0%
disk latency: ~2–4 ms
I/O PSI some: 0.04
I/O PSI full: 0.04Если бы я подключился только в этот момент и посмотрел top, free -h, df -h и systemctl status nginx, то, скорее всего, решил бы, что с VPS всё в порядке. Затем возвращалась обычная нагрузка, и состояние машины резко менялось.
Чтение по 18,7 секунды изменило ход расследования
Один из самых показательных samples iostat выглядел так:
r_await = 18744 ms
f_await = 53561 ms
aqu-sz = 128.54
util = 100.10%
read = 88 KB/sЭти значения важно смотреть вместе. Завершившиеся чтения в среднем занимали около 18,7 секунды. Flush latency составляла около 53,6 секунды. Средняя очередь I/O превышала 128, а полезная скорость чтения при этом была всего 88 KB/s. Это был не просто занятый диск, который быстро гоняет большой объём данных. Storage path тратил огромное количество времени на ожидание завершения операций.
iowait и PSI показали системное I/O pressure
В худшие периоды vmstat показывал 4–9 заблокированных процессов, CPU iowait около 97–100% и CPU idle 0%. iowait не означает, что приложение съедает весь CPU. Он означает, что полезная работа ждёт завершения outstanding I/O.
Linux Pressure Stall Information сделал картину ещё нагляднее:
I/O PSI some avg10 = 99.14
I/O PSI full avg10 = 95.55При последующих воспроизведениях full приближался к 98%. Disk utilization говорит, что устройство занято; PSI показывает, насколько сильно workload реально остановлен из-за этого ресурса. Устойчивое I/O pressure на уровне 95–98% — это не небольшая потеря производительности.
D-state и kernel stacks указали ниже уровня приложения
Затем я посмотрел, какие процессы были заблокированы. Одновременно в D-state оказывались jbd2, systemd-journald, Nginx workers, процессы кеша Nginx и другие операции с filesystem. Если зависает только моё приложение, я разбираю приложение. Когда одновременно блокируются Nginx, системный журнал и EXT4 journal, storage становится самым очевидным общим звеном.
В путях EXT4 journaling были:
wait_on_buffer
jbd2_log_wait_commit
jbd2_journal_commit_transactionNginx workers ждали на обычном чтении файлов:
folio_wait_bit_common
filemap_read
generic_file_read_iter
ext4_file_read_iter
vfs_read
pread64В один момент kernel сообщил, что задача Nginx была заблокирована больше 122 секунд. При этом Nginx всё ещё мог отображаться как active. Но это не означало, что его workers способны завершать полезную работу. running и здоровое состояние — разные вещи.
Ответ backend за 3 ms отделил приложение от filesystem path
Самым чистым сравнением оказался Nginx против локального backend приложения. Запросы через Nginx возвращали HTTP=000 из-за connection или TLS timeout. Прямой запрос к backend завершался примерно за 3 ms:
connect = 0.000423 s
TTFB = 0.003063 s
total = 0.003139 sКонкретный HTTP status для этого теста был неважен. Backend принял соединение, обработал запрос и почти мгновенно сформировал ответ. Одновременно Nginx workers были видны в ожидании EXT4 reads. Это позволило отделить нормальное выполнение приложения от зависимого от filesystem пути перед ним.
Проблема воспроизводилась и могла снова исчезнуть
Перед одним из воспроизведений машина выглядела нормально:
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 checks продолжали падать. Это гораздо полезнее, чем просто сказать, что VPS кажется медленным.
После снятия нагрузки обратный переход мог произойти очень быстро:
D-state: 0
CPU iowait: 6%
r_await: ~0.98 ms
queue depth: ~0.07
HTTP: 200Именно поэтому intermittent storage problems трудно исследовать постфактум. Провайдер может посмотреть сервер уже после восстановления и действительно увидеть нормальную latency. Это всё равно не объясняет, что происходило десять минут назад. Поэтому точные UTC timestamps стали критически важными.
Две метрики, которые могут обмануть: await=0 и свободное место
В некоторые плохие интервалы я видел r_await = 0, хотя iowait был высоким, процессы находились в D-state, запросы оставались in-flight, а чтения почти не завершались. Статистика latency строится по завершённым I/O. Если операция зависла и не закончилась внутри sampling interval, она не может попасть в среднюю latency завершённых операций. Поэтому ноль не всегда означает мгновенный диск.
Я также проверял версию с заполненностью диска. Позже filesystem действительно был заполнен сильнее, чем я обычно допускаю, но тот же класс сбоя уже появлялся, когда root filesystem был занят лишь примерно на 24%. В тот момент было доступно около 1,2 GiB RAM, inode usage составлял около 5%, а сетевой интерфейс не показывал errors или dropped packets. Заполненность диска не могла объяснить весь инцидент.
Что я смог доказать, а что нет
Изнутри VPS я мог наблюдать приложение, Linux VFS, EXT4 и virtual block device. После этого начинается инфраструктура провайдера: virtualization, distributed storage, storage network, физические устройства, scheduling и другие уровни, которых из guest я не вижу.
Поэтому я не могу честно утверждать, что был сломан какой-то конкретный физический SSD, или назвать определённый storage node, network path или virtualization component корневой причиной.
Зато я могу сделать более узкий и хорошо подтверждённый вывод: виртуальный storage path, предоставленный моей Linux VM, многократно входил в состояние, в котором обычные filesystem I/O operations занимали секунды или не завершались за разумное время. Это подтверждалось iostat, PSI, D-state, kernel wait stacks, ожиданиями EXT4/jbd2, ожиданиями Nginx на filesystem, глубиной очереди и request timings. Для нужного мне инженерного диагноза этого было достаточно, для определения физического root cause — нет.
Почему прежние 3+ ТБ трафика не противоречат последующим зависаниям
Сначала именно это меня смущало. Если storage испытывал проблемы, как VPS до этого успешно передал несколько терабайт?
Потому что сетевой трафик и физический disk I/O — разные вещи. Файл можно один раз прочитать из backing storage, оставить в Linux page cache, а затем много раз отдавать из памяти. Поэтому 3 ТБ, переданные по сети, не означают 3 ТБ уникальных физических чтений с диска.
Условия инфраструктуры тоже меняются со временем: состояние cache, нагрузка storage, очереди, host placement и другие workloads могут быть разными. Нормальная работа VPS вчера не гарантирует абсолютно такое же поведение storage сегодня.
В итоге я перестал ждать более глубокий root cause
Я собирал точные timestamps, vmstat, iostat, PSI, snapshots заблокированных процессов, kernel stacks, filesystem waits, глубину очередей и HTTP timings. Отправил диагностику в FDCServers и ждал более глубокого объяснения на уровне инфраструктуры.
Ждал долго. В какой-то момент перестал. Со своей стороны я уже знал достаточно, чтобы принять практическое решение: проблема воспроизводилась, была тяжёлой, проявлялась ниже уровня приложения, а её физическая причина находилась за пределами видимости моего VPS.
Я попросил возврат, и FDCServers вернул деньги
Я отправил FDCServers краткое описание проблем и собранную диагностику, попросил отменить услугу и вернуть деньги. Деньги мне вернули.
Поэтому эта история не заканчивается долгой борьбой за возврат. Я ждал окончательного технического объяснения, решил больше не ждать, отправил имеющиеся доказательства и попросил вернуть оплату. FDCServers её вернул.
Что я изменил после этого
Полезным итогом было не решение, хороший это хостер или плохой. Изменился мой подход к диагностике медленных Linux-серверов.
Я по-прежнему использую 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 paths: внешний запрос, локальный Nginx, прямой backend, filesystem и block-device metrics. Вопрос теперь не просто в том, почему сервер медленный. Вопрос такой: на каком уровне полезная работа перестаёт завершаться?
Когда возможно, я сохраняю доказательства до reboot. Перезагрузка может восстановить сервис, но вместе с этим стереть именно тот D-state, PSI, очереди и latency, благодаря которым intermittent incident вообще можно диагностировать.
Последняя мысль
Я покупал VPS у FDCServers не для того, чтобы получить материал для статьи о хостинге. Мне нужен был сервер с большим объёмом трафика. Какое-то время я именно это и получал: он обслуживал реальную нагрузку и передал больше трёх терабайт.
Затем обычная нагрузка начала воспроизводимо давать iowait до 100%, I/O PSI почти 100%, чтение до 18,7 секунды, flush latency больше 53 секунд, большие очереди, Nginx в ожидании filesystem reads и EXT4/jbd2 в ожидании I/O.
Я так и не узнал, какой физический или host-side компонент был причиной, и не собираюсь делать вид, что знаю. Я определил уровень, на котором проявлялся сбой, собрал достаточно данных, чтобы отделить его от проблемы приложения, перестал ждать более глубокого объяснения root cause и попросил вернуть деньги. FDCServers вернул их.
Это не вердикт обо всех VPS FDCServers. Это один хорошо документированный пример того, что сервис может выглядеть active, процесс — running, а машина при этом почти всё полезное время проводить в ожидании storage.