Схема контроля Ceph scrub и deep-scrub: policy, очередь PG, health detail и сохранение evidence.
Схема основана на материале «Как я контролирую Ceph scrub и deep-scrub: просрочку проверок и ошибки целостности» и его сигналах. Причинная схема без белой логотипной плашки: слева policy и разрешённые окна, затем очередь PG и две независимые временные линии scrub и deep-scrub; развилка ведёт либо к свежему результату, либо к просрочке, а health detail с inconsistent и scrub errors направляет к блоку сохранения evidence до любого решения. Контекст PG и acting OSD показан боковой связью, Zabbix остаётся только read-only наблюдателем и не соединяется стрелкой запуска с repair.

Начинаю с жизненного цикла, а не с общего цвета

В этой практике я не строю ещё одну панель общего здоровья Ceph. Я, Семёнов Евгений Сергеевич, веду эту работу как технический директор IT Fresh. Одновременно я основатель компании и ведущий системный администратор, поэтому отвечаю и за инженерную проверяемость предложенного маршрута. Меня интересует отдельный жизненный цикл: когда PG стала кандидатом на проверку, могла ли она стартовать в разрешённом окне, действительно ли проверка завершилась, какой результат вернул кластер и осталось ли доказательство для следующего решения. Общий health нужен как вход, но не заменяет эту временную цепочку. Зелёное состояние в момент опроса не отвечает само по себе на вопрос, насколько давно конкретная PG проходила глубокую проверку. Предупреждение о просрочке, напротив, ещё не означает повреждение данных. Поэтому я храню рядом четыре времени: момент сбора Zabbix, время самого ответа Ceph, последнюю известную обычную проверку и последнюю известную глубокую проверку. Если какое-то значение отсутствует или схема изменилась, результат становится неизвестным, а не нулевым. Такой подход заметно отличается от расследования quorum, общей доступности OSD или клиентской задержки: здесь первична последовательность проверки целостности. До настройки я записываю, кто владеет policy, где определены допустимые окна и какое действие разрешено дежурному. Стоп-критерий на первом шаге — невозможность получить однозначные отметки или подтвердить их смысл для установленного выпуска. В таком случае я не изобретаю поле и не создаю триггер на предположении.

Scrub и deep-scrub дают разные свидетельства

Обычный scrub и deep-scrub я показываю раздельно, потому что они проверяют не одно и то же и имеют разную стоимость. Scrub сопоставляет метаданные объектов и помогает выявлять расхождения без полного чтения содержимого каждого объекта. Deep-scrub дополнительно читает данные и проверяет их глубже, включая контрольные признаки там, где они применимы. Из этого следует важная причинная граница: свежий scrub не доказывает свежесть deep-scrub, а просроченный deep-scrub нельзя закрыть только фактом недавней обычной проверки. Более тяжёлая операция способна заметнее конкурировать с клиентской нагрузкой, поэтому расписание и ограничения должны принадлежать Ceph policy, а не автоматизации Zabbix. В карточке PG я вывожу две независимые отметки, два возраста и два состояния доказательства. Если версия отдаёт только часть этих данных, именно эту часть и показываю, явно называя предел наблюдения. Ошибка, найденная любой проверкой, переводит расследование из ветки свежести в ветку целостности: теперь важны исходный health detail, affected PG, acting OSD и сохранённый снимок до вмешательства. Стоп-критерий — попытка объединить оба вида проверки одним булевым флагом или вывести отсутствие повреждения из факта запуска. Запуск не равен завершению, завершение без разобранного результата не равно доказанной норме.

Просрочку вычисляю относительно policy и окон

Я не задаю универсальное число часов для любого кластера. Сначала получаю утверждённую policy и эффективные параметры конкретной установки: интервалы, разрешённые часы и дни, ограничения нагрузки, а также особенности выпуска. Затем возраст последней проверки сравниваю не только с целевым интервалом, но и с реальной возможностью запуска. Например, PG может достичь планового возраста сразу после закрытия разрешённого окна; это ещё не тот же случай, что многократный пропуск доступных окон. Поэтому модель содержит состояния приближения, ожидания первого подходящего окна, подтверждённой просрочки после доступной возможности и неизвестности из-за неполных данных. Порог Zabbix задаю макросом кластера и документирую его происхождение, но событие включает саму policy, последнюю отметку и вычисленный возраст. Изменение policy не должно задним числом делать старую историю однозначной: рядом хранится версия снимка конфигурации. Я также проверяю синхронизацию времени, потому что смещение часов способно породить отрицательный возраст или ложную свежесть. Стоп-критерии здесь — неизвестная временная зона, будущая отметка, отсутствие доверенного текущего времени или расхождение policy между источниками. При них событие классифицируется как проблема достоверности сбора, а не как просрочка целостности.

Очередь и отложенные проверки читаю как контекст

Когда просроченных PG становится больше, я не назначаю причиной носитель или OSD по одному счётчику. Сначала выясняю, видит ли Ceph кандидатов на проверку и что могло ограничить их выполнение. Сопоставляю разрешённое окно с текущим временем, активные флаги, состояния PG, recovery и backfill, клиентскую нагрузку и доступность acting OSD. Очередь может расти, потому что окно слишком узко для фактического профиля, потому что PG не находится в подходящем состоянии или потому что приоритет отдан другой работе. Эти гипотезы требуют разных решений и не должны сливаться в сообщение «диск неисправен». В Zabbix я показываю динамику: сколько PG ожидают, сколько впервые пересекли границу, сколько получили доступное окно и всё равно не продвинулись. Важнее направление и длительность, чем единичный снимок. Если после открытия окна свежесть начинает обновляться и ошибок нет, это свидетельство работы планировщика, но не гарантия будущей производительности. Если очередь растёт вместе с деградацией PG, расследование передаётся владельцу Ceph с обоими наборами evidence. Стоп-критерий — предложение массово запустить проверки ради очистки графика. Сначала нужно оценить влияние и подтвердить отдельный эксплуатационный план вне Zabbix.

Ошибку целостности отделяю от ошибки коллектора

Самая опасная путаница возникает, когда невозможность разобрать ответ выглядит как отсутствие ошибок. Поэтому master item хранит статус выполнения wrapper, время, версию схемы и ограниченный исходный JSON, а dependent items создаются только после успешной валидации. Ошибка команды, отказ прав, timeout или неизвестное поле формируют отдельное событие наблюдаемости. Они не превращаются в ноль scrub errors. Реальный признак целостности я беру из health detail и состояний PG, сохраняя код проверки, affected PG и связанный контекст OSD. Термин inconsistent рассматриваю как сигнал расхождения, а не как готовый диагноз физического устройства. До любого изменения фиксирую снимок health, карту PG, acting set, версию Ceph, время и соседние события. Это evidence before remediation: оно позволяет сравнить состояние после согласованного действия и не потерять исходную картину. Я не помещаю полный внутренний вывод в уведомление и не раскрываю имена узлов публично; дежурный получает идентификатор события и путь к защищённому evidence. Стоп-критерии — отсутствие идентичности PG, меняющийся между чтениями набор без временных отметок или предложение repair до сохранения данных. Тогда автоматическая ветка заканчивается, а решение принимает ответственный инженер Ceph.

PG и OSD использую для локализации, не для приговора

После появления ошибки я связываю affected PG с acting OSD, но не делаю скачок от совместного присутствия к виновности. Одна PG имеет набор реплик, а наблюдаемое расхождение само по себе не сообщает, какая копия правильная и почему они разошлись. Я смотрю, повторяются ли затронутые PG на одном OSD, совпадает ли время с ошибками daemon или носителя, были ли изменения размещения и доступны ли все участники для чтения. Одновременно проверяю, не устарел ли снимок карты. Эта корреляция помогает расставить приоритет исследования, но команда мониторинга не выбирает источник истины. Health detail и события daemon сохраняю как независимые свидетельства, а не склеиваю в одно текстовое поле. Если affected PG исчезает из следующего снимка, я проверяю, было ли документированное действие и получен ли новый результат проверки; простое исчезновение предупреждения не стирает историю. Стоп-критерий — намерение вывести OSD из строя, перезапустить его или изменить размещение только потому, что он встретился в acting set. Такие операции находятся за границей read-only runbook и требуют отдельной оценки устойчивости, ёмкости и пути восстановления.

Сбор в Zabbix оставляю узким и проверяемым

Для сбора я предпочитаю один локальный wrapper с фиксированными read-only командами и одним JSON-ответом. Это уменьшает число обращений к monitor и позволяет dependent items разобрать общий снимок без повторных запросов. Wrapper не принимает параметры от пользователя, макросов или обнаружения; путь и команды зафиксированы в файле с административным владельцем. Учётная запись не получает возможности менять конфигурацию или запускать обслуживающие операции. В Zabbix master item имеет разумный интервал, timeout и отдельный признак unsupported, а тяжёлые перечни не запрашиваются чаще, чем нужно принятой модели реакции. Preprocessing проверяет типы, обязательные поля и время; пустой массив допустим только там, где официальный формат действительно означает отсутствие объектов. Для событий использую tags кластера, типа проверки, класса evidence и состояния свежести, но не секреты и не полную топологию. Небольшой UserParameter из configuration_collection показывает границу: агент вызывает один файл без аргументов. Стоп-критерий — необходимость передать keyring через параметры, открыть произвольный shell, разрешить wildcard-команды или собирать полный дамп чаще без измерения стоимости. В этом случае я останавливаю внедрение и меняю способ коллекции, а не расширяю доступ ради удобства.

Проверяю логику без воздействия на production

Контролируемый тест не обязан создавать настоящее расхождение данных. Я использую сохранённые обезличенные ответы и тест preprocessing, чтобы пройти три ветки: нормальную свежесть, просрочку после разрешённого окна и ошибку inconsistent. Проверяю, что каждое событие содержит ожидаемое время, PG и класс причины, а нормальный fixture создаёт Recovery. Затем сравниваю один рабочий read-only снимок wrapper с прямым чтением тем же ограниченным ключом. Я не запускаю scrub ради проверки триггера и тем более не создаю повреждение. Такой тест подтверждает тракт сбора, вычисление возраста, маршрутизацию и отображение evidence, но честно не доказывает поведение кластера при реальном отказе. Если формат текущей версии отличается, сначала обновляю fixture и только потом preprocessing. Если событие появляется из-за старого master item, оно должно называться потерей свежести наблюдения, а не ошибкой Ceph. Стоп-критерии: неожиданная нагрузка, запрос прав изменения, неоднозначный разбор времени, потеря идентификатора PG или уведомление без ссылки на исходное свидетельство. Rollback выполняю сразу: выключаю новые items и actions, возвращаю прежние интервалы и оставляю сам Ceph неизменным.

Решение принимаю только после сохранения evidence

Итоговый маршрут у меня короткий, но строгий. Дежурный сначала доказывает свежесть коллектора, затем читает health detail, сопоставляет обе отметки проверки с policy и окнами, оценивает очередь и только после этого переходит к affected PG и OSD. Просрочка без ошибки направляется владельцу расписания и ёмкости окна; inconsistent или scrub errors требуют приоритетного инженерного разбора. Ни один путь не заканчивается автоматическим repair. До вмешательства сохраняются исходный JSON, версия, время, PG, acting set и связанные события. Дальнейшие команды выбирает владелец Ceph по документации установленного выпуска, состоянию реплик и утверждённому регламенту. Recovery в Zabbix наступает после нового достоверного результата: свежая проверка завершилась, признак ошибки исчез и первичный источник это подтвердил. Ручное закрытие не заменяет доказательство. Если безопасный следующий шаг неизвестен, данных недостаточно или затрагивается несколько PG с общей неопределённостью, это явный стоп-критерий и основание для эскалации, а не для эксперимента. Обсудить проект мониторинга можно на https://itfresh.ru/, рабочие заметки доступны по https://t.me/ITfresh_Boss, связаться по телефону можно через tel:+79037296241.

Сигналы, которые сопоставляю

  • Свежесть master item и успешность разбора отделены от содержательного состояния Ceph; отсутствие данных не превращается в нормальный ноль.
  • Возраст последнего scrub и deep-scrub хранится раздельно по PG и сравнивается с утверждённой policy и фактически доступными окнами.
  • Очередь кандидатов и доля PG, не продвинувшихся после разрешённого окна, рассматриваются вместе с нагрузкой, флагами и состояниями PG.
  • Health detail сохраняет точные проверки PG_NOT_SCRUBBED, PG_NOT_DEEP_SCRUBBED, OSD_SCRUB_ERRORS и inconsistent, если они поддерживаются установленным выпуском и реально присутствуют.
  • Affected PG сопоставляются с acting OSD и событиями daemon только для локализации; совпадение не объявляется доказанной физической причиной.
  • Recovery требует нового свежего результата первичного источника и не возникает от ручного закрытия либо автоматической команды изменения.

Отвергнутые альтернативы

  • Считать HEALTH_OK доказательством своевременного deep-scrubОбщий статус является текущей агрегацией. Для свежести нужны фактические отметки проверок, policy, разрешённые окна и подтверждение, что снимок коллектора не устарел.
  • Назначить всем кластерам один календарный порогРасписание, допустимые окна, нагрузка, выпуск Ceph и эксплуатационная политика различаются. Один порог создаст ложные просрочки либо скроет реальное отставание.
  • Автоматически запускать deep-scrub для каждой просроченной PGОперация читает данные и создаёт нагрузку; массовый запуск способен ухудшить клиентский сервис и нарушить планирование. Zabbix должен сообщать evidence, а решение принимает владелец кластера.
  • Автоматически применять repair при inconsistentНесогласованность ещё не указывает, какая копия верна и какова причина. До изменения нужны сохранённые доказательства, анализ PG и OSD, резервный путь и отдельное одобрение.
  • Объяснять очередь проверок только неисправностью дискаПроверки могут откладываться из-за разрешённых окон, нагрузки, состояния PG, флагов и других ограничений. Носитель — одна из гипотез, а не вывод из длины очереди.

Конфигурация и сбор

Я выделяю локальную учётную запись сбора без интерактивного входа и без прав изменения. Ей разрешён только вызов фиксированного wrapper на Ceph-узле с ключом, имеющим минимальные возможности чтения состояния monitor и OSD, необходимые для согласованных команд status, health detail, pg dump и osd dump. Wrapper не принимает аргументы из макросов, не возвращает keyring и отбрасывает внутренние имена перед передачей. Агент Zabbix получает только его подготовленный JSON; sudo, если он действительно нужен конкретной установке, разрешает единственный файл wrapper без shell и без произвольной команды. Права на запуск scrub, deep-scrub, repair, изменение конфигурации, управление daemon и запись в Proxmox VE API не выдаются.

  • На Ceph-узле выполнить фиксированный read-only wrapper, который последовательно читает `ceph status --format json`, `ceph health detail --format json`, `ceph pg dump pgs_brief --format json` и разрешённый снимок `ceph osd dump --format json`; перед внедрением сверить доступность полей с установленной версией.
  • Из одного JSON master item создать dependent items: доступность коллектора, время сбора, общий health, коды и тексты проверок, число PG по состояниям, идентификаторы проблемных PG, счётчики scrub errors и наблюдаемые отметки последнего scrub и deep-scrub там, где версия их предоставляет.
  • Политику получать отдельным редким read-only снимком эффективной конфигурации или утверждённым инвентарём: интервалы, допустимые часы и дни, ограничения нагрузки и флаги, способные блокировать либо откладывать проверку. Не подставлять отсутствующее поле значением по умолчанию по памяти.
  • В Zabbix хранить исходное время Ceph и время приёма отдельно; возраст вычислять dependent item, а порог просрочки задавать макросом конкретного кластера после сверки с его policy и окнами обслуживания.
  • События разделить на недостоверный сбор, приближение к границе свежести, подтверждённую просрочку, накопление ожидающих проверок и обнаруженную ошибку целостности; для recovery требовать новый свежий read-only снимок, а не ручное закрытие.
  • Безопасный фрагмент UserParameter: `UserParameter=ceph.scrub.snapshot,/usr/local/libexec/zbx-ceph-scrub-readonly`; файл wrapper принадлежит root, не принимает `$1`, а его разрешённый вывод проверяется как JSON до передачи в preprocessing.

Контролируемая проверка и свидетельство

Я проверяю тракт на сохранённых обезличенных JSON-ответах официального формата и во встроенном тесте preprocessing Zabbix. Подготавливаю три fixture вне production: свежая завершённая проверка без ошибок, просроченная отметка относительно тестовой policy и PG с тестовым признаком inconsistent. Подаю их только в тестовый master item либо в preprocessing test, не меняя состояние Ceph и не вызывая scrub, deep-scrub или repair. Ожидаю разные события, корректные tags, отсутствие подмены пустого значения нулём и Recovery после возврата свежего нормального fixture. Затем на одном рабочем кластере выполняю только чтение и сравниваю JSON wrapper с непосредственным read-only выводом в один момент. Стоп-критерии: wrapper требует расширить права, создаёт заметную нагрузку, вывод меняется во время разбора, появляются неизвестные поля или событие целостности теряет идентификатор PG. При любом из них тест останавливаю, items оставляю выключенными и возвращаюсь к схеме данных; воздействующий тест в рабочем кластере не провожу.

Фрагмент рабочего регламента

  • Проверить свежесть самого master item, время Ceph и ошибку preprocessing; при старом или неполном снимке состояние целостности считать неизвестным, а не нормальным.
  • Прочитать `ceph health detail` и зафиксировать точные health checks, affected PG и время; не ограничиваться цветом общего health.
  • Сопоставить отметки последнего scrub и deep-scrub с эффективной policy, разрешённым окном и текущим временем; отдельно отметить PG, которые ещё не получили возможность выполнить проверку.
  • Проверить состояния PG и связь с acting OSD, blocked или inactive состояниями, recovery/backfill и флагами; это контекст задержки, но не автоматическое доказательство причины.
  • При inconsistent или scrub errors сохранить исходный JSON, список PG, версию, карту OSD и соседние health events как evidence; не запускать repair из Zabbix.
  • Остановить разбор и передать решение владельцу Ceph, если данные расходятся между monitor, поля не поддерживаются версией, нет безопасных прав чтения или следующий шаг способен изменить данные.

Откат

Откат касается только добавленного наблюдения. Я сначала отключаю новые triggers и actions, затем master и dependent items на пилотном host, возвращаю сохранённые интервалы и preprocessing, отвязываю только новый шаблон и удаляю созданное для него правило UserParameter. После подтверждения, что старый мониторинг продолжает работать, владелец отзывает отдельный read-only ключ и точечное sudo-правило. Историю событий и обезличенный evidence сохраняю по принятому сроку, чтобы не потерять объяснение решения; секреты и полный внутренний вывод в истории не оставляю. Если сбор увеличил нагрузку либо выдаёт несовместимую схему, немедленно прекращаю опрос и не пытаюсь исправить это запуском Ceph-операций. Откат мониторинга не отменяет и не изменяет расписание scrub, состояние PG, OSD или данные кластера. Подтверждение отката — отсутствие вызовов wrapper, нормальная очередь Zabbix, отсутствие новых unsupported items и неизменный read-only снимок Ceph.

Ограничения вывода

Наблюдение подтверждает только то, что Ceph сообщил в конкретный момент и что сборщик смог корректно разобрать. Отсутствие текущего health warning не доказывает, что каждый объект недавно прошёл deep-scrub. Просрочка относительно настроенной policy не равна повреждению данных, а завершившийся scrub не заменяет резервное копирование или проверку восстановления. Имена полей, health checks, команды представления, параметры расписания и доступность отметок по PG различаются между выпусками Ceph и интеграцией Proxmox VE; до внедрения я сверяю документацию и фактический вывод установленной версии. Окна задают разрешённое время старта, но фактическое выполнение зависит от нагрузки, состояния PG, флагов и очереди. Универсального безопасного интервала, процента просроченных PG или срока восстановления нет. Zabbix не определяет физическую причину ошибки согласованности, не доказывает исправность носителя и не должен автоматически запускать scrub, deep-scrub, repair, перезапуск или удаление объектов.

Источники

  1. Ceph documentation: Placement Group scrubbing
  2. Ceph documentation: health checks
  3. Ceph documentation: monitoring a cluster
  4. Proxmox VE documentation: Ceph
  5. Zabbix documentation: user parameters
  6. Zabbix documentation: dependent items