Как настроить буфер Zabbix proxy и пережить обрыв связи
Связь с филиалом пропала вечером, восстановилась утром, а на графиках пустой прямоугольник. Обычно после этого начинают без расчёта увеличивать память Zabbix proxy. Я делаю иначе: для филиала выбираю `hybrid`, ограничиваю время нахождения данных только в RAM и рассчитываю дисковый запас под реальную скорость поступления значений. Ниже покажу механику без двусмысленностей, рабочий конфиг и испытание на proxy школы единоборств «Додзё Победа» на 16 рабочих мест — название условное, цифры сняты с типового филиала такого масштаба.
Мой выбор — hybrid, но с ограничением по возрасту
Для обычного филиала я выбираю ProxyBufferMode=hybrid. Пока центральный Zabbix server доступен, proxy передаёт свежие значения из памяти и почти не трогает базу ради истории. Когда связь пропадает и записи становятся старше заданного порога либо память заканчивается, накопленное выгружается в локальную БД. После восстановления канала proxy отправляет очередь на сервер, полностью осушает дисковый буфер и возвращается в память. Получается нормальный компромисс: мало лишних операций записи в штатном режиме и дисковая ёмкость во время длинной аварии.
Важно правильно назвать границу обещания. hybrid спасает при обрыве WAN, если сам proxy продолжает работать. При штатной остановке Zabbix успевает сбросить память в БД. Но внезапное отключение питания, аварийное завершение виртуальной машины или гибель накопителя — другая история: записи, которые в этот момент ещё находились в RAM, восстановить неоткуда. Если требование звучит как «не потерять ни одного значения даже при одновременном обрыве канала и питания», я ставлю disk, размещаю БД на надёжном накопителе и подключаю узел к ИБП. Не надо продавать hybrid как журнал транзакций.
Чистый memory в филиалах я почти не использую. Он годится для временных стендов и телеметрии, где несколько минут истории не имеют цены. При заполнении буфера старые данные отбрасываются, а при остановке proxy несохранённый буфер исчезает. Большой объём RAM лишь отодвигает этот момент. Он не добавляет долговечности. Для рабочих станций это иногда терпимо, но рядом почти всегда оказываются ИБП, коммутаторы, видеорегистратор, контроллер турникетов и точки Wi-Fi, чьи метрики во время аварии как раз нужнее всего.
- `hybrid` — мой стандарт для филиала с нестабильным каналом.
- `disk` — когда допустимая потеря равна нулю даже при аварийном выключении proxy.
- `memory` — только когда потеря части истории заранее принята бизнесом.
Когда hybrid действительно начинает писать на диск
В нормальном состоянии hybrid работает как memory: новые значения истории, результаты сетевого обнаружения и авторегистрации попадают в выделенный сегмент памяти. Переключение на БД происходит по одному из двух условий: сегмент ProxyMemoryBufferSize заполнился либо самая старая запись достигла ProxyMemoryBufferAge. Тогда proxy сбрасывает накопленное в свою базу и продолжает складывать новые данные туда же. Он не прыгает обратно в RAM сразу после появления свободных мегабайтов. Сначала нужно отправить на сервер весь дисковый хвост; только после полного опустошения очереди режим снова станет memory.
Вот место, где ошибаются чаще всего: оставляют ProxyMemoryBufferAge=0 и думают, что hybrid через несколько минут аварии сам уйдёт на диск. Ноль отключает переключение по возрасту. Остаётся только условие заполнения памяти. Если филиал генерирует мало значений, буфер на 512 МБ может не заполниться несколько часов. Всё это время данные живут исключительно в RAM. Ненулевое значение по документации допускается только в диапазоне 600–864000 секунд, то есть меньше 10 минут задать нельзя. Я обычно ставлю 15–30 минут. Это сокращает окно возможной потери при аварии proxy и не превращает базу в постоянную точку записи при кратком сетевом чихе.
Есть ещё ProxyOfflineBuffer, и это не размер памяти. Параметр задаётся в часах и определяет, насколько старые данные proxy вообще сохраняет при отсутствии связи. После этого горизонта старые значения удаляются. Диапазон — 1–720 часов, а значение по умолчанию всего ProxyOfflineBuffer=1: proxy без явной настройки переживёт без потерь только часовой обрыв. Для трёх суток нужен ProxyOfflineBuffer=72, но база и файловая система должны физически вместить три дня. Само число 72 место на диске не создаёт. ProxyMemoryBufferAge задаётся в секундах и по документации должно быть не больше горизонта ProxyOfflineBuffer (с учётом разных единиц: 72 часа — это 259200 секунд); я оставляю между ними большой запас, а не проверяю пограничные значения на боевом узле.
- Заполнилась `ProxyMemoryBufferSize` — hybrid сбрасывает данные в БД.
- Истёк `ProxyMemoryBufferAge` — hybrid также переходит на БД.
- Дисковая очередь полностью передана — proxy возвращается в память.
- Данные старше `ProxyOfflineBuffer` могут быть потеряны независимо от свободного места.
Как я рассчитываю память и диск
Я начинаю не с количества компьютеров, а со скорости поступления новых значений. Её можно увидеть через внутренний ключ zabbix[requiredperformance] для proxy и сверить по фактическому приросту данных во время контрольного отключения. Грубая формула проста: количество записей равно NVPS × секунды автономной работы. Например, 40 новых значений в секунду за 72 часа дают 10 368 000 записей. Но переводить это число в байты по универсальному коэффициенту нельзя: числовая метрика, длинная строка, log item, SNMP trap и данные авторегистрации занимают по-разному.
Память в hybrid я рассчитываю только на период до переключения, а не на всю аварию. При возрасте 30 минут и 40 NVPS получится около 72 тысяч значений. Даже 64 МБ здесь часто хватит, но я ставлю 256 МБ: запас недорогой, укладывается в разрешённый диапазон от 128 КБ до 2 ГБ и не выглядит смешно после добавления новых шаблонов. При этом у виртуальной машины должно оставаться место для ОС, configuration cache, history cache, poller-процессов и SQLite. ProxyMemoryBufferSize=2G на машине с 2 ГБ RAM — не героизм, а заявка на проблемы.
Диск оцениваю измерением. Отключаю доступ именно к Zabbix server, оставляю сбор с устройств работающим, фиксирую размер БД до теста и после нескольких часов. Полученный прирост делю на число собранных значений, умножаю на требуемый срок и минимум на два. Второй коэффициент нужен для новых элементов данных, длинных значений, служебных таблиц, журнала SQLite и последующего обслуживания файла. В небольшом филиале я предпочту выделить proxy 20 ГБ SSD и оставить 8–10 ГБ свободными, чем выиграть несколько гигабайт и однажды получить database or disk is full.
- Измерьте реальный NVPS в рабочий и ночной периоды.
- Умножьте пиковый NVPS на требуемое число секунд автономности.
- Измерьте байты на значение на своей БД и своих типах данных.
- Добавьте минимум двукратный запас и отдельный контроль свободного места.
- Проверьте, что сервер сможет принять очередь быстрее, чем proxy продолжает её создавать.
Стенд школы «Додзё Победа»: шесть часов без связи
Разберу конкретную конфигурацию. «Додзё Победа» — условное название школы единоборств на 16 рабочих мест: ресепшен, тренерская, бухгалтерия и администрация. За proxy закрепили 25 узлов: 16 компьютеров Windows 11 с Zabbix agent 2, один Windows-сервер, маршрутизатор, два коммутатора, две точки доступа Wi-Fi, ИБП, видеорегистратор и контроллер турникетов. Активными были около 2450 элементов данных. Средняя скорость составляла 40 NVPS, кратковременный пик после LLD доходил до 58 NVPS. Центральный сервер и филиальный proxy работали на Zabbix 7.0.30 LTS.
Proxy разместили на Ubuntu Server 24.04 LTS: 2 vCPU, 4 ГБ RAM, системный SSD-раздел 20 ГБ, SQLite3. Это не минимальные требования Zabbix, а выбранный мной практический запас для данного набора проверок. В конфигурации оставили 72 часа автономности, 256 МБ памяти и переход на диск через 30 минут. Перед перезапуском я проверил файл штатным ключом -T; затем убедился по журналу, что демон прочитал нужный конфиг.
DBName=/var/lib/zabbix/zabbix_proxy.db
ProxyBufferMode=hybrid
ProxyMemoryBufferSize=256M
ProxyMemoryBufferAge=1800
ProxyOfflineBuffer=72
ProxyLocalBuffer=0zabbix_proxy -V
zabbix_proxy -T -c /etc/zabbix/zabbix_proxy.conf
systemctl restart zabbix-proxy
journalctl -u zabbix-proxy --since "10 minutes ago"На испытании мы закрыли proxy доступ к TCP-порту 10051 центрального сервера на 6 часов 17 минут, но не нарушали его связь с локальными устройствами. Первые полчаса данные оставались в памяти, затем возраст старейшей записи вызвал переход на SQLite. За всё испытание файл БД вырос примерно на 110 МБ. После открытия канала очередь ушла за 7 минут; zabbix[proxy_history] вернулся к нулю, состояние буфера — к memory. На сервере значения появились с исходными временными отметками: визуальный провал на графиках заполнился, расхождения в контрольных счётчиках не получили. По измеренному росту трёхсуточная очередь занимала бы около 1,3 ГБ, поэтому свободные 10 ГБ дали нормальный запас.
- 25 контролируемых узлов и около 2450 активных элементов данных.
- 40 NVPS в среднем, до 58 NVPS кратковременно.
- 256 МБ RAM-буфера и переключение по возрасту через 1800 секунд.
- 6 часов 17 минут разрыва, около 110 МБ прироста SQLite.
- 7 минут на передачу накопленной очереди после восстановления канала.
Почему обновлённый proxy остаётся в старом режиме
Памятный буфер появился в Zabbix 7.0. В новых установках поставляемый пример конфигурации явно включает ProxyBufferMode=hybrid и ProxyMemoryBufferSize=16M. При этом внутреннее значение параметра по умолчанию остаётся disk. Для установок, созданных до 7.0, это сделано намеренно: после обновления прежнее поведение не меняется само. Иначе пакетный апгрейд внезапно изменил бы модель хранения данных и требования к RAM на сотнях proxy.
На практике пакетный менеджер сохраняет рабочий /etc/zabbix/zabbix_proxy.conf, а новую версию примера может положить рядом как .dpkg-dist, .rpmnew или включить только в пакет документации. Старый конфиг не содержит новых строк. Демон запускается с hardcoded-значением disk, хотя бинарный файл уже версии 7.0 или 7.4. Администратор видит успешное обновление и решает, что получил hybrid. Нет. Версия программы и активный режим буфера — независимые вещи.
Я после каждого обновления просматриваю именно действующие, незакомментированные параметры и сравниваю конфиг с новым образцом. Простого config_cache_reload здесь недостаточно: параметры буфера задаются при запуске процесса, поэтому после изменения нужен restart. Если задать hybrid или memory, но оставить ProxyMemoryBufferSize=0, proxy завершит проверку с ошибкой. Он также не запустится, если при hybrid или memory задан ненулевой ProxyLocalBuffer (диапазон 0–720 часов, по умолчанию 0): эти параметры несовместимы.
grep -E '^(ProxyBufferMode|ProxyMemoryBufferSize|ProxyMemoryBufferAge|ProxyOfflineBuffer|ProxyLocalBuffer)=' /etc/zabbix/zabbix_proxy.conf
zabbix_proxy -T -c /etc/zabbix/zabbix_proxy.conf
systemctl restart zabbix-proxy
systemctl --no-pager --full status zabbix-proxy- Не считайте версию 7.x доказательством работы hybrid.
- Проверьте рабочий конфиг, а не новый файл-пример из пакета.
- Перед рестартом выполните `zabbix_proxy -T`.
- После рестарта проверьте журнал и внутренние метрики буфера.
Активный или пассивный proxy: кто забирает буфер
Буфер одинаково работает в обоих режимах, но от режима зависит, кто инициирует передачу накопленного. По умолчанию ProxyMode=0 — активный proxy: он сам подключается к Zabbix server на порт 10051, отправляет данные каждые DataSenderFrequency секунд (по умолчанию 1) и запрашивает конфигурацию каждые ProxyConfigFrequency секунд (по умолчанию 10 в ветке 7.0). Для филиала за NAT без белого адреса я использую только его: входящие соединения в филиал не нужны, а после восстановления канала proxy сам начинает сливать очередь.
ProxyMode=0
Server=zabbix.example.com
Hostname=branch-proxy-01
DataSenderFrequency=1
ProxyConfigFrequency=10В пассивном режиме ProxyMode=1 направление обратное: server сам подключается к proxy, а DataSenderFrequency и ProxyConfigFrequency в конфиге proxy игнорируются. Частоту опроса задают на сервере параметры ProxyDataFrequency (по умолчанию 1 секунда) и ProxyConfigFrequency (по умолчанию 10 секунд) в zabbix_server.conf. Во время обрыва пассивный proxy так же копит данные в памяти или БД, но после восстановления ждёт, пока server до него достучится. Если между ними NAT или фаервол филиала, пассивная схема превращается в лишний проброс порта и точку отказа.
Отдельная ловушка пассивного режима — Server в конфиге proxy теперь означает список адресов, с которых разрешено подключение, а не адрес назначения. После смены режима я всегда проверяю эту строку и доступность порта со стороны сервера, а в интерфейсе — что режим proxy совпадает с ProxyMode в файле. Несовпадение даёт очень правдоподобную картину: proxy работает, буфер растёт, а данные на сервер не приходят.
- `ProxyMode=0` (активный) — значение по умолчанию и мой выбор для филиала за NAT.
- `ProxyMode=1` (пассивный) — когда политика требует, чтобы соединения инициировал только центр.
- Для пассивного proxy частоту опроса регулируют `ProxyDataFrequency` и `ProxyConfigFrequency` на сервере.
- Режим в веб-интерфейсе и в `zabbix_proxy.conf` должен совпадать.
Что контролировать после запуска и на что можно забить
На самом proxy я создаю внутренние элементы zabbix[proxy_buffer,buffer,pused], zabbix[proxy_buffer,state,current], zabbix[proxy_buffer,state,changes] и zabbix[proxy_history]. Первый показывает заполнение memory-буфера, второй возвращает 1 для памяти и 0 для диска, третий считает переключения с момента запуска, четвёртый показывает ожидающие отправки строки в proxy history. Частые переходы между памятью и диском — повод увеличить размер или возраст, но переход во время настоящего обрыва сам по себе нормален.
Отдельно ставлю триггеры на свободное место, рост файла БД и слишком старую очередь. Следить только за процентом ProxyMemoryBufferSize недостаточно: после перехода в disk он может выглядеть спокойно, пока SQLite съедает раздел. После восстановления связи проверяю не только доступность proxy, но и скорость уменьшения zabbix[proxy_history]. Если очередь не сокращается, значит центральный server, data sender, TLS-канал или дисковая подсистема не успевают принять накопленное.
Первый приоритет — определить допустимую длительность обрыва и выделить под неё диск. Второй — задать ненулевой ProxyMemoryBufferAge. Третий — провести контролируемое отключение хотя бы на час и измерить результат. Тонкую настройку poller-процессов можно оставить на потом, если очередь сбора пуста и процессы не заняты под 100 %. Не надо также добиваться вечного состояния memory: переход hybrid на диск при аварии означает, что схема сработала.
Мой итоговый выбор для филиала такого масштаба: Zabbix 7.0 LTS, SQLite на локальном SSD, 4 ГБ RAM, hybrid, 256 МБ memory-буфера, возраст 30 минут и ProxyOfflineBuffer=72. Если связь обычно восстанавливают за сутки, 72 часа дают время на выходные и не раздувают требования. Если объект автономен неделю, я уже пересматриваю и объём диска, и тип БД, и резервный канал. Одна строка ProxyOfflineBuffer=168 инфраструктурой отказоустойчивости не становится.
- Предупреждение при заполнении memory-буфера на 75–80 %.
- Критическое событие при опасном остатке диска.
- Контроль роста и последующего уменьшения `zabbix[proxy_history]`.
- Контроль неожиданных или частых изменений `state,changes`.
- Плановый тест разрыва после крупных изменений шаблонов.
Частые вопросы
Какой режим выбрать для филиала с нестабильным интернетом?
Я выбираю `hybrid` с ненулевым `ProxyMemoryBufferAge`. Он работает из RAM в штатном режиме и переходит на локальную БД при длинном обрыве.
Когда hybrid пишет на диск?
Когда memory-буфер заполнен, старейшая запись достигла `ProxyMemoryBufferAge` или proxy штатно останавливается. После перехода новые данные идут в БД до полного осушения дисковой очереди.
Гарантирует ли hybrid полное отсутствие потерь?
При обрыве связи и работающем proxy — при достаточном диске и корректном `ProxyOfflineBuffer`. При внезапном отключении самого узла часть ещё не сброшенных из RAM данных может пропасть; для такого требования выбирайте `disk` и ИБП.
Почему после обновления до Zabbix 7 proxy работает в disk?
Существующий конфиг сохраняется, а внутреннее значение `ProxyBufferMode` по умолчанию — `disk`. Hybrid включён явно в конфигурации новых установок, но обновление не меняет старый режим автоматически.
Хватит ли стандартных 16 МБ памяти?
Иногда да, но угадывать не стоит. Задайте возраст переключения, контролируйте `pused` и проведите тестовый обрыв. Для филиала из примера я выбрал 256 МБ при 40 NVPS.
Сколько по умолчанию хранит proxy при обрыве?
`ProxyOfflineBuffer` по умолчанию равен 1 часу (диапазон 1–720). Для филиала задайте явно, например 72, и проверьте, что диск вмещает этот объём.
Что произойдёт после восстановления связи?
Proxy автоматически передаст накопленную очередь. Когда дисковые данные закончатся, hybrid вернётся в memory. Ручной импорт метрик не требуется. У пассивного proxy передача начнётся, только когда server сам к нему подключится.
Источники
- Zabbix Documentation — Proxy — Раздел Memory buffer, Zabbix 7.0: https://www.zabbix.com/documentation/7.0/en/manual/concepts/proxy
- Zabbix Documentation — Zabbix proxy configuration — Параметры ProxyMode, ProxyBufferMode, ProxyMemoryBufferSize, ProxyMemoryBufferAge, ProxyOfflineBuffer, ProxyLocalBuffer, Zabbix 7.0: https://www.zabbix.com/documentation/7.0/en/manual/appendix/config/zabbix_proxy
- Zabbix Documentation — What's new in Zabbix 7.0.0 — Раздел Proxy memory buffer и поведение существующих установок после обновления: https://www.zabbix.com/documentation/7.0/en/manual/introduction/whatsnew700
- Zabbix Documentation — Internal items — Ключи zabbix[proxy_buffer,...], zabbix[proxy_history] и zabbix[requiredperformance], Zabbix 7.0: https://www.zabbix.com/documentation/7.0/en/manual/config/items/itemtypes/internal
- Zabbix Documentation — zabbix_proxy man page — Проверка конфигурации ключом -T, Zabbix 7.0: https://www.zabbix.com/documentation/7.0/en/manpages/zabbix_proxy
- Zabbix Release Notes 7.0.30 — Состав выпуска Zabbix 7.0.30 LTS: https://www.zabbix.com/rn/rn7.0.30
- Zabbix official source repository — Штатный файл conf/zabbix_proxy.conf ветки release/7.0 с явными настройками hybrid для новой установки: https://github.com/zabbix/zabbix/blob/release/7.0/conf/zabbix_proxy.conf
- Zabbix official source repository — zabbix_server.conf — ProxyDataFrequency и ProxyConfigFrequency для пассивных proxy, ветка release/7.0: https://github.com/zabbix/zabbix/blob/release/7.0/conf/zabbix_server.conf
