Во время полной ресинхронизации DRBD-раздела Jenkins (1.1 TB) w_await на primary-ноде вырос до 103ms. Builds деградировали, агенты начали таймаутиться. Причина — фиксированный resync-rate без учёта нагрузки приложения. Решение заняло 15 минут.

Контекст

Jenkins работает в active-standby DR: primary-нода держит раздел DRBD в состоянии Primary/UpToDate, secondary — Secondary/UpToDate. Оба узла на OpenStack Ubuntu 22.04, раздел jenkins занимает 1.1 TB из 1.3 TB блочного устройства.

После планового обслуживания secondary-нода вышла из синхронизации. DRBD начал полный resync.

Проблема

Сразу после старта resync iostat на primary показал рабочую нагрузку:

Device  r/s   w/s    wkB/s   w_await  %util
vdb     945  2270   12969     5.71    34.4

Через 10 минут под активной нагрузкой Jenkins:

Device  r/s   w/s    wkB/s   w_await  %util
vdb     980    54    5613   103.00    76.0

w_await 103ms — это очередь на диске. Builds стали зависать, часть агентов ушла в JNLP reconnect loop.

Конфиг resync в момент инцидента:

drbdsetup disk-options jenkins --c-plan-ahead=0 --resync-rate=512000k

c-plan-ahead=0 отключает адаптивный контроллер. DRBD читал с диска ~945 r/s для отправки на secondary и не снижал скорость, даже когда Jenkins активно писал.

Решение

Переключил на adaptive resync прямо на ходу — без остановки Jenkins, без разрыва репликации:

drbdsetup disk-options jenkins \
  --c-plan-ahead=20 \
  --c-fill-target=50k \
  --c-min-rate=50000k \
  --c-max-rate=500000k

Что делает каждый параметр:

c-plan-ahead=20 — горизонт планирования контроллера в единицах 0.1s, то есть 2 секунды. Документация рекомендует ≥ 5x RTT; при ping 0.23ms между нодами значение 20 избыточно, но безопасно.

c-fill-target=50k — сколько данных держать in-flight, в секторах (1 сектор = 512 байт, 50k ≈ 25 MB). Контроллер регулирует скорость чтения так, чтобы очередь не росла.

c-min-rate=50000k — нижняя граница скорости resync. Даже когда Jenkins пишет интенсивно, контроллер не опустит resync ниже ~50 MB/s.

c-max-rate=500000k — верхний предел. Когда диск свободен — resync берёт до ~500 MB/s.

Результат

iostat через 2 минуты после смены параметров:

Device  r/s   w/s    wkB/s   w_await  %util
vdb     870  2269   12965     5.71    34.4   # Jenkins активно пишет
vdb       0     0       0     0.00     0.0   # Jenkins idle
vdb       1     1       4     0.00     0.0   # Jenkins idle

w_await — максимум 5.7ms против 103ms до изменений. Builds перестали зависать.

Скорость resync упала до ~36 MB/s: DRBD отдаёт приоритет Jenkins и берёт остатки. Расчётное время до конца синхронизации — 8.5 часов. Jenkins работал без перебоев всё это время.

Выводы

Фиксированный resync-rate с c-plan-ahead=0 на production-ноде — ошибка конфигурации. Adaptive controller включён в DRBD 9 по умолчанию (c-plan-ahead=20), но явный --c-plan-ahead=0 в drbdsetup disk-options его отключает.

Если меняешь параметры через drbdsetup — проверь, что c-plan-ahead не ноль. Параметры применяются без перезапуска ресурса и без прерывания репликации.

Следующий раз: сначала adaptive, потом смотреть, нужен ли fixed rate.