Сколько хранить логи и как не разориться на хранилище
Логи копятся быстрее, чем кажется: сегодня 500 МБ в день, через полгода это уже терабайт, за который вы платите каждый месяц — а смотрели вы в них последний раз три месяца назад. Вопрос «сколько хранить логи» не имеет единого правильного ответа, но есть рабочая методика, которая позволяет держать баланс между реальной пользой логов и реальными деньгами за диск. Разберём её по шагам.
Содержание
Почему «хранить всё вечно» — плохая стратегия по умолчанию
Интуитивно кажется, что чем больше логов сохранено, тем лучше: вдруг понадобятся. Проблема в том, что затраты на хранение логов растут линейно (а часто быстрее — если объём трафика или число сервисов увеличивается), а практическая польза от логов старше определённого возраста падает почти до нуля.
Возьмём типичную картину: сервер пишет 2-3 ГБ логов в сутки (nginx access, приложение, systemd journal, аудит). Без ротации и без ограничения срока хранения это:
- за месяц — 60-90 ГБ;
- за год — 700 ГБ - 1 ТБ;
- за три года — несколько терабайт, которые лежат на SSD-разделе и ничем не отличаются от логов недельной давности с точки зрения того, как вы их храните.
При этом если честно посмотреть на статистику обращений к логам (через access-time файлов или просто вспомнить, когда вы в последний раз открывали лог годичной давности), окажется, что подавляющее большинство логов старше 30-90 дней никто и никогда не открывает повторно. Их держат «на всякий случай», а платят за это каждый месяц вне зависимости от того, наступит ли этот случай вообще.
Отсюда фундаментальный компромисс, вокруг которого строится вся статья: логи нужны для диагностики (иногда проблема обнаруживается не сразу, а спустя недели или месяцы — и тогда нужны именно старые логи) и в некоторых случаях обязательны для аудита или соответствия регуляторным требованиям на конкретный минимальный срок. Но бессрочное хранение всех логов в неизменном полном объёме означает постоянно растущие расходы без соразмерного роста практической пользы. Задача — не выбрать одну из крайностей, а построить политику, которая покрывает реальные сценарии использования логов и не более того.
Если хотите разобраться, во что вообще превращается диск без всякой политики хранения, у нас есть отдельный разбор: логи заняли 300 ГБ, и никто их не читал — типичная история сервера, где ротацию один раз настроили и забыли.
Уровень 1: разным типам логов — разный срок хранения
Первая и самая важная идея: не все логи одинаково ценны, и не стоит применять к ним одну и ту же политику хранения. Практика показывает разумное деление на несколько категорий.
Ошибки и критичные события (5xx в access-логе, exception-трейсы, CRITICAL/ERROR в journal, срабатывания алертов) — стоит хранить дольше, обычно от 90 дней до года. Причина простая: проблема, которая вызвала ошибку, иногда всплывает как баг-репорт от клиента или как повторяющийся паттерн только спустя месяцы, и тогда единственный способ понять «а было ли это раньше и когда началось» — поднять историю ошибок.
Подробные debug и info-логи обычных успешных операций — на другом полюсе. Строка вида INFO: request processed in 42ms, user_id=1234 практически никогда не понадобится, если запрос отработал без ошибок. Такие логи нужны в первые часы-дни после события (пока идёт активная отладка чего-то смежного), а дальше их ценность падает почти до нуля. Разумный срок — 7-14 дней.
Access-логи веб-сервера — золотая середина: полезны для анализа трафика, разбора инцидентов безопасности, статистики. Обычно достаточно 30-90 дней в полном виде, дальше — агрегированная статистика (если она вообще нужна), а не сырые строки.
Логи, подпадающие под регуляторные требования (об этом подробнее ниже) — здесь срок диктует не удобство, а закон или договор, и его нужно соблюдать отдельно от «инженерной» политики.
Пример конфига logrotate с разным сроком для разных категорий:
# /etc/logrotate.d/myapp
/var/log/myapp/error.log {
daily
rotate 180
compress
delaycompress
missingok
notifempty
}
/var/log/myapp/debug.log {
daily
rotate 10
compress
missingok
notifempty
}
/var/log/nginx/access.log {
daily
rotate 60
compress
delaycompress
missingok
notifempty
sharedscripts
postrotate
systemctl reload nginx > /dev/null 2>&1 || true
endscript
}
Обратите внимание на rotate 180 для error.log против rotate 10 для debug.log — это ровно та дифференциация, о которой речь. Если у вас логи пишутся в journald, аналогичное деление делается через SystemMaxUse= и отдельные vacuum-политики по unit'ам, либо через разные приложения-получатели в syslog/Loki с разными retention-правилами.
Если ротацию логов вы вообще ещё не настраивали, начните с базовой статьи — ротация логов, чтобы не забивался диск — а уже поверх неё стройте дифференцированные сроки, о которых мы говорим здесь.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать VPSУровень 2: сжатие старых логов
Даже логи, которые вы решили хранить долго, не обязаны занимать место в исходном текстовом виде. Текстовые логи (JSON, plain text, CSV) сжимаются очень хорошо — типичный коэффициент сжатия gzip на логах 5-10x, потому что там много повторяющихся строк, полей и шаблонов.
Идея простая: логи младше нескольких дней держим несжатыми (к ним обращаются часто, grep и tail -f должны работать мгновенно), а логи старше этого порога сжимаем — вы платите чуть большим временем доступа при редком обращении, но экономите ощутимо на дисковом пространстве.
logrotate делает это из коробки через compress и delaycompress (последний откладывает сжатие на один цикл ротации, чтобы не сжимать файл, в который приложение ещё может дописывать через уже открытый файловый дескриптор):
compress
delaycompress
compresscmd /usr/bin/zstd
compressext .zst
uncompresscmd /usr/bin/unzstd
Если логов много и gzip через logrotate уже недостаточно быстр, стоит присмотреться к zstd — он сжимает и разжимает заметно быстрее при сравнимой степени сжатия, что важно, если вам иногда всё же приходится грепать архив на несколько гигабайт.
Практический ориентир (не измеренное число, а именно ориентир — на вашем железе и вашем типе логов цифры будут другими): для типичных текстовых access-логов и логов приложений сжатие уменьшает объём в разы, для уже структурированных бинарных форматов (например, журналов баз данных) выигрыш обычно меньше — там стоит проверить на своих данных, прежде чем закладывать экономию в расчёт бюджета.
Уровень 3: многоуровневое хранение — горячее и холодное
Третий рычаг — не только сжимать старые логи, но и физически перемещать их на более дешёвое хранилище. Логика та же, что при выборе диска под свежие данные и архив: недавние логи, к которым обращаются часто и от которых требуется быстрый поиск, держим на быстром (и, соответственно, более дорогом) хранилище — обычно это SSD/NVMe раздел на самом сервере или на VPS с быстрым диском. Логи старше определённого возраста, которые нужны крайне редко, переносим на более дешёвое, но более медленное хранилище — HDD-раздел, отдельный сервер для архивов или объектное хранилище (S3-совместимое).
Этот же принцип детально разобран применительно к архивам бэкапов в статье холодное хранение архивов — он полностью переносится и на архивные логи: экономия достигается именно за счёт того, что для «холодных» данных вы сознательно жертвуете скоростью доступа ради цены за гигабайт.
Практическая схема на VPS:
# перенос логов старше 30 дней на отдельный "холодный" раздел
find /var/log/myapp -name "*.log.*.gz" -mtime +30 -exec mv {} /mnt/cold-storage/logs/ \;
Или, если инфраструктура крупнее и логи агрегируются через Graylog / Grafana Loki, там есть штатные retention-политики с несколькими storage-классами: например, в Loki это retention_period на уровне tenant'а плюс настройка компакции индексов, а в Graylog — index rotation strategies и возможность выгружать старые индексы в архив перед удалением. Если вы ещё выбираете между этими двумя системами именно с точки зрения стоимости хранения логов, у нас есть сравнение — Graylog или Grafana Loki: что выгоднее и когда.
Важный нюанс: перенос логов на холодное хранилище имеет смысл только если у вас действительно бывают редкие, но реальные случаи, когда старые логи нужны. Если такого не бывает практически никогда — возможно, дешевле не хранить холодный архив вообще, а просто удалять логи по истечении срока (уровень 4 ниже).
Уровень 4: явная и автоматизированная политика удаления
Здесь чаще всего случается главная ошибка: даже если сроки хранения определены на бумаге, без автоматизации они не соблюдаются. «Раз в квартал зайти и почистить логи вручную» — план, который работает ровно до первого отпуска, смены ответственного сотрудника или просто загруженного месяца. Через год на диске снова накопится всё то же самое, что и без всякой политики.
Правило простое: срок хранения должен быть закодирован в конфигурации, а не в памяти человека. Практические варианты:
- logrotate с параметром
rotate N— самый базовый и надёжный способ для локальных логов, встроен почти во все дистрибутивы, запускается через cron/systemd timer автоматически. - journald —
SystemMaxUse=,MaxRetentionSec=в/etc/systemd/journald.confограничивают и объём, и возраст записей в systemd journal. - cron-задача с
find ... -mtime +N -delete— годится для нестандартных путей логов, которые не покрыты logrotate:
# /etc/cron.d/purge-old-logs
0 3 * * * root find /var/log/myapp/archive -name "*.gz" -mtime +365 -delete
- Retention-политики в централизованных системах логирования (Graylog index retention, Loki
retention_period, Elasticsearch ILM) — если логи агрегируются, срок хранения настраивается один раз на уровне индекса/потока, и дальше система сама удаляет данные без ручного вмешательства.
Отдельно стоит держать мониторинг того, что политика реально работает: алерт на случай, если диск с логами вдруг снова начал расти быстрее ожидаемого — потому что ротация могла сломаться (например, приложение держит старый файловый дескриптор открытым после ротации и продолжает писать в удалённый inode, не освобождая место). Это довольно частая грабля, разобранная в статье про антипаттерн: логи без ротации.
Как определить срок для своего конкретного случая
Универсального «правильного» числа дней не существует — есть три вопроса, ответы на которые для вашей ситуации и дают конкретный срок.
(а) Как быстро в вашей практике обычно обнаруживаются проблемы, требующие логов задним числом? Если у вас были случаи, когда баг или инцидент безопасности всплывал через несколько недель после события и для разбора нужны были именно логи за этот период — ориентируйтесь на этот реальный опыт, а не на абстрактный «а вдруг». Если таких случаев не было ни разу за всё время работы проекта — вероятно, вы закладываете избыточный запас.
(б) Какие регуляторные требования применимы к вашей отрасли? Для ряда сфер (финансы, персональные данные, некоторые виды B2B-договоров) минимальный срок хранения определённых логов задаётся не инженерным здравым смыслом, а законом или регламентом — и здесь нельзя полагаться на общие предположения из статей в интернете, включая эту. Требования различаются по юрисдикции, типу данных и отрасли, регулярно меняются, и правильный источник ответа — юрист или комплаенс-специалист, знакомый именно с вашей регулируемой сферой. О том, что вообще может требоваться хранить и в каком объёме именно с точки зрения закона (без привязки к конкретной юрисдикции — только принцип), можно почитать в статье что хранить в логах по закону, но финальное решение по срокам для вашего случая всё равно должен подтвердить юрист.
(в) Сколько реально стоит хранение при выбранном сроке относительно вашего бюджета? Здесь считаем не абстрактно, а конкретно: объём логов в день × выбранный срок × цена за гигабайт вашего хранилища (с поправкой на сжатие и многоуровневость из разделов выше). Если получившаяся сумма несущественна на фоне остальных расходов на инфраструктуру — можно позволить себе более длинный срок «на всякий случай». Если счёт за хранилище логов начинает конкурировать по величине со счётом за сам сервер — это сигнал пересмотреть политику: сократить срок для debug-логов, добавить сжатие, перенести архив на более дешёвый диск.
Ни один из этих трёх пунктов сам по себе не даёт ответа — решение находится на их пересечении. Осознанный выбор конкретного срока под вашу ситуацию — это и есть цель, а бездумные крайности («храним всё всегда» или «удаляем всё как можно скорее») одинаково плохи: первая душит бюджет без реальной пользы, вторая рискует оставить вас без данных именно тогда, когда они понадобятся.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать VPSНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
С чего начать, если сейчас логи вообще не удаляются?
Сначала измерьте текущий объём и скорость роста (du -sh /var/log/*, посмотреть за неделю разницу), затем внедрите базовую ротацию с разумными сроками по категориям из раздела выше, и только потом при необходимости добавляйте сжатие и многоуровневое хранение — не усложняйте архитектуру раньше, чем убедитесь, что базовая ротация уже решает проблему.
Нужно ли хранить логи бэкапов так же долго, как сами бэкапы?
Не обязательно и это разные сущности с разной логикой хранения — у бэкапов свой критерий (сколько точек восстановления вам нужно), у логов свой (диагностика и аудит). Если интересна ротация именно бэкапов, у нас есть отдельный разбор — сколько хранить бэкапы и какая ротация.
Можно ли просто удалять логи по мере заполнения диска, без фиксированного срока?
Это работает как аварийный клапан, но не как политика: удаление «когда припрёт» непредсказуемо (можно потерять свежие логи ошибок, если что-то другое неожиданно раздуло диск) и не решает исходную задачу — контролировать затраты заранее. Лучше сочетать: явный срок хранения по расписанию плюс алерт на случай, если место всё равно заканчивается быстрее ожидаемого.
Что делать с логами Docker-контейнеров — они растут отдельно от системных логов?
Да, у Docker свой драйвер логирования, и настройки logrotate для /var/log его не затрагивают — нужно отдельно ограничивать log-opts (max-size, max-file) в /etc/docker/daemon.json или в конфиге конкретного контейнера. Подробно разобрано в статье Docker съел весь диск логами.
Стоит ли хранить старые логи в объектном хранилище (S3) вместо локального диска?
Для действительно холодного архива — да, это часто выгоднее по цене за гигабайт, чем держать растущий локальный диск на самом сервере. Но добавляет сложность (отдельный процесс выгрузки, зависимость от внешнего сервиса, время на скачивание при редком обращении) — оправдано, если объём архива уже ощутимый, и не оправдано для небольшого проекта, где хватит второго дешёвого диска на том же сервере.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →