Производительность и масштаб

Что ломается, когда логов становятся терабайты в день, и как держать стек в форме.

Масштабирование логирования — приведение пропускной способности и хранилища ELK в соответствие с объёмом логов так, чтобы поиск оставался быстрым, а стоимость — приемлемой.

Главная переменная — объём

Логи коварны: один сервис в DEBUG может генерировать гигабайты в час, а сотня сервисов — терабайты в день. Объём определяет всё: сколько нужно узлов, дисков, памяти, денег. Поэтому первый вопрос масштабирования — сколько данных в секунду мы реально пишем (events/sec и GB/day). Без этой цифры планировать кластер невозможно.

Размер шарда — ключевой параметр

Каждый индекс делится на шарды, и размер шарда сильно влияет на производительность. Слишком много мелких шардов — накладные расходы на каждый (память, метаданные кластера) убивают производительность; слишком крупные — медленное восстановление и перемещение. Практическое правило для логов: держать шард в диапазоне 10–50 ГБ. Именно поэтому в rollover мы задавали max_size: 50gb — чтобы шард не вырастал за разумный предел.

  ПЛОХО: тысячи шардов по 100 МБ  --> кластер задыхается на метаданных
  ПЛОХО: один шард на 500 ГБ      --> медленный recovery, нельзя распараллелить
  ХОРОШО: шарды по 10-50 ГБ       --> баланс

Реплики: надёжность против стоимости

Реплика — копия шарда на другом узле. number_of_replicas: 1 означает: каждый шард существует в двух экземплярах, переживёт падение узла и удваивает мощность чтения. Но это и удвоение объёма хранения. Для горячих важных логов реплика нужна; для холодных архивных её часто убирают (replicas: 0) ради экономии — потеря узла там не катастрофа.

Горизонтальное масштабирование и роли узлов

ELK масштабируется добавлением узлов. При больших объёмах узлы специализируют по ролям: ingest-узлы крутят пайплайны обработки, data hot на быстрых SSD принимают запись, data warm/cold на дешёвых дисках хранят старое (из урока про ILM), master-узлы координируют кластер. Разделение ролей не даёт тяжёлой записи мешать поиску и наоборот.

Как работает под капотом: запись против поиска

Запись логов и поиск конкурируют за ресурсы. Индексация — это построение инвертированного индекса (нагрузка на CPU и диск), поиск — обход этого индекса и агрегации (нагрузка на CPU и память). При пиковом потоке логов агрессивная индексация может «придушить» поисковые запросы дежурного. Приёмы балансировки: увеличить refresh_interval (как часто новые логи становятся видны для поиска — для логов 30s вместо дефолтной 1s резко снижает нагрузку записи), вынести тяжёлую обработку на ingest-узлы, и не держать на горячих узлах ничего, кроме свежих данных.

Контроль стоимости

Самый дешёвый байт — тот, который вы не записали. Перед масштабированием железа спросите: точно ли нужен этот DEBUG в проде? Нужны ли health-check'и в индексе (помните drop)? Можно ли семплировать слишком частые события? Грамотная фильтрация на входе экономит больше, чем любой апгрейд кластера.

Планирование ёмкости

Прежде чем разворачивать кластер, делают грубый расчёт ёмкости, и он начинается с объёма. Оцените средний размер события (часто от половины до двух килобайт для структурированного лога) и пиковый поток событий в секунду — их произведение даёт пропускную способность в байтах, которую кластер должен переваривать. Умножьте дневной объём на срок хранения и на коэффициент реплик — получите требуемый объём диска. Эти прикидки приблизительны, но они отделяют «у нас будет кластер из трёх узлов» от «нам нужно двадцать узлов и пересмотр сроков хранения». Кластер, спроектированный без оценки объёма, либо не справляется с потоком в первый же пик, либо переплачивает за простаивающее железо.

Отдельно планируют запас на пики и рост. Логи коварны тем, что их объём нелинейно скачет: при инциденте, когда логи нужнее всего, их поток обычно резко возрастает (сервисы массово пишут ошибки и стектрейсы) — ровно в худший момент. Кластер, рассчитанный впритык под средний поток, захлёбывается именно во время аварии. Поэтому закладывают запас по индексации и буфер (Kafka) перед хранилищем, который сгладит всплеск. Планировать логирование по средней нагрузке — всё равно что строить мост под средний, а не максимальный вес.

Частые ошибки

  • Шардов слишком много. «Over-sharding» — самая частая болезнь кластеров логов: тысячи мелких шардов кладут master-узел. Считайте размер шарда.
  • refresh_interval по умолчанию. Для логов видимость через 1 секунду не нужна; дефолт зря тратит ресурсы записи. Поднимайте интервал.
  • Масштабировать железо вместо фильтрации. Докупать узлы, продолжая лить мусорные DEBUG-логи, — дорого и бесконечно. Сначала сократите объём на входе.

Итоги

  • Объём (events/sec, GB/day) — главная переменная; с неё начинается планирование кластера.
  • Размер шарда держат в районе 10–50 ГБ; over-sharding убивает кластер.
  • Реплики дают надёжность ценой удвоения хранения; на холодных данных их часто убирают.
  • Балансируйте запись и поиск (refresh_interval, роли узлов); дешевле всего — не писать лишнее.
Проверьте себя
1. Какой ориентировочный размер шарда считается здоровым для логов в Elasticsearch?
A100–200 МБ
B10–50 ГБ
C500 ГБ и больше
DРазмер не имеет значения
2. Почему для логов часто увеличивают refresh_interval (например, с 1s до 30s)?
AЧтобы логи быстрее искались
BЛогам не нужна видимость через секунду, а больший интервал заметно снижает нагрузку на запись
CЭто требование лицензии
DЧтобы включить ILM
3. Какой самый дешёвый способ справиться с растущим объёмом логов?
AДокупать узлы кластера
BНе записывать лишнее: фильтровать DEBUG, health-check'и и семплировать частые события на входе
CУвеличить число реплик
DУменьшить размер шарда до минимума