Все уроки
DevOps и облакоСредний12 мин чтенияВ моём стеке

Мониторинг, алертинг и бэкапы

Узнавайте о проблеме раньше пользователей и умейте откатить самый худший день.

  • Prometheus
  • Grafana
  • Loki
  • Uptime
  • Backups & restores
Шаг 1/5
Каждую ночь в 02:00, пока все спят, база делает backup и отправляет копию на NAS.

За 30 секунд

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

Почему я это использую

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

Как это работает

01Метрики, логи и трейсы: три взгляда на одну систему

Метрики — это числа во времени: запросы в секунду, доля ошибок, время ответа, CPU, свободное место на диске, длина очереди. Их дёшево хранить, они идеальны для дашбордов и алертов, но говорят, что что-то не так, а не что именно. Логи — события с отметкой времени и подробностями: вот этот запрос, этот пользователь, это исключение и стектрейс. Они отвечают, что случилось, но искать по ним в больших объёмах дорого, поэтому пишите их в JSON с единообразными полями. Трейсы прослеживают один запрос через сервисы: вызов API, запросы к базе, обращение к платёжному провайдеру — каждый со своей длительностью, так что видно, куда ушло время. OpenTelemetry — вендор-нейтральный стандарт для всех трёх. Начните с метрик и логов; трейсинг добавляйте, когда у вас несколько сервисов общаются друг с другом.

  • Метрики: всё ли в порядке? (агрегированные числа)
  • Логи: что именно произошло? (отдельные события)
  • Трейсы: на что этот запрос потратил время? (один запрос, много переходов)

02Prometheus, Grafana и Loki

Prometheus — база временных рядов, которая каждые несколько секунд забирает (scrape) метрики по HTTP с целевых сервисов. Exporter'ы отдают метрики того, что вы не писали сами: node_exporter — CPU, память и диск, postgres_exporter — базу данных, а ваше приложение может отдавать собственный эндпоинт /metrics. Запросы пишутся на PromQL, там же задаются правила алертов; затем Alertmanager группирует, дедуплицирует и направляет эти алерты в почту, Slack или на пейджер. Grafana рисует дашборды поверх Prometheus и многих других источников. Loki дёшево хранит логи, индексируя только метки вроде app, environment и level, а не весь текст, а Grafana Alloy — это сборщик, который отправляет в него логи и метрики. Вместе они дают self-hosted стек, который спокойно работает рядом с приложением на Docker Compose.

yaml
groups:
  - name: host
    rules:
      - alert: DiskAlmostFull
        expr: node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} < 0.15
        for: 15m
        labels: { severity: warning }
        annotations:
          summary: "Less than 15% disk left on {{ $labels.instance }}"
      - alert: HighErrorRate
        expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.05
        for: 10m
        labels: { severity: critical }

03Проверки доступности, трекинг ошибок и алерты без спама

Uptime-проверка стучится на ваш сайт снаружи каждую минуту, как это сделал бы пользователь: отдаёт ли главная 200, действителен ли TLS-сертификат ещё хотя бы две недели, подтверждает ли health-эндпоинт, что база отвечает. Инструменты вроде Uptime Kuma можно хостить самому; облачные сервисы проверяют из нескольких регионов. Трекинг ошибок (Sentry для веба и бэкенда, Firebase Crashlytics для мобильных) группирует исключения и падения, показывает стектрейс, релиз и затронутых пользователей. Что касается алертов: будите человека только из-за симптомов, которые чувствуют пользователи (сайт лежит, много ошибок, не работает оформление заказа), а причины вроде высокой загрузки CPU отправляйте на дашборд или в низкоприоритетный канал. Требуйте, чтобы условие держалось несколько минут, прежде чем срабатывать, группируйте связанные алерты, и пусть каждый алерт ведёт на runbook с объяснением, что проверить в первую очередь.

  • Алертите по симптомам, расследуйте причины.
  • По каждому вызову должно быть понятно, что делать; если действовать никому не нужно, это не повод будить.
  • Раз в месяц пересматривайте шумные алерты и удаляйте или донастраивайте их.

04Бэкапы: правило 3-2-1, снапшоты и настоящие бэкапы

Правило 3-2-1: держите три копии данных на двух разных типах носителей, причём одну — вне площадки. Современное расширение добавляет одну неизменяемую или офлайн-копию, чтобы её не могли удалить ни ransomware, ни украденный админский ключ, и ноль ошибок после проверенного восстановления. Снапшот провайдера копирует весь диск на определённый момент. Из него быстро восстановить сервер целиком, но обычно он живёт в том же аккаунте провайдера, а снапшот работающей базы может оказаться неконсистентным. Настоящий бэкап — это консистентная копия на уровне приложения, например вывод pg_dump или mysqldump плюс загруженные файлы, хранящаяся в другом месте и зашифрованная. Используйте оба: снапшоты — для быстрого восстановления сервера целиком, логические бэкапы — для точного и переносимого восстановления данных.

bash
#!/usr/bin/env bash
set -euo pipefail
STAMP=$(date +%F_%H%M)
pg_dump -Fc -U app appdb > /backups/appdb_$STAMP.dump
 
# encrypted, deduplicated, off-site copy (S3-compatible storage)
export RESTIC_REPOSITORY=s3:https://s3.example.com/your-backup-bucket
restic backup /backups /var/www/app/shared/storage
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check

05Проверка восстановления, RPO и RTO

Стратегию бэкапов определяют два числа, и их нужно согласовать с бизнесом, а не угадывать силами инженеров. RPO (recovery point objective) — сколько данных вы можете позволить себе потерять, в единицах времени: с ночными дампами RPO — до 24 часов, с непрерывным архивированием WAL или отправкой binlog'ов — минуты. RTO (recovery time objective) — сколько вы можете простаивать, пока идёт восстановление. А затем докажите, что укладываетесь в них. По расписанию восстанавливайте последний бэкап во временную базу или на временный сервер, выполняйте несколько проверочных запросов, убеждайтесь, что загруженные файлы открываются, и засекайте время всего процесса. Запишите шаги в runbook, чтобы любой в команде смог сделать это в стрессовой ситуации.

bash
# monthly restore drill into a throwaway database
createdb restore_test
pg_restore --no-owner -d restore_test /backups/appdb_latest.dump
psql -d restore_test -c "SELECT count(*), max(created_at) FROM orders;"
dropdb restore_test

Когда применять

  • С первого дня всего, что работает в продакшене: как минимум uptime-проверки, трекинг ошибок и автоматические бэкапы вне площадки.
  • Полноценные стеки метрик и логов — как только у вас свои серверы или несколько сервисов.
  • Трейсинг — когда запросы проходят через несколько сервисов или очередей и трудно найти, где тормозит.
  • Учения по восстановлению — перед любой крупной миграцией и регулярно после неё.

Когда не стоит

  • Self-hosted стек Prometheus и Loki для одного маленького сайта — хватит облачной uptime-проверки и трекера ошибок.
  • Алерты-вызовы на каждый всплеск метрики: большинству сигналов место на дашборде, а не в чьём-то телефоне.
  • Полагаться только на снапшоты, хранящиеся в том же аккаунте, что и сервер.

Альтернативы

  • Облачная observability (Grafana Cloud, Datadog, New Relic)

    Никаких своих серверов, быстрее начать; стоимость растёт с объёмом данных.

  • Uptime Kuma или алерты провайдера

    Простые алерты по доступности, диску или нагрузке для небольших конфигураций.

  • Sentry / Crashlytics

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

  • Управляемые бэкапы баз данных

    Point-in-time recovery на стороне провайдера; всё равно проверяйте восстановление и держите внешнюю копию.

Лучшие практики

  1. Следите за четырьмя золотыми сигналами: задержка, трафик, ошибки и насыщение.
  2. Пишите структурированные JSON-логи с request ID, который проходит через каждый сервис и задачу.
  3. Будите людей только из-за симптомов, видимых пользователям; к каждому алерту прикладывайте ссылку на runbook.
  4. Соблюдайте 3-2-1, причём хотя бы одна копия неизменяемая или в отдельном аккаунте, и шифруйте бэкапы.
  5. Бэкапьте загруженные файлы и конфигурацию, а не только базу.
  6. Планируйте учения по восстановлению, засекайте время и сравнивайте с согласованными RPO и RTO.
  7. Алертите, когда задача бэкапа упала или не запускалась, а не только когда сайт лежит.

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

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

Глубже

06SLI, SLO, error budget и алерты по burn rate

Индикатор уровня сервиса (SLI) — это измеряемая доля хороших событий среди всех событий, например доля запросов, на которые успешно ответили быстрее чем за 500 мс. Цель уровня сервиса (SLO) — целевое значение для него на окне времени, скажем 99,9% за 30 дней. Оставшиеся 0,1% — это error budget: примерно 43 минуты полного простоя в месяц или более долгий период частичных ошибок. Вместо алерта на фиксированный процент ошибок алертите по тому, как быстро сгорает бюджет. Burn rate 1 расходует ровно весь бюджет за 30 дней; burn rate 14,4, продержавшийся час, съедает 2% месячного бюджета и заслуживает пейджа. Паттерн multiwindow из SRE workbook от Google проверяет длинное окно, чтобы убедиться, что проблема реальна, и короткое — чтобы убедиться, что она всё ещё происходит. Так алерты быстро срабатывают и быстро гаснут.

yaml
# page: 2% of a 30-day 99.9% budget burned in 1 hour
- alert: ErrorBudgetFastBurn
  expr: |
    (sum(rate(http_requests_total{status=~"5.."}[1h])) / sum(rate(http_requests_total[1h])) > 14.4 * 0.001)
    and
    (sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 14.4 * 0.001)
  labels: { severity: page }
  annotations: { runbook: "https://wiki.example.com/runbooks/error-budget" }

07Внутренности Prometheus: серии, кардинальность и гистограммы

Prometheus хранит отдельный временной ряд для каждой уникальной комбинации имени метрики и значений лейблов. http_requests_total с лейблами method, route и status может дать несколько сотен серий — это нормально. Добавьте лейбл user_id или полный URL, и вы получите по серии на каждого пользователя или каждый URL: память взрывается, запросы ползут. Это и есть проблема кардинальности, самый частый способ сломать Prometheus. Держите лейблы в небольших ограниченных наборах, а детали с высокой кардинальностью отправляйте в логи или трейсы. Для латентности используйте гистограммы: приложение раскладывает запросы по бакетам, а histogram_quantile оценивает p95 или p99 в момент запроса по всем инстансам. Средние значения прячут медленный хвост, который пользователи как раз и чувствуют. Тяжёлые запросы из дашбордов и алертов стоит превратить в recording rules, которые считаются один раз за интервал. По умолчанию Prometheus хранит 15 дней; долгосрочное хранение обычно уходит в Thanos, Mimir или облачный бэкенд через remote_write.

yaml
# p95 latency per route over 5 minutes
histogram_quantile(0.95,
  sum by (le, route) (rate(http_request_duration_seconds_bucket[5m])))
 
# recording rule: compute once, reuse in dashboards and alerts
- record: route:http_request_duration_seconds:p95_5m
  expr: histogram_quantile(0.95, sum by (le, route) (rate(http_request_duration_seconds_bucket[5m])))
 
# find the metrics with the most series
topk(10, count by (__name__) ({__name__=~".+"}))

08Point-in-time recovery для PostgreSQL

Ночной дамп даёт RPO до суток. Point-in-time recovery (PITR) сокращает его до минут. PostgreSQL записывает каждое изменение в журнал предзаписи (WAL) до того, как применить его. Если у вас есть периодический base backup — физическая копия каталога данных — плюс каждый сегмент WAL с того момента, можно восстановить base backup и проиграть WAL до любого момента, например за минуту до того, как кто-то выполнил DELETE без WHERE. Включается это через archive_mode и команду архивации, которая отправляет каждый завершённый сегмент за пределы сервера. На практике берите специализированный инструмент вроде pgBackRest или WAL-G: они сами занимаются сжатием, шифрованием, ретеншеном, параллельным восстановлением и проверкой и складывают всё в объектное хранилище. Восстановление: разложите base backup, задайте recovery_target_time и создайте файл recovery.signal. Управляемые базы дают то же самое одной кнопкой, но репетировать всё равно нужно.

bash
# postgresql.conf (with pgBackRest)
wal_level = replica
archive_mode = on
archive_command = 'pgbackrest --stanza=app archive-push %p'
archive_timeout = 60          # ship at least once a minute
 
# restore to just before the mistake
pgbackrest --stanza=app --type=time \
  --target="2026-11-05 14:31:00+00" --target-action=promote restore

09Защита самих бэкапов

Современный ransomware и злонамеренные инсайдеры первым делом бьют по бэкапам, так что исходите из того, что атакующий с учётными данными сервера попытается их удалить. Три защиты работают вместе. Раздельные учётные данные: сервер должен уметь добавлять новые бэкапы, но не удалять старые. У rest-server от restic есть режим append-only, а объектное хранилище позволяет выдать право на запись без права на удаление. Неизменяемость: S3 Object Lock (его предлагают и некоторые S3-совместимые провайдеры) хранит объекты в режиме write-once на время ретеншена; в режиме compliance никто, даже root аккаунта, не может его сократить. Независимый мониторинг: dead man's switch ждёт пинг после каждого успешного бэкапа и алертит, если пинга нет, — так ловятся тихо сломавшиеся cron-задачи. Ключ или пароль шифрования храните отдельно от сервера, например в менеджере паролей: зашифрованный бэкап без ключа — просто шум.

bash
# bucket must have versioning; lock new objects for 30 days
aws s3api put-object-lock-configuration --bucket example-backups \
  --object-lock-configuration '{"ObjectLockEnabled":"Enabled","Rule":{"DefaultRetention":{"Mode":"COMPLIANCE","Days":30}}}'
 
# end of backup script: report success to a dead man's switch
restic backup /backups && curl -fsS -m 10 --retry 3 https://hc-ping.example.com/your-check-id

Реальные ситуации

01

Пользователи говорят, что сайт тормозит, но ни один алерт не сработал

Проблема

В обед поддержка получает жалобы на медленные страницы. Дашборды показывают нормальный CPU и среднее время ответа 180 мс, а за всю неделю не сработал ни один алерт.

Как решить

Средние прячут хвост, поэтому смотрите на перцентили. Постройте латентность p95 и p99 по каждому роуту из гистограммы длительности запросов: обычно один-два роута тормозят для части пользователей. Дальше проверьте насыщение: заполненность пула соединений к базе, slow query log, бэклог очереди и число воркеров в обеденное время. Если задействовано несколько сервисов, откройте трейс медленного запроса и посмотрите, какой span доминирует. Устраните причину — часто это отсутствующий индекс или N+1-запрос, который бьёт только в пик. Затем добавьте SLO по латентности p95 для ключевых роутов с алертом по burn rate, чтобы следующее замедление разбудило дежурного раньше, чем о нём услышит поддержка.

02

В 14:32 таблицу случайно опустошили

Проблема

Скрипт обслуживания выполнил DELETE без нужного фильтра на продакшен-таблице. Приложение продолжает работать, но сотни клиентов потеряли свои записи, а новые заказы продолжают поступать.

Как решить

Не восстанавливайте поверх продакшена — вы потеряете все заказы, записанные с тех пор. С PITR восстановите последний base backup плюс WAL на отдельный сервер с recovery target 14:31, за минуту до ошибки. Если есть только ночной дамп, восстановите его во временную базу. Затем верните только удалённые строки, например через COPY недостающих ID или INSERT ... SELECT через временный foreign data wrapper, проверяя внешние ключи. Пока работаете, сообщайте статус заинтересованным людям. После инцидента добавьте защиту: скрипты выполняются в транзакции с проверкой числа строк, а опасные операции требуют ревью.

03

Команда получает 200 алертов в неделю и игнорирует их

Проблема

Канал алертов замьючен у большей части команды. Реальное падение в прошлом месяце заметили на сорок минут позже, потому что его алерт утонул среди предупреждений о скачках CPU.

Как решить

Выгрузите историю алертов за месяц и отсортируйте по количеству и по тому, реагировал ли кто-нибудь. Удалите алерты, которые ни разу не привели к действию, а алерты по причинам, вроде CPU или памяти, перенесите на дашборды или в ежедневный дайджест. Пейджите только по симптомам, которые видит пользователь: доступность, сгорание error budget, SLO по латентности, упавшие бэкапы. Добавьте for: длительности, чтобы короткие скачки не срабатывали, группируйте связанные алерты в Alertmanager и используйте inhibition, чтобы алерт о недоступном хосте подавлял двадцать алертов, которые он вызывает. У каждого оставшегося алерта должен быть владелец и ссылка на runbook. Пересматривайте список раз в месяц; разумная цель — несколько полезных пейджей в неделю.

Шпаргалка

Проверить правила алертов и recording rules
promtool check rules alerts.yml
Заглушить алерт на время обслуживания
amtool silence add alertname=DiskAlmostFull --duration=2h --comment="disk resize"
Латентность p95 (PromQL)
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
Доля ошибок (PromQL)
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))
Ошибки в логах (LogQL)
sum by (app) (count_over_time({env="prod"} |= "ERROR" [5m]))
Восстановить дамп параллельно
pg_restore -j 4 --no-owner -d restore_test appdb.dump
Список снапшотов restic и восстановление
restic snapshots && restic restore latest --target /tmp/restore
Найти, что забивает диск
du -xh / --max-depth=2 2>/dev/null | sort -h | tail -20
Ужать журнал systemd
journalctl --vacuum-size=500M
Проверить срок действия TLS снаружи
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate

В моих реальных проектах

  • На сервере POS SaaS работает стек observability из Prometheus, Grafana и Loki в виде override-файла Compose, с health check'ами, runbook'ами и скриптами бэкапа.
  • Приложения на React Native отправляют падения через Firebase Crashlytics.
  • Мой базовый набор для серверов включает снапшоты плюс проверенное восстановление и мониторинг диска, нагрузки и доступности через Uptime Kuma или алерты провайдера; бэкапы вне площадки — часть моего текущего плана консолидации.
  • Я почистил один продакшен-сервер с примерно 91% занятого диска до примерно 66%, удалив старые логи, старые сборки и раздутые node_modules.

Вопросы и ответы

Q1Чем отличаются метрики, логи и трейсы?

Метрики — числовые временные ряды: частота запросов, доля ошибок, перцентили задержки, свободное место на диске. Они дешёвые, легко агрегируются и идеальны для дашбордов и алертов, но теряют индивидуальные детали. Логи — отдельные события с контекстом, например один упавший запрос с его пользователем, входными данными и стектрейсом; они объясняют, что произошло, но их дорого хранить и искать. Трейсы прослеживают один запрос через сервисы и показывают каждый шаг с его временем — так в распределённой системе находят, откуда берётся задержка. На практике я алерчу по метрикам, а затем, чтобы найти причину, использую логи и трейсы, связанные request ID.

Q2На что бы вы настроили алерты для веб-приложения?

Будят меня симптомы, которые чувствуют пользователи: сайт или API не проходят внешние uptime-проверки, доля ошибок устойчиво выше порога, задержка сильно выше нормы, ломается критичный сценарий вроде оформления заказа или логина, у TLS-сертификата подходит срок. С меньшим приоритетом я алерчу и на то, что станет падением, если это игнорировать: заполняется диск, растёт хвост очереди, бэкапы упали или не запускались. Всплески CPU сами по себе идут на дашборды. Каждому алерту нужно окно длительности, чтобы он не «моргал», маршрутизация к нужному человеку и ссылка на runbook. Если алерт сработал, а делать никому ничего не нужно, я его удаляю или донастраиваю.

Q3Объясните RPO и RTO.

RPO (recovery point objective) — максимальный объём потери данных, который бизнес готов принять, выраженный во времени. Если бэкапы делаются раз в ночь, можно потерять до суток заказов, значит RPO — 24 часа. Непрерывная отправка логов или реплики сокращают его до минут. RTO (recovery time objective) — максимально допустимый простой на время восстановления. Восстановление, которое занимает шесть часов, не уложится в RTO в один час. И то и другое — бизнес-решения с ценником: меньшие числа требуют реплик, point-in-time recovery и автоматизации. Задача инженера — сделать компромисс понятным, реализовать его и доказать учениями по восстановлению с замером времени.

Q4Достаточно ли снапшотов сервера в качестве бэкапа?

Нет, это полезный слой, но не полная стратегия. Снапшот обычно живёт у того же провайдера и часто в том же аккаунте, так что взломанный аккаунт, проблема с оплатой или инцидент у провайдера могут унести и сервер, и его снапшоты. Снапшот работающей базы может быть неконсистентным, если база не рассчитана на восстановление после сбоя и вы это не проверили. Кроме того, из снапшота трудно восстановить одну таблицу или данные одного клиента. Я комбинирую их с логическими дампами базы и бэкапами файлов — зашифрованными и скопированными вне площадки в отдельное хранилище, с правилами хранения и регулярной проверкой восстановления.

Q5Что такое правило бэкапов 3-2-1?

Держите минимум три копии данных: рабочую и два бэкапа. Храните их на двух разных типах носителей, например на диске сервера и в объектном хранилище, чтобы один тип сбоя не уничтожил всё. Одну копию держите вне площадки — у другого провайдера, в другом регионе или аккаунте. Более новый вариант, 3-2-1-1-0, добавляет одну неизменяемую или офлайн-копию, которую нельзя удалить даже с админскими правами (это защищает от ransomware), и ноль ошибок — то есть бэкапы проверены реальным восстановлением. Для типичного веб-приложения это дампы базы плюс загруженные файлы, зашифрованные, с версионированием или object lock на удалённом бакете.

Q6Как понять, что ваши бэкапы действительно работают?

Регулярно восстанавливаться из них, а не проверять, что файлы существуют. Я слежу, чтобы каждая задача бэкапа завершилась и выдала файл правдоподобного размера, и алерчу, если она не запустилась. Затем по расписанию восстанавливаю последний бэкап в изолированную базу или на временный сервер, делаю проверки вроде количества строк и самых свежих таймстемпов в ключевых таблицах, открываю несколько загруженных файлов и фиксирую, сколько всё это заняло. Это время сравнивается с RTO. Шаги лежат в runbook'е, чтобы восстановление не зависело от того, вспомнит ли один конкретный человек команды посреди инцидента.

Вопросы уровня senior

S1Как бы вы определили SLO и алертинг для нового сервиса?

Начинаю с пользовательских сценариев, а не с инфраструктуры. Для интернет-магазина это может быть просмотр каталога, добавление в корзину и оплата. Для каждого выбираю SLI, которые отражают опыт пользователя: обычно доступность (ответы не 5xx) и латентность (доля запросов быстрее порога), измеренные как можно ближе к пользователю — на балансировщике или синтетическими проверками. Цели согласую с бизнесом, исходя из того, что нужно пользователям и чего система достигает сегодня; 99,9% — частый выбор, и каждая лишняя девятка стоит заметно дороже. Затем алертю по burn rate error budget с multiwindow-правилами: быстрое сгорание — пейдж, медленное — тикет. Бюджет публикую и договариваюсь о политике на случай его исчерпания, например о паузе рискованных релизов. Через квартал реальных данных пересматриваю цели.

S2Pull или push для метрик: в чём компромиссы?

В pull-модели, которую использует Prometheus, сервер по расписанию опрашивает каждый таргет. Это даёт бесплатный сигнал здоровья (неудачный scrape значит, что таргет упал или недоступен), централизованный контроль частоты опроса и простую отладку — /metrics можно открыть в браузере. Но нужны service discovery и сетевой доступ от сервера мониторинга к каждому таргету, что неудобно через файрволы и для короткоживущих задач. В push-модели, как в StatsD, OTLP-экспортерах OpenTelemetry и у многих облачных вендоров, клиенты сами отправляют данные в коллектор. Это хорошо подходит для serverless-функций, batch-задач и edge-устройств, но молчащий клиент неотличим от простаивающего, а сбойный клиент может завалить бэкенд. Многие сетапы смешивают оба подхода: долгоживущие сервисы скрейпят, а задачи пушат через коллектор или Pushgateway.

S3Репликация, снапшоты, бэкапы: почему реплика — не бэкап?

Реплика копирует каждое изменение primary за секунды, и именно в этом проблема: DELETE без WHERE, неудачная миграция или шифрование ransomware реплицируются так же исправно, как и хорошие данные. Реплики защищают от отказа железа и дают быстрый failover, улучшая RTO, но не позволяют вернуться в прошлое. Бэкап — это отдельная историческая копия, которую можно восстановить на более ранний момент, в идеале с PITR, хранящаяся независимо и защищённая от удаления. Снапшоты где-то посередине: это срез на момент времени, но обычно в том же аккаунте и у того же провайдера. Грамотная схема использует все три для разных отказов: реплики для доступности, снапшоты для быстрого восстановления всего сервера и внешние неизменяемые логические или физические бэкапы против потери данных — с проверкой через учения по восстановлению.

S4Объём логов и их стоимость взлетели. Как взять это под контроль?

Сначала измеряю: какие сервисы и какие строки логов дают больше всего байт. Обычно доминируют несколько шумных источников: забытый debug-уровень, access-логи health check или стек-трейсы, повторяющиеся на каждом ретрае. Это исправляется у источника правильными уровнями и логированием с rate limit. Затем делю данные на уровни: полные логи держу несколько дней в быстром хранилище, объёмные и малоценные логи, вроде успешных запросов, агрегирую или сэмплирую, а то, чего требует compliance, архивирую в дешёвое объектное хранилище. Повторяющиеся вопросы, на которые отвечают грепом по логам, превращаю в метрики — они намного дешевле. В Loki держу лейблы с низкой кардинальностью и фильтрую по содержимому во время запроса. Компромисс — возможности расследования: агрессивное сэмплирование может спрятать тот самый нужный запрос, поэтому ошибки и медленные запросы всегда сохраняю без сэмплирования.

Глоссарий

SLI
Service level indicator: измеряемая доля хороших событий среди всех, например быстрых успешных запросов.
SLO
Service level objective: цель для SLI на окне времени, например 99,9% за 30 дней.
Error budget
Допустимый по SLO объём сбоев; когда он исчерпан, работа над надёжностью важнее новых фич.
Burn rate
Насколько быстро расходуется error budget по сравнению с равномерным расходом на всё окно.
Кардинальность
Число уникальных комбинаций лейблов, а значит и временных рядов, которые порождает метрика.
Exporter
Небольшая программа, которая читает статистику системы, например базы или хоста, и отдаёт её Prometheus.
Recording rule
PromQL-выражение, которое Prometheus вычисляет по расписанию и сохраняет как новую серию, ускоряя дашборды.
WAL
Write-ahead log: последовательный журнал всех изменений базы для восстановления после сбоя, репликации и PITR.
PITR
Point-in-time recovery: восстановление базы на любой выбранный момент проигрыванием журналов поверх base backup.
Dead man's switch
Монитор, который алертит, когда ожидаемый сигнал перестаёт приходить, например пинг об успешном бэкапе.

Есть идея продукта?Давайте создадим его.

Расскажите о своей идее, продукте или команде. Обычно отвечаю в течение одного рабочего дня.