Деградация SSD в серверных RAID-массивах: диагностика и решение

Исходная ситуация

Хостинг-провайдер «ВебХост» обратился к нам с нетипичной жалобой: на 40 серверах с SSD-дисками в RAID-10 производительность записи деградировала на 70-80% спустя 3-4 месяца эксплуатации. Серверы обслуживали клиентские сайты на WordPress и Bitrix, и при высокой нагрузке пользователи жаловались на таймауты.

Первичная диагностика показала следующую картину:

  • Конфигурация: Intel S4510 480GB x4 в RAID-10 через LSI MegaRAID 9361-8i
  • Заполнение дисков: 85-92% на большинстве серверов
  • Скорость записи: упала с 450 MB/s до 90-120 MB/s (случайная запись 4K — с 68K IOPS до 7K IOPS)
  • Латентность: p99 записи выросла с 0.3 мс до 12 мс, периодические всплески до 45 мс

Аппаратный RAID-контроллер LSI не поддерживал проброс команды TRIM на SSD — и это оказалось корнем проблемы.

Как NAND-память теряет скорость без TRIM

Чтобы понять проблему, нужно разобраться в устройстве SSD. NAND-память работает с двумя единицами хранения: страница (4-16 КБ) и блок (128-512 страниц, то есть 512 КБ — 8 МБ). Ключевое ограничение: записать данные можно только в чистую страницу, а очистить страницы можно только целым блоком.

Когда файловая система удаляет файл, она просто помечает сектора как свободные в своей таблице. Но контроллер SSD об этом не знает — для него эти секторы всё ещё заняты. Команда TRIM сообщает контроллеру, какие логические блоки больше не нужны, и он может заранее очистить соответствующие физические блоки.

Без TRIM возникает цепная реакция деградации:

  1. Сборщик мусора (GC) вынужден работать в реальном времени при каждой записи
  2. Read-Modify-Write: чтобы записать 4 КБ, контроллер читает весь блок (2-4 МБ), модифицирует, стирает блок, записывает обратно
  3. Write Amplification (WA) вырастает до 5-10x — на 1 логическую запись приходится 5-10 физических
  4. Стирание блока занимает 3000 мкс против 900 мкс на запись в чистую страницу — задержка утраивается

Flash Translation Layer (FTL) поддерживает карту соответствия логических и физических адресов, и по мере заполнения диска эта карта становится всё более фрагментированной.

Почему TRIM не работает через аппаратный RAID

Мы проверили поддержку TRIM на одном из серверов:

# Проверяем, поддерживает ли блочное устройство discard
lsblk -D /dev/sda
NAME  DISC-ALN DISC-GRAN DISC-MAX
sda          0        0B       0B
sda1         0        0B       0B
sda2         0        0B       0B

Нули в колонках DISC-GRAN и DISC-MAX означают, что TRIM не поддерживается на уровне блочного устройства. Причина — аппаратный RAID-контроллер LSI MegaRAID не пробрасывает команду TRIM на физические диски.

TRIM не работает в следующих сценариях:

  • Аппаратные RAID-контроллеры (LSI/Broadcom, Adaptec) — не поддерживают TRIM в RAID 0/1/5/6/10
  • Firmware RAID (Intel RST) — TRIM работает только в RAID 0 и RAID 1, но не в RAID 5/6
  • USB/SATA-мосты — протокол USB Mass Storage не передаёт TRIM
  • Полнодисковое шифрование (dm-crypt без опции --allow-discards) — блокирует TRIM по умолчанию

Для серверов с NVMe-дисками ситуация проще: Linux MD RAID (mdadm) поддерживает проброс TRIM/UNMAP для NVMe. Но у «ВебХоста» стояли SATA SSD за аппаратным контроллером.

Решение: Over-Provisioning + миграция на mdadm

Мы реализовали двухэтапное решение. Первый этап — немедленное облегчение через over-provisioning, второй — долгосрочная миграция на программный RAID.

Этап 1: Over-Provisioning через неразмеченное пространство

Идея: оставить 20-30% ёмкости SSD неразмеченным, чтобы контроллер использовал эти блоки для внутренней сборки мусора.

# 1. Бэкап данных сервера
rsync -avzP /srv/data/ backup-server:/backup/webhost-node15/

# 2. Secure Erase для полного сброса SSD
# (выполняется через RAID-контроллер или напрямую при загрузке с LiveUSB)
hdparm --user-master u --security-set-pass PasS /dev/sda
hdparm --user-master u --security-erase PasSs /dev/sda

# 3. Пересоздаём разделы, оставляя 25% неразмеченными
# Для диска 480GB (447 GiB) размечаем только 335 GiB
parted /dev/sda mklabel gpt
parted /dev/sda mkpart primary ext4 1MiB 335GiB

# 4. Пересоздаём RAID и восстанавливаем данные

Этап 2: Миграция на mdadm с поддержкой TRIM

На новых серверах мы перешли с аппаратного RAID на программный Linux MD RAID:

# Создаём RAID-10 с поддержкой TRIM (--assume-clean для SSD)
mdadm --create /dev/md0 --level=10 --raid-devices=4 \
  --assume-clean \
  /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1

# Включаем проброс TRIM в mdadm
echo 'ARRAY /dev/md0 metadata=1.2 name=webhost:0' >> /etc/mdadm/mdadm.conf

# Монтируем с поддержкой discard
# /etc/fstab:
/dev/md0  /srv  ext4  defaults,noatime,discard  0 2

# Проверяем, что TRIM проходит через RAID
lsblk -D /dev/md0
# DISC-GRAN  DISC-MAX
# 512B       2G         <-- значения > 0 = TRIM работает

Настройка fstrim и I/O Scheduler

Постоянный discard (опция discard в fstab) добавляет задержку при каждом удалении файла. Для серверов с высокой нагрузкой мы предпочитаем периодический TRIM через fstrim:

# Убираем discard из fstab, вместо этого настраиваем systemd timer
# /etc/fstab:
/dev/md0  /srv  ext4  defaults,noatime  0 2

# Включаем встроенный fstrim.timer
systemctl enable fstrim.timer
systemctl start fstrim.timer

# По умолчанию запускается раз в неделю. Для нагруженных серверов
# меняем на ежедневный запуск:
mkdir -p /etc/systemd/system/fstrim.timer.d
cat > /etc/systemd/system/fstrim.timer.d/override.conf << 'EOF'
[Timer]
OnCalendar=
OnCalendar=daily
RandomizedDelaySec=6h
EOF

systemctl daemon-reload

# Ручной запуск fstrim с отчётом
fstrim -v /srv
# /srv: 84.2 GiB (90441424896 bytes) trimmed

I/O Scheduler для SSD:

На серверах с SSD дисковый планировщик CFQ (по умолчанию в старых ядрах) добавляет ненужную латентность. Для SSD оптимальны:

  • none (noop) — для NVMe, где контроллер сам управляет очередью
  • mq-deadline — для SATA SSD, обеспечивает предсказуемую латентность
# Проверяем текущий планировщик
cat /sys/block/sda/queue/scheduler
# [mq-deadline] kyber bfq none

# Устанавливаем mq-deadline для SATA SSD
echo mq-deadline > /sys/block/sda/queue/scheduler

# Для NVMe — none
echo none > /sys/block/nvme0n1/queue/scheduler

# Постоянная настройка через udev-правило
cat > /etc/udev/rules.d/60-ssd-scheduler.rules << 'EOF'
# SATA SSD → mq-deadline
ACTION=="add|change", KERNEL=="sd[a-z]*", ATTR{queue/rotational}=="0", \
  ATTR{queue/scheduler}="mq-deadline"
# NVMe → none
ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/scheduler}="none"
EOF

udevadm control --reload-rules

Бенчмаркинг и мониторинг

Для объективной оценки производительности мы использовали fio — стандартный инструмент бенчмаркинга дисковой подсистемы:

# Тест случайной записи 4K (типичная нагрузка MySQL/PostgreSQL)
fio --name=rand-write --ioengine=libaio --direct=1 \
  --rw=randwrite --bs=4k --size=4G --numjobs=4 \
  --runtime=300 --time_based --group_reporting \
  --filename=/srv/fio-test

# Результаты ДО оптимизации:
# write: IOPS=6845, BW=26.7MiB/s
# lat (usec): avg=2312, p99=11840

# Результаты ПОСЛЕ (over-provisioning + fstrim + mq-deadline):
# write: IOPS=62450, BW=244MiB/s
# lat (usec): avg=253, p99=680

# Смешанный тест (70% чтение / 30% запись — типичный веб-сервер)
fio --name=mixed --ioengine=libaio --direct=1 \
  --rw=randrw --rwmixread=70 --bs=4k --size=4G \
  --numjobs=8 --runtime=300 --time_based \
  --group_reporting --filename=/srv/fio-test

Мониторинг здоровья SSD через smartctl:

# Установка smartmontools
apt install smartmontools

# Проверяем ключевые SMART-атрибуты SSD
smartctl -A /dev/sda | grep -E '(Wear_Leveling|Media_Wearout|Total_LBAs_Written|Reallocated)'

# Ключевые метрики для мониторинга:
# Media_Wearout_Indicator — оставшийся ресурс (100 = новый, 0 = исчерпан)
# Total_LBAs_Written — общий объём записи (для расчёта DWPD)
# Reallocated_Sector_Ct — количество переназначенных секторов (> 0 = проблема)

# Скрипт для Prometheus node_exporter (textfile collector)
cat > /opt/scripts/ssd_health.sh << 'SCRIPT'
#!/bin/bash
for disk in /dev/sd[a-z]; do
  name=$(basename $disk)
  wear=$(smartctl -A $disk | awk '/Media_Wearout|Wear_Leveling/ {print $4}')
  written=$(smartctl -A $disk | awk '/Total_LBAs_Written/ {print $10}')
  realloc=$(smartctl -A $disk | awk '/Reallocated_Sector/ {print $10}')
  echo "ssd_wear_indicator{disk=\"$name\"} ${wear:-0}"
  echo "ssd_total_written_lba{disk=\"$name\"} ${written:-0}"
  echo "ssd_reallocated_sectors{disk=\"$name\"} ${realloc:-0}"
done > /var/lib/prometheus/node-exporter/ssd.prom
SCRIPT
chmod +x /opt/scripts/ssd_health.sh

# Добавляем в cron — каждые 5 минут
echo '*/5 * * * * root /opt/scripts/ssd_health.sh' > /etc/cron.d/ssd-health

NVMe vs SATA SSD: когда стоит мигрировать

В процессе работы с «ВебХостом» мы провели сравнение SATA и NVMe SSD для серверных задач:

ПараметрSATA SSD (Intel S4510)NVMe SSD (Intel P4510)
ИнтерфейсSATA III (6 Gbps)PCIe 3.0 x4 (32 Gbps)
Последовательное чтение560 MB/s3200 MB/s
Последовательная запись510 MB/s2000 MB/s
Случайное чтение 4K97K IOPS637K IOPS
Случайная запись 4K36K IOPS163K IOPS
Латентность чтения78 мкс15 мкс
TRIM через mdadmДаДа (нативно)
Цена за 1 TB~15 000 руб.~28 000 руб.

Мы рекомендовали «ВебХосту» поэтапную миграцию на NVMe для серверов с базами данных (MySQL, PostgreSQL), где случайный I/O критичен. Для файловых хранилищ и серверов со статикой SATA SSD с правильным over-provisioning и TRIM работают достаточно.

Результаты и рекомендации

За две недели мы обработали все 40 серверов «ВебХоста». Итоговые результаты:

МетрикаДоПосле
Случайная запись 4K (IOPS)6 80062 400
Латентность записи p9912 мс0.68 мс
TTFB сайтов (средний)1.8 сек0.3 сек
Жалобы клиентов на скорость~40/месяц2/месяц
Write Amplification8-10x1.2-1.5x

Рекомендации для серверов с SSD в RAID:

  • Программный RAID (mdadm) вместо аппаратного — поддержка TRIM, проще управление, современные CPU справляются без контроллера
  • Over-provisioning 20-25% — оставляйте неразмеченное пространство, особенно при аппаратном RAID
  • fstrim.timer вместо discard в fstab — меньше влияние на производительность при удалении файлов
  • I/O scheduler — mq-deadline для SATA SSD, none для NVMe
  • Мониторинг SMART — алерт при Media_Wearout_Indicator < 20% и Reallocated_Sector_Ct > 0
  • Не заполнять выше 75% — оставляйте запас для GC и TRIM

Если вашему хостингу или серверной инфраструктуре нужна оптимизация дисковой подсистемы — напишите нам в ITFresh, мы разберёмся с проблемой и настроим всё под ключ.

Часто задаваемые вопросы

Выполните команду lsblk -D и проверьте колонки DISC-GRAN и DISC-MAX. Если обе показывают 0B — TRIM не поддерживается на уровне блочного устройства. Для дополнительной проверки используйте fstrim -v /mount-point — если команда завершится ошибкой, TRIM недоступен.
Для SSD — нет. Аппаратные контроллеры не пробрасывают TRIM, имеют собственный кэш с батарейкой (BBU), который избыточен для SSD, и стоят $300-800. Программный mdadm на современных CPU работает не медленнее, поддерживает TRIM и проще в управлении. Исключение — серверы с 24+ дисками HDD, где аппаратный контроллер оправдан.
Для серверных SSD без TRIM — минимум 20-25% от ёмкости. Промышленные серверные SSD (Intel D-серия, Samsung PM-серия) уже имеют 7-28% встроенного OP. Если TRIM работает через mdadm, достаточно не заполнять файловую систему выше 75-80%.
Для серверов с умеренной записью (веб-хостинг, файловый сервер) достаточно раз в день. Для серверов с интенсивной записью (базы данных, логирование) — каждые 6-12 часов. Запуск fstrim создаёт кратковременную нагрузку, поэтому рекомендуется планировать его на часы минимальной активности.
Частично — да. Удалите ненужные файлы, чтобы заполнение было ниже 75%, и выполните fstrim. Но если SSD за аппаратным RAID без поддержки TRIM, единственный путь — Secure Erase и переразметка с over-provisioning, либо миграция на mdadm.

Нужна помощь с проектом?

Специалисты АйТи Фреш помогут с архитектурой, DevOps, безопасностью и разработкой — 15+ лет опыта

📞 Связаться с нами
#ssd#raid#trim#over-provisioning#write amplification#nand#fstrim#fio
Комментарии 0

Оставить комментарий

загрузка...