Ceph: Настройка scrub и снижение его влияния на производительность

Обычно не пишу о том, что и так известно почти всем или если это хорошо освещено. Но недавно в одном популярном русскоязычном telegram-чате посвященном Ceph обсуждалась проблема scrubbing’а и я понял, что все таки знаю кое что, что еще не известно всем) Решил написать заметку посвященную данной теме.

Scrub — служебный механизм призванный проверять целостность копий данных в кластере RADOS. Процесс scrubbing’а идет фоном и циклически перебирает все данные сравнивая одну копию данных на одной OSD с другой копией на другой(или других) OSD.
Проверок бывает два типа: простая(scrubbing) и глубокая(scrubbing+deep)
В рамках простой проверки сверяются только атрибуты фалов и их размер, этот тип проверки безобиден и практически ни оказывает никакого влияния на работу кластера и по этому проводится с частотой в сутки.
При глубокой проверке(scrubbing+deep) проверяемые данные считываются с дисков, считается их контрольная сума и сверяется. Собственно чтение данных и есть проблема. Такие проверки идут с интервалом в неделю.
Естественно проверки не запускаются разом на все данные. В таком случае все вставало бы колом) Разные PG проверяются в разное время. Этот процесс идет не прерывно, сейчас одни проверяются, затем другие а через время опять первые и так без конца.

Так вот когда в кластере появляется нормальное количество данных и они активно используются то вы заметите влияние scrubbing’а даже без мониторинга)

Под нормальным объемом данных я подразумеваю не какой то общий объем данных в кластере а заполненность используемых дисков. Например если у вас диски размером в 2Tb и они заполнены на 50-60 или более процентов то у вас много данных в Ceph, даже если дисков всего шесть). Это моя субъективная метрика но по моему 3-х летнему опыту работы с Ceph в проде — это самый важный критерий.
Собственно когда наши диски достигли такой утилизации мы стали замечать просадки производительности и повышенные задержки во время идущего scrubbing’а. Возможно если бы у нас были SSD мы жили бы счастливо но у нас обычные SATA диски с журналами на SSD.

Так вот, scrubbing. Когда во время идущего скраббинга приходит пользовательская нагрузка на те же OSD что в процессе скраббирга, не заметить это сложно, особенно если у вас есть внешний мониторинг.

Изменение расписания scrubbing’а

Первое что можно сделать это задать расписание для scrubbing’а, отведя для него время где нибудь ночью, например с 00.00-08.00.

Задать в ceph.conf:

[osd]
    osd scrub begin hour = 0
    osd scrub end hour = 8
    ...

Задать в рантайме(без рестарта OSD):

ceph tell osd.* injectargs '--osd_scrub_begin_hour 0'
ceph tell osd.* injectargs '--osd_scrub_end_hour 8'

Это сразу изменит ситуацию к лучшему но не надолго. Опять же если у вас много данных то они просто не будут успевать проходить scarbbing в отведенное время. Если какие то PG не успеют пройти scrubbing за 7 дней то он будет запущен принудительно в любое время. Так мы увидели идущий скраббинг в дневное время). Увеличивать установленное время без скраббинга нельзя т.к. он очень важен для сохранности данных. Так мы кстати еще раз получили подтверждение, что у нас много данных.

Раз скраббинг все же идет в итоге в дневное время и мешает нормальной работе сервиса то ничего не остается как искать пусти его ограничения.

Снижение приоритета с помощью CFQ

Самая популярная рекомендация, она же является официальной: https://ceph.com/geen-categorie/ceph-reduce-osd-scrub-priority/

Необходимо сменить планировщик у всех OSD-дисков на CFQ:

cat /sys/block/sda/queue/scheduler
noop [deadline] cfq

echo cfq > /sys/block/sda/queue/scheduler

и установить следующие параметры для всех OSD:

Задать в ceph.conf:

[osd]
    osd disk thread ioprio class = idle
    osd disk thread ioprio priority = 7
    ...

Задать в рантайме(без рестарта OSD):

ceph tell osd.* injectargs '--osd-disk-thread-ioprio-class idle'
ceph tell osd.* injectargs '--osd-disk-thread-ioprio-priority 7'

Этот подход используют очень многие и кому то он помогает. Нам он не помог практически ни как. Мы довольно долго его тестировали но периодические просадки производительности и взлет летенси никуда не делись.

Уменьшение порции данных одного scrubbing’а

Это то ради чего написана эта заметка. Я нигде не видел статей или обсуждений на эту тему, но это то что избавило нас от проблем связанных со скраббингом.

Суть в том, что бы позволить scrubbing’у идти круглые сутки но читать данные очень мелкими порциями максимально снижая нагрузку на OSD в момент времени.

Задать в ceph.conf:

[osd]
   osd scrub sleep = .2
   osd scrub chunk min 1 # default - 5
   osd scrub chunk max 2 # default - 25
  ...

Задать в рантайме(без рестарта OSD):

ceph tell osd.* injectargs '--osd_scrub_sleep .2'
ceph tell osd.* injectargs '--osd-scrub-chunk-min 1'
ceph tell osd.* injectargs '--osd-scrub-chunk-max 2'

С этими параметрами вы будете видеть больше активных скрабов в выводе ceph -s но каждый из них будет минимально влиять на OSD на которой он идет.

При использовании этого подхода, на мой взгляд лучше сменить планировщик на deadline.

Данный подход представлен в этой статье как один из вариантов и возможно для вас окажется не таким эффективным как для нас. В общем попробуйте и решите сами.