Обзор
Когда у хоста или cgroup памяти заканчивается память, OOM-killer в Linux
завершает процесс с помощью SIGKILL — обычно самого крупного потребителя,
которым на выделенном хосте является сам clickhouse-server. В результате
вместо шанса на восстановление сервер целиком выходит из строя.
OOM-канарейка меняет то, кто погибает первым. Она запускает небольшой жертвенный дочерний процесс, который делает себя наиболее привлекательной целью для OOM, чтобы ядро убило его, а не сервер. Затем сервер обнаруживает его завершение, подтверждает, что причиной был OOM, и сбрасывает давление на память, чтобы выжить.
Канарейка не увеличивает никакой лимит памяти и не заменяет корректно настроенные
ограничения (см. Оверкоммит памяти и
max_server_memory_usage). Это последний рубеж защиты: за небольшой,
фиксированный объём памяти она даёт шанс пережить резкий всплеск потребления памяти.
Как это работает
Канарейка — это отдельный процесс clickhouse oom-canary. Он устанавливает для себя
oom_score_adj на максимум (1000), чтобы ядро выбрало его первой целью, затем
выделяет oom_canary_size байт (по умолчанию 100 МБ), обращается к этой памяти и вызывает mlock,
чтобы его резидентный объём памяти был реальным. Этот процесс автоматически завершается, если сервер останавливается.
На сервере поток мониторинга следит за канарейкой (через pidfd) и реагирует, когда
она завершается:
- Завершена сигналом
SIGKILLпри наличии признаков OOM в cgroup → выполнить реакцию на OOM, затем заново запустить новую канарейку. - Завершена без признаков OOM (например, при ручном
kill -9) или завершилась из-за временного сбоя → только перезапуск, без реакции. - Постоянная ошибка инициализации или остановка сервера → канарейка отключается сама.
Признаки OOM берутся только из счётчика oom_kill в memory.events.local cgroup v2.
Это намеренно ограничено текущей cgroup: иерархические или общесистемные счётчики могут
увеличиваться из-за несвязанных процессов и вызывать ложные срабатывания.
При подтверждённом OOM реакция выполняет следующие независимые шаги: записывает сообщение FATAL
в журнал, очищает арены аллокатора (jemalloc), по возможности отменяет все выполняющиеся
запросы, отменяет все слияния и мутации и ставит событие в очередь
system.crash_log. Системные журналы не
сбрасываются на диск синхронно, потому что принудительный I/O при нехватке памяти может только ухудшить ситуацию.
Требования
- Linux ≥ 5.3. Монитор управляет канарейкой через
pidfd_open; на более старых ядрах канарейка отключается при запуске. На платформах, отличных от Linux, это не даёт никакого эффекта. - cgroup v2 с
memory.events.localдля реакции на OOM. Без этого канарейка всё равно перезапускается послеSIGKILL, но не может подтвердить OOM, поэтому реакция не запускается (при запуске в журнал записывается предупреждение). - Привилегия
mlock(необязательно). Чтобы заблокировать память канарейки, требуетсяCAP_IPC_LOCKили достаточныйRLIMIT_MEMLOCK; если это не удаётся, канарейка записывает предупреждение, а её память может быть выгружена в swap, что снижает её эффективность как цели OOM.
Конфигурация
Работа канарейки управляется настройками сервера, которые задаются как элементы верхнего уровня конфигурации сервера и применяются после перезапуска.
| Setting | Default | Description |
|---|---|---|
oom_canary_enable |
false |
Включить OOM-канарейку. |
oom_canary_size |
104857600 (100 MB) |
Количество байтов, которое канарейка выделяет и использует. Чем больше значение, тем более вероятной целью при OOM она становится. |
oom_canary_relaunch |
true |
Перезапускать канарейку после её завершения (если это не постоянный сбой инициализации и не штатная остановка) с учётом указанных ниже ограничений. |
oom_canary_max_rapid_relaunches |
10 |
Максимальное число последовательных быстрых перезапусков до отключения автоперезапуска, чтобы избежать постоянных циклов перезапуска. Счётчик сбрасывается, если канарейка проработает дольше oom_canary_max_backoff_seconds. |
oom_canary_initial_backoff_seconds |
1 |
Начальная задержка между перезапусками; каждый раз удваивается до максимального значения. |
oom_canary_max_backoff_seconds |
60 |
Максимальная задержка между перезапусками. |
<clickhouse>
<oom_canary_enable>1</oom_canary_enable>
<oom_canary_size>104857600</oom_canary_size>
</clickhouse>Обсервабилити
Подтверждённый OOM создаёт строку в
system.crash_log с signal = 9 и
signal_description, где упоминается OOM Canary:
SELECT event_time, signal, signal_description
FROM system.crash_log
WHERE signal = 9 AND signal_description LIKE '%OOM Canary%'
ORDER BY event_time DESC;Жизненный цикл канарейки и каждый этап реакции на OOM также записываются в журнал сервера.