Перейти к содержанию

Контроль целостности

Страница для инженера эксплуатации: как запросить проверку кластера («Проверить и исправить»), как прочитать её результат по областям, что делать с повреждёнными полосами и как приостановить фоновый контроль целостности. Что делают сами фоновые процессы и как они ограничивают нагрузку, объясняет раздел «Контроль целостности» страницы «Фоновые процессы».

Обычно вмешиваться не нужно: недостающие фрагменты кластер перестраивает сам. Запрос проверки нужен после события, которое кластер не может обнаружить сам: отказа нескольких дисков одновременно, отключения питания, извлечения дисков вручную.

Как обнаруживаются и исправляются повреждения

Что случилось Как обнаруживается Как исправляется
Отказ диска диск не удаётся открыть сменой состава группы: на месте диска оказывается новый участник, а группа размещения получает новую эпоху, которая закрывает доступ старому
Повреждение данных контрольная сумма не совпадает владелец группы перестраивает по k сохранившимся фрагментам тот фрагмент, которого нет или который читается под чужим ключом
Запись не дошла до участника запись остаётся в очереди ресинхронизации так же: фрагмент перестраивает владелец группы

Восстановление читает все сохранившиеся фрагменты, а не только первые k. Поэтому результат проверяется по избыточным фрагментам, и повреждённый фрагмент среди сохранившихся обнаруживается. Полоса, которую не удалось привести в порядок, вносится в реестр повреждённых полос.

Перестроение фрагментов процессами resync, resync_queue и scrub не меняет порядка проверки групп: группа проверяется в свой срок, и перестроенный фрагмент сверяется с чётностью при следующей проверке группы.

Где смотреть состояние:

Запрос проверки

Чтобы проверить и исправить кластер, администратору достаточно одного действия: запроса проверки.

Условия:

Порядок действий:

  1. Отправьте запрос POST /v2/repair или нажмите кнопку «Проверить и исправить» в разделе консоли «Контроль целостности»:

    curl -u ivanov -X POST https://console.example.net/s3gateway/api/v2/repair
    
  2. Следите за ходом запроса и состоянием областей, пока поле finished запроса не станет равным true:

    curl -u ivanov https://console.example.net/s3gateway/api/v2/repair
    
  3. Проверьте поле skipped запроса и области со статусом warning или error (см. «Состояние по областям»). Подробности по области данных:

    curl -u ivanov https://console.example.net/s3gateway/api/v2/repair/data
    

Отменить запрос или заменить его новым нельзя.

Ответы на POST /v2/repair

Код Когда
202 запрос записан; тело содержит его в том же виде, что поле request ответа GET /v2/repair. Если предыдущий запрос ещё не завершён, ответ содержит его, а новые сканирования не начинаются
403 запрос отправлен с ролью s3r_observer
409 код RepairPaused: фоновый контроль целостности приостановлен, сначала его нужно возобновить
503 код ClusterNew: начальное формирование кластера не завершено

Что запускает запрос

Запрос записывается в таблицу s3r_cluster. После этого:

  • мастер каждого репликасета выполняет сканирование каталога (процесс catalog) по строкам своего репликасета;
  • владелец каждой группы размещения выполняет сверку позиций блоков группы с каталогом (процесс reconcile);
  • владелец каждой группы сканирует её заново и сравнивает всех участников во всех позициях блоков (процесс resync); идущее сканирование при этом прерывается.

Запрос проверки не делает следующего:

  • не запускает проверку целостности данных. Процесс scrub идёт по периоду своего яруса (scrub_period_s), а возраст самой давней проверки каждого яруса показывает область data;
  • не восстанавливает размещение групп (см. «Группы не на своих позициях»);
  • не переформатирует диски, не признаёт их вышедшими из строя и не удаляет их (см. Действия с дисками).

Что из этого требуется, видно по областям ответа GET /v2/repair. Выполняется это отдельными действиями API управления.

Идентификатор запроса

Запрос получает идентификатор (request_id, в таблице s3r_cluster столбец repair_request_id): UUID версии 7, который записывается вместе с запросом и отличает его от других запросов. Он содержит время создания, поэтому по журналам видно, какой запрос был раньше. Идентификаторы сравниваются только на равенство, потому что часы на разных инстансах не обязаны идти монотонно.

Когда запрос завершён

Запрос завершён (finished: true), когда закончились все сканирования, которые он запустил: сканирование каталога у мастера каждого репликасета, сверка позиций блоков и ресинхронизация у владельца каждой группы.

  • Сканирование засчитывается и тогда, когда оно не удалось. Например, ресинхронизация группы с утраченной полосой завершает свою часть запроса, а утраченная полоса остаётся в реестре повреждённых полос и в области data.
  • Засчитываются только сканирования, начатые после записи запроса: каждое сканирование запоминает идентификатор запроса при начале. Время на часах инстансов для этого не используется.
  • Инстанс, перезапущенный во время запроса, снова читает идентификатор запроса из s3r_cluster и выполняет свои сканирования заново.

Что запрос не смог проверить

Запрос ждёт только те инстансы, которые Picodata считает доступными (Online). Что запрос не смог проверить, перечисляет поле skipped, по одной записи на область:

Запись Что означает
offline инстанс, который Picodata считает недоступным (Offline), на момент запроса или с какого-то момента во время него
orphaned группа, у которой нет владельца и которую не может принять ни один инстанс
paused область, сканирования которой не закончились к моменту приостановки фонового контроля целостности

Инстанс, который снова стал доступен, выполняет сканирования по текущему запросу, и следующий запрос проверки его учитывает.

Состояние по областям

GET /v2/repair доступен ролям s3r_superuser и s3r_observer. Ответ содержит:

  • режим фонового контроля целостности: mode, mode_changed_by, mode_changed_at;
  • последний запрос проверки: request; значение null, если проверку ни разу не запрашивали;
  • состояние четырёх областей в поле areas.

Каждая область описывает весь кластер, а не только инстанс, который ответил. Ход запроса ответ узнаёт у каждого доступного владельца групп.

Область Что учитывается Подробности
catalog недостающие директории, которые последнее сканирование каталога нашло и не смогло перестроить (directories_missing), и неудачные сканирования (failed) GET /v2/repair/catalog: расписание и последнее сканирование каждого репликасета
data группы, ожидающие ресинхронизации (needs_resync_groups), строки очереди ресинхронизации (resync_queue), рассогласованные (inconsistent_stripes) и утраченные (lost_stripes) полосы, а также время окончания самой давней проверки целостности данных (oldest_scrub_at) и период scrub_period_s того яруса, который сильнее остальных отстал от своего периода; те же значения для каждого яруса перечислены в поле scrub_tiers GET /v2/repair/data: группы, ожидающие ресинхронизации, и повреждённые полосы с объектами, не больше ста на тенанта
disks диски в каждом состоянии, кроме active; поля blank, foreign, corrupt, failed и draining присутствуют всегда GET /v2/repair/disks: каждый такой диск и подходящее действие: reformat, remove или wait
groups группы деградированные (degraded), утраченные (lost), с переносом данных, ждущим места (drain_waiting), меняющие владельца (transferring), без владельца (orphaned) и не на своих позициях (asymmetric) GET /v2/repair/groups: каждая такая группа и её состояние; у несимметричной группы reform: true

Роль s3r_observer не видит ключ объекта в ответе GET /v2/repair/data: вместо ключа возвращается null.

Деградированные и утраченные группы

  • Деградированной считается группа, у которой уцелевших участников меньше, чем фрагментов в полосе, но не меньше k.
  • Утраченной считается группа, у которой уцелевших участников меньше k.
  • Уцелевшим считается участник, чей диск не удалён, не вышел из строя и не переформатирован, если участник не находится в состоянии new и у него нет отстающих экстентов из списка extents_behind.

Участник, поставленный на замену, хранит только записи, сделанные после его постановки в группу, пока процесс resync не проверит его отстающие экстенты. Такого участника не заменяют, он ждёт ресинхронизации. Утраченная группа тоже может ждать замены участника на вышедшем из строя диске.

Так же группы считают строка placement ответа GET /v2/health и метрики s3r_pg_degraded и s3r_pg_lost.

Важность элементов

У каждого элемента, который перечисляют маршруты областей и GET /v2/repair/catalog, есть важность в поле severity. Элементы с важностью error и warning требуют вмешательства администратора, а fixing означает, что кластер исправит это сам.

Важность В консоли Элементы
error неисправно вышедший из строя (failed) или повреждённый (corrupt) диск; деградированная группа, которую нечем исправить: ни один диск, отвечающий правилам размещения, не может принять её утраченного участника; утраченная группа; группа без владельца; утраченная полоса; рассогласованная полоса; неудачное сканирование каталога
warning неоптимально несимметричная группа; группа, участника которой на выводимом диске не может принять ни один диск; пустой (blank) или чужой (foreign) диск, ожидающий переформатирования; самая давняя проверка целостности данных яруса старше его периода scrub_period_s; всё, что иначе получило бы оценку fixing, пока фоновый контроль целостности приостановлен
fixing исправляется группа, ожидающая ресинхронизации; группа, меняющая владельца; деградированная группа, участника которой можно заменить или участник которой ждёт ресинхронизации; диск, который переводится в обслуживание или ещё подключается; недостающие директории, найденные сканированием каталога; строка очереди ресинхронизации. В области data эту оценку получают группы, ожидающие ресинхронизации, и строки очереди ресинхронизации

Группа, которая ещё не закончила ни одной проверки целостности данных, предупреждения о сроке проверки не вызывает, но и не скрывает его: ярус, в котором просрочена проверка другой группы, считается отставшим.

Поля области

Поле Что содержит
status наивысшая важность элементов области: ok (ничего не найдено), fixing, checking (сканирование, запущенное последним запросом, на доступном инстансе ещё не закончилось), warning или error. Важность checking выше fixing и ниже warning
errors, warnings число элементов области с важностью error и warning
checked_at когда закончилось самое давнее из последних сканирований области; служит только для отображения. Для областей disks и groups сканирования нет: они показывают состояние на момент ответа

Сводка для консоли

Число элементов с важностью error и warning во всех четырёх областях возвращают поля repair_errors и repair_warnings ответа GET /v2/cluster/attention. Их сумму консоль показывает значком у раздела «Контроль целостности»: красным, если есть хотя бы одна ошибка, и жёлтым в остальных случаях. Значения хранятся в кеше десять секунд, поэтому запросы к инстансам при каждом обращении не отправляются.

Если состояние не удалось подсчитать

Ответ 500 не означает, что повреждений нет

Если подсчёт не удался, GET /v2/repair возвращает код 500, а не нулевые значения: нулевое значение означало бы, что повреждений нет, хотя их никто не подсчитал.

Повреждённые полосы и объекты, ожидающие копирования на другую площадку, подсчитываются распределённым SQL-запросом ко всем репликасетам. Если хотя бы один репликасет не ответил:

  • GET /v2/repair, GET /v2/repair/data и GET /v2/cluster/attention возвращают код 500;
  • ошибка хранится в кеше те же десять секунд;
  • в журнал выводится строка the damage and replication counts could not be read from every replicaset;
  • консоль показывает у раздела «Контроль целостности» красный значок «!». Если запрос отклонён или не дошёл до сервера, значок не показывается.

Так же обрабатывается ошибка чтения таблиц, по которым считаются области: сканирований каталога, дисков, отметок проверки целостности данных, владельцев групп и таблиц размещения. GET /v2/repair, GET /v2/repair/data, GET /v2/repair/groups и GET /v2/cluster/attention тогда возвращают код 500, а не нулевые значения.

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

Реестр повреждённых полос

Полоса, которую не удалось привести в порядок, вносится в реестр повреждённых полос s3r_t<N>_damage своего тенанта вместе с объектом, которому принадлежит.

-- Реестр повреждённых полос тенанта 0: объект, полоса, вид записи и причина
SELECT parent, "name", stripe_no, pg_id, kind, detail, detected_at
  FROM s3r_t0_damage;

Вид записи указан в столбце kind.

Утраченная полоса (lost) — данные объекта потеряны

Чтение такого объекта возвращает 404 NoSuchKey. HeadObject строит ответ только по метаданным объекта, поэтому для объекта, данные которого уже нельзя прочитать, он может вернуть 200, тогда как GetObject возвращает 404.

Рассогласованную полосу (inconsistent) фоновые процессы не исправят

Администратору нужно сравнить объект с копией клиента или с его контрольной суммой и записать объект заново: перезапись исключает полосу из реестра.

kind Что произошло Кто делает запись Что дальше
lost, утраченная полоса все участники группы ответили, а сохранившихся фрагментов недостаточно для восстановления полосы процессы resync, scrub и владелец группы, перестраивающий фрагменты по строкам очереди ресинхронизации запись хранит сведения об утраченных данных и остаётся в реестре, пока на полосу ссылается строка объекта
inconsistent, рассогласованная полоса все фрагменты полосы на месте, но проверка целостности нашла расхождение между копиями или между данными и чётностью и не смогла определить повреждённый фрагмент, поэтому полоса не перестраивается процесс scrub запись получает важность error. Полосу исключает из реестра перезапись объекта. Если очередное сканирование прочитает все фрагменты полосы и они совпадут, проверка тоже исключит полосу из реестра

Фрагмент, который проверка может назвать повреждённым, она перестраивает сразу и в реестр не вносит.

Если запись в реестр не удалась

Если запись в реестр не удалась, например мастер репликасета объекта ответил ошибкой или не ответил вовремя, процесс scrub останавливает проверку группы перед этой полосой и на следующем шаге повторяет запись. До успешной записи scrubbed_at группы не сдвигается, а другие группы того же владельца не проверяются. Утраченную полосу, запись которой не удалась, процесс resync запишет при следующем сканировании группы.

Когда запись исключается из реестра

Записи обоих видов исключаются из реестра в той же транзакции, в которой строка объекта перестаёт ссылаться на свои полосы. Это происходит:

  • при удалении объекта или одной его версии;
  • при перезаписи объекта: ключ остаётся, а записи о прежних данных исключаются;
  • при очистке удалённого бакета процессом bucketgc;
  • при переходе объекта в класс хранения другого яруса, когда данные переписываются на диски этого яруса;
  • при замене собственных данных объекта ссылкой на общую копию.

Запись остаётся в реестре в следующих случаях:

  • переход в класс того же яруса только меняет метку класса и записи не затрагивает;
  • в бакете с версионированием маркер удаления не освобождает полос, поэтому записи о версиях под ним остаются;
  • полосы, общие для нескольких объектов после дедупликации, принадлежат общей копии: их записи живут столько же, сколько сама копия, и исключаются при её удалении вместе с последней ссылкой на неё.

Ход проверки целостности данных

Проверку целостности данных выполняет процесс scrub владельца группы. Её ход и итоги хранятся в двух таблицах.

-- Группы, их эпохи и владельцы: перестраивает фрагменты владелец группы
SELECT pg_id, tier, epoch, owner FROM s3r_pg ORDER BY pg_id;

-- Последняя полная проверка целостности каждой группы и итоги завершённых
-- проверок. `scrubbed_at` сдвигается, когда проверена каждая полоса группы,
-- то есть по завершении сканирования
SELECT pg_id, scrubbed_at, stripes_checked, stripes_inconsistent,
       damage_recorded FROM s3r_scrub_pg ORDER BY pg_id;

-- Идущие сканирования: место в каталоге, с которого прочитана текущая страница
-- (`live_set_cursor`), последняя проверенная на ней полоса и найденное с начала
-- сканирования. Владелец записывает строку раз в 64 шага
SELECT pg_id, owner_uuid, live_set_cursor, resume_object, resume_stripe,
       stripes_checked, stripes_inconsistent, damage_recorded
  FROM s3r_scrub_pg_cursor ORDER BY pg_id;
Таблица Что хранит
s3r_scrub_pg итоги завершённых проверок. Счётчики увеличиваются по завершении сканирования группы
s3r_scrub_pg_cursor строку хода сканирования: найденное до завершения. Строка удаляется по завершении сканирования и при удалении группы

Таблица s3r_scrub_pg_cursor шардирована по номеру группы. Перезапущенный владелец находит строку, даже если перебалансировка перенесла её в другой репликасет, и продолжает сканирование с записанного в ней места. Строка обновляется раз в 64 шага (константа), поэтому после перезапуска повторно проверяется не больше 64 шагов, то есть не больше 64 000 полос. Поля resume_object и resume_stripe пусты, пока на текущей странице не проверена ни одна полоса.

Приостановка фонового контроля целостности

Приостановка нужна администратору, который разбирается с одновременным отказом нескольких дисков или сохраняет состояние кластера для последующего разбора.

Приостановка действует на весь кластер и сохраняется после перезапуска

Пока она действует, проверка целостности данных, ресинхронизация и сканирование каталога не выполняются, а запрос проверки и запрос восстановления размещения отклоняются с ответом 409.

Режим хранит поле repair_mode строки s3r_cluster: running (фоновый контроль целостности работает) или paused (приостановлен). Его переключает запрос PUT /v2/repair/mode с ролью s3r_superuser или переключатель «Фоновый контроль целостности» в консоли:

curl -u ivanov -X PUT https://console.example.net/s3gateway/api/v2/repair/mode \
  -H 'content-type: application/json' -d '{"mode": "paused"}'

Значение running возобновляет фоновый контроль целостности.

Во время приостановки Процессы
Не выполняются проверка целостности данных (scrub); ресинхронизация (resync); сканирование каталога (catalog)
Продолжают работать запись и чтение; сборка мусора: процессы chunkgc, extentgc, dirgc, bucketgc и mpugc; сверка позиций блоков (reconcile)

Сверка позиций блоков строит вид смонтированной группы. Без построенного вида группа не выделяет позиций блоков, поэтому приостановка сверки остановила бы запись.

Что ещё меняется:

  • Состояние областей по-прежнему вычисляется, и все запросы на чтение отвечают.
  • Приостановка во время идущего запроса проверки действует сразу и завершает запрос: каждая область, сканирования которой не закончились, перечисляется в поле skipped как paused.
  • Метрика s3r_repair_paused равна 1.
  • Оповещение S3rScrubBehind из deploy/prometheus/s3r-alerts.yml не срабатывает: проверку целостности данных остановил администратор, и это не отказ. После возобновления проверка, период которой превышен, снова вызывает оповещение.

Запуск и приостановка фоновых процессов вручную

Диагностические эндпоинты инстанса позволяют выполнить шаг процесса сразу и приостановить процесс на этом инстансе. Полный перечень эндпоинтов — в разделе Диагностические эндпоинты.

Немедленный шаг. Один шаг процесса выполняется обращением к /-/debug/run/<имя>:

# Применить правила жизненного цикла сейчас
curl -s --cacert /etc/s3r/ca.pem "https://node1.example.net:8443/-/debug/run/lifecycle"

# Применить их так, как если бы наступило заданное время (секунды с начала эпохи Unix)
curl -s --cacert /etc/s3r/ca.pem "https://node1.example.net:8443/-/debug/run/lifecycle?as_of=1800000000"

# Вернуть в вид владельца позиции блоков удалённых объектов
curl -s --cacert /etc/s3r/ca.pem "https://node1.example.net:8443/-/debug/run/reconcile"
curl -s --cacert /etc/s3r/ca.pem "https://node1.example.net:8443/-/debug/run/extentgc"

Параметр as_of процесса lifecycle задаёт момент в секундах с начала эпохи Unix (unix time), на который вычисляются сроки. Правило со сроком в тридцать дней так можно проверить сразу, не переводя системное время.

Шаг scrub, запущенный этим способом, начинает с группы, которую не проверяли дольше остальных, даже если срок её проверки ещё не подошёл.

Приостановка на инстансе. Процесс приостанавливает обращение к /-/debug/hold/<имя>, возобновляет — к /-/debug/release/<имя>. Это поддерживается для процессов bucketgc, dirgc, siterepl, resync, resync_queue, reconcile, group, scrub, tenant, transition и dedup. Приостановка действует только на этом инстансе и до его перезапуска. Она позволяет, например, отложить ресинхронизацию на время испытаний под клиентской нагрузкой.

Приостановка во всём кластере. Фоновый контроль целостности во всём кластере приостанавливает repair_mode (см. Приостановка контроля целостности).

Расписание сверки каталога

Процесс catalog запускается сам с периодом, который по умолчанию равен 336 часам (двум неделям).

  • Период меняет запрос PUT /v2/repair/catalog с телом {"every_hours": N}. Значение 0 отключает запуск по расписанию; другие допустимые значения лежат в пределах от 24 до 8760 часов.
  • Внеочередное сканирование запускает запрос проверки POST /v2/repair (см. Запрос проверки). Он нужен после события, которое кластер не может обнаружить сам: отказа нескольких дисков одновременно, отключения питания, извлечения дисков вручную.
  • Результат последнего сканирования каждого репликасета возвращает GET /v2/repair/catalog. Мастер каждого репликасета записывает результат своего сканирования в отдельную строку таблицы s3r_catalog_pass, и результаты разных репликасетов друг друга не заменяют.