8(800) 222 32 56
Панель управления
Решения для бизнеса

Runbook для сервера: какие инструкции должны быть у команды на случай аварии

Runbook для сервера: какие инструкции должны быть у команды на случай аварии
Подберите идеальное решение для ваших задач:
в России, США и Нидерландах обеспечат максимальную скорость. Воспользуйтесь всеми преимуществами надежного оборудования. Базовая помощь и техническое обслуживание входят в пакет услуг.

Сайт не отвечает. Диск заполнен на 100%. В рабочий репозиторий случайно попал приватный ключ. Приложение теряет соединение с базой данных, а дежурный инженер пытается понять, что из этого причина, а что — уже следствие.

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

Именно в этот момент нужен runbook — заранее подготовленная инструкция, которая помогает не вспоминать инфраструктуру по кусочкам, а последовательно пройти путь от первого сигнала до полного восстановления сервиса.


Готовы перейти на современную серверную инфраструктуру?

В King Servers мы предлагаем серверы как на AMD EPYC, так и на Intel Xeon, с гибкими конфигурациями под любые задачи — от виртуализации и веб-хостинга до S3-хранилищ и кластеров хранения данных.

  • S3-совместимое хранилище для резервных копий
  • Панель управления, API, масштабируемость
  • Поддержку 24/7 и помощь в выборе конфигурации

Создайте аккаунт

Быстрая регистрация для доступа к инфраструктуре


Что такое runbook и почему он не должен быть формальностью

Runbook помогает действовать по шагам во время аварии

Runbook — это пошаговый операционный сценарий для конкретной ситуации. Он отвечает не на абстрактный вопрос «как устроен наш сервер», а на вполне практический: «что именно должен сделать дежурный инженер, когда произошло определённое событие».

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

С серверной инфраструктурой происходит то же самое.

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

Порядок действий при инциденте
1. Зафиксировать симптомы
2. Определить масштаб аварии
3. Остановить потенциально опасные изменения
4. Собрать минимальную диагностику
5. Выбрать безопасное временное решение
6. Проверить восстановление глазами пользователя
7. Зафиксировать действия и передать информацию команде

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

Runbook, playbook и план аварийного восстановления — не одно и то же

Эти документы часто смешивают, хотя задачи у них разные.

Runbook описывает конкретную операцию: что делать, если заполнен диск, не отвечает Nginx или истёк TLS-сертификат.

Playbook охватывает более широкий сценарий и может объединять несколько runbook. Например, playbook «Компрометация инфраструктуры» будет включать инструкции по отзыву ключей, изоляции узлов, анализу журналов и оповещению ответственных.

План аварийного восстановления, или Disaster Recovery Plan, объясняет, как вернуть бизнес-системы после серьёзного отказа: потери основного сервера, повреждения хранилища, отказа площадки или масштабной кибератаки.

Проще говоря, DR-план показывает маршрут до запасного аэродрома, а runbook объясняет, какие переключатели и в какой последовательности нужно нажать.

Runbook vs playbook vs DR

Конкретная операция: диск, Nginx, TLS, 5xx.
Широкий сценарий из нескольких runbook.
Восстановление после крупного отказа площадки или данных.

Что должно быть в каждом серверном runbook

Структура серверного runbook

Рабочая инструкция начинается не с команд Linux. Сначала она должна дать дежурному инженеру контекст.

Название и область применения

Название должно описывать наблюдаемый симптом, а не предполагаемую причину.

Именование runbook по симптому
Плохой вариант:
  Исправление ошибки Nginx

Хороший вариант:
  Сайт не отвечает или возвращает большое количество ответов 502/503

Во втором случае инструкция остаётся полезной, даже если проблема оказалась не в Nginx, а в приложении, базе данных или сетевом соединении.

Условия запуска

Нужно прямо указать, при каких сигналах открывается runbook

• внешний мониторинг не может загрузить сайт

• доля ответов 5xx превысила установленный порог

• свободное место на разделе стало меньше 10%

• появились ошибки No space left on device

• приложение не может подключиться к базе данных

секрет обнаружен в Git, журнале, тикете или публичном канале.

Это помогает не запускать тяжёлую аварийную процедуру из-за единичного ложного срабатывания.

Ожидаемое влияние

Инженер должен быстро понять, насколько серьёзна ситуация:

• недоступен весь сервис или одна функция

• проблема касается всех клиентов или отдельного региона

• нарушено только чтение или также запись

• есть ли риск потери данных

продолжается ли активное повреждение системы.

Например, заполненный на 92% архивный раздел и заполненный на 100% раздел с базой данных — два совершенно разных уровня срочности.

Ответственные роли

Даже в небольшой команде полезно разделить четыре функции

• координатор инцидента принимает решения и следит за общей картиной

• технический исполнитель проводит диагностику и меняет систему

• ответственный за коммуникацию обновляет коллег, поддержку и руководство

секретарь инцидента фиксирует время, команды, гипотезы и результаты.

В команде из двух человек некоторые роли можно объединить. Но должно быть понятно, кто принимает финальное решение и кто имеет право выполнять изменения в production.

Необходимые доступы

В runbook следует перечислить

• адреса серверов и понятные имена узлов

• способ подключения через SSH, VPN или bastion host

• расположение панели управления инфраструктурой

• ссылка на мониторинг

• ссылка на централизованные логи

• расположение резервных копий

• контакты провайдера и внутренней эскалации

перечень ролей, которые дают необходимые права.

Пароли, токены и приватные ключи в сам runbook помещать нельзя. Инструкция должна ссылаться на менеджер секретов или утверждённый процесс получения доступа.

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

Безопасные и опасные действия

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

Например:

Опасное действие. Не выполнять очистку Docker, пока не подтверждено, что остановленные контейнеры и неиспользуемые образы не нужны для отката.

Или:

Перед перезапуском. Сохранить последние 200 строк журнала и текущее состояние процесса.

Полезная инструкция не просто говорит, что делать. Она также предупреждает, где инженер может случайно сделать хуже.

Критерии успешного восстановления

Фраза «сервис запущен» ничего не гарантирует. Процесс может иметь статус active, но возвращать пользователям ошибки.

Поэтому критерии должны быть измеримыми

• внешний запрос получает ожидаемый HTTP-код

• главная страница и критичный пользовательский сценарий работают

• доля ошибок вернулась к нормальному уровню

• очередь запросов сокращается

• приложение выполняет запрос чтения и тестовую запись

• репликация базы данных не отстаёт

• свободного места достаточно для безопасной работы

старый скомпрометированный ключ больше не принимается.

Обязательные разделы runbook

Первые десять минут: универсальная часть любого runbook

Первые минуты реагирования на инцидент

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

Шаг 1. Подтвердить инцидент

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

Например:

Проверка health-check
curl -sS -o /dev/null \
  -w 'HTTP %{http_code}, time %{time_total}s\n' \
  https://example.com/health

Следом полезно проверить сервис из другой сети или через внешний мониторинг. Если сайт открывается из офиса, но не открывается с мобильного интернета, проблема может находиться в DNS, маршрутизации, CDN или сетевой фильтрации.

Шаг 2. Зафиксировать время и симптомы

В журнал инцидента записывают

• время первого сигнала

• время подтверждения

• затронутые компоненты

• наблюдаемые ошибки

• последние изменения

• текущего координатора

ссылку на аварийный канал.

Даже простая запись «12:42 UTC — внешний мониторинг фиксирует 100% ошибок 502, начало примерно в 12:39» позже сэкономит много времени.

Без хронологии участники начинают спорить о том, что произошло раньше: рост нагрузки, релиз, отказ базы или перезапуск приложения.

Шаг 3. Остановить новые изменения

До выяснения картины следует временно приостановить

• релизы

• миграции базы данных

• изменения сетевых правил

• автоматические операции обслуживания

масштабные конфигурационные изменения.

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

Представьте, что команда ищет причину массовых ошибок, а параллельно CI/CD выкатывает очередную версию приложения. Каждая новая переменная превращает расследование в движущуюся мишень.

Шаг 4. Определить масштаб

Нужно ответить на несколько вопросов

• проблема внешняя или сервис не работает и внутри сети

• недоступны все узлы или один

• затронут один дата-центр или несколько

• ошибки получают все пользователи или только часть

• продолжают ли выполняться фоновые задачи

• работает ли чтение из базы данных

• работает ли запись

есть ли риск повреждения данных.

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

Шаг 5. Проверить последние изменения

Один из самых быстрых путей к восстановлению — найти связь с недавним изменением

• релизом

• обновлением пакетов

• миграцией

• изменением DNS

• ротацией сертификата

• обновлением секрета

• изменением firewall

• задачей очистки

увеличением логирования.

Свежий релиз не всегда виноват. Но его нужно проверить одним из первых.

Шаг 6. Сначала стабилизировать, потом расследовать

Во время серьёзного инцидента главная цель — уменьшить влияние на пользователей.

Иногда правильным временным решением становится

• откат релиза

• перевод сайта в режим обслуживания

• отключение тяжёлой функции

• переключение на резервный узел

• временное ограничение трафика

• перевод приложения в режим только для чтения

остановка процесса, который быстро заполняет диск.

Поиск корневой причины продолжается после стабилизации. Это не означает «замести проблему под ковёр». Это означает сначала остановить пожар, а уже затем выяснять, почему загорелась проводка.

Первые 10 минут

Подтвердить → зафиксировать → freeze → масштаб → changes → стабилизировать.

confirm log freeze scope changes stabilize

Сценарий №1. Сайт упал или начал возвращать 5xx

Диагностика ошибок 5xx и недоступности сайта

Фраза «сайт не работает» слишком широкая. За ней могут скрываться ошибка DNS, истёкший сертификат, отказ reverse proxy, падение приложения, недоступность базы данных или нехватка ресурсов.

Runbook должен помогать последовательно локализовать слой проблемы.

Шаг 1. Проверить внешний ответ

curl -I --connect-timeout 5 --max-time 15 https://example.com/

Для более подробной картины:

Детальная проверка HTTP
curl -sS -o /dev/null \
  -w 'IP=%{remote_ip} HTTP=%{http_code} DNS=%{time_namelookup}s CONNECT=%{time_connect}s TLS=%{time_appconnect}s TOTAL=%{time_total}s\n' \
  https://example.com/

Результат уже даёт направление:

• ошибка разрешения имени указывает на DNS

• долгий этап подключения — на сеть или перегруженный сервер

• проблема TLS — на сертификат или конфигурацию HTTPS

• ответ 502 часто означает, что proxy не получил нормальный ответ от приложения

• 503 может появиться при недоступности upstream, перегрузке или включённом режиме обслуживания

500 обычно требует проверки приложения.

HTTP-код — не диагноз, а указатель на следующий участок дороги.

Шаг 2. Проверить DNS

Проверка DNS
dig +short A example.com
dig +short AAAA example.com

Сравните результат с ожидаемыми адресами.

Дополнительно стоит проверить:

• не изменялись ли DNS-записи

• не истёк ли домен

• совпадают ли ответы разных резолверов

• не осталась ли устаревшая AAAA-запись

доступен ли домен напрямую по нужному IP с корректным заголовком Host.

Пример:

curl -I --resolve example.com:443:203.0.113.10 https://example.com/

Если с принудительно указанным IP сайт работает, а при обычном обращении нет, искать проблему следует в DNS или маршрутизации к текущему адресу.

Шаг 3. Проверить сервер и основные ресурсы

После подключения к узлу сначала собирают состояние, а не перезапускают всё подряд:

Состояние сервера
date
hostname
uptime
free -h
df -hT
df -i
systemctl --failed

Затем проверяют, слушаются ли нужные порты:

sudo ss -lntp

Для Nginx:

Диагностика Nginx
sudo systemctl status nginx --no-pager
sudo nginx -t
sudo journalctl -u nginx --since "-15 minutes" --no-pager
sudo tail -n 200 /var/log/nginx/error.log

Для приложения под управлением systemd:

Диагностика приложения
sudo systemctl status myapp --no-pager
sudo journalctl -u myapp --since "-15 minutes" --no-pager

Для Docker Compose:

Docker Compose
docker compose ps
docker compose logs --tail=200

Названия сервисов и пути к журналам должны быть заранее вписаны в runbook. Команда вида «посмотрите логи приложения» в аварийной инструкции почти бесполезна: дежурный не должен ночью угадывать, где именно они хранятся.

Шаг 4. Проверить локальный health-check

Если приложение слушает локальный порт, запросите его напрямую, минуя внешний балансировщик:

curl -v --max-time 10 http://127.0.0.1:8080/health

Возможны три характерных результата.

Локальный health-check работает, внешний сайт нет.Вероятная зона поиска — Nginx, балансировщик, firewall, TLS, DNS или сеть.

Локальный порт не отвечает.Проверяем процесс приложения, его журналы, конфигурацию и зависимости.

Health-check отвечает, но пользовательская операция не работает.Возможно, проверка слишком поверхностная. Приложение живо как процесс, но не может обратиться к базе данных, очереди или внешнему API.

Это хороший повод позже улучшить health-check: он должен проверять не только существование процесса, но и критичные зависимости — в разумных пределах и без создания дополнительной нагрузки.

Шаг 5. Выбрать безопасное восстановление

Runbook должен содержать развилки.

Если проблема появилась сразу после релиза

Сохранить журналы и идентификатор версии.

Сравнить время релиза со временем начала ошибок.

Остановить дальнейшее развёртывание.

Выполнить заранее проверенный откат.

Проверить пользовательский сценарий.

Убедиться, что ошибки и задержки снижаются.

Важно: откат приложения может быть опасен, если релиз включал необратимую миграцию базы данных. Такие ограничения должны быть написаны прямо рядом с командой rollback.

Если процесс приложения остановлен

Перед перезапуском сохраните диагностику:

Сохранить диагностику перед перезапуском
sudo systemctl status myapp --no-pager > /tmp/myapp-status.txt
sudo journalctl -u myapp --since "-30 minutes" --no-pager > /tmp/myapp-journal.txt

После этого, если runbook разрешает перезапуск:

Перезапуск приложения
sudo systemctl restart myapp
sudo systemctl status myapp --no-pager

Перезапуск считается временной мерой, пока не установлена причина остановки.

Если сервер перегружен

Проверьте:

Проверка нагрузки
uptime
free -h
vmstat 1 10
pidstat 1 10

Дальнейшие действия зависят от причины:

• ограничить входящий трафик

• отключить тяжёлый необязательный функционал

• остановить runaway-процесс

• временно увеличить число экземпляров

• уменьшить параллелизм фоновых задач

• перевести часть запросов на резервный узел

включить страницу обслуживания.

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

Шаг 6. Проверить восстановление

После технического изменения недостаточно увидеть зелёный статус процесса.

Проверка должна пройти по цепочке:

Внешняя проверка
curl -fSs https://example.com/health
curl -fSs https://example.com/ >/dev/null

Затем:

• выполнить критичный пользовательский сценарий

• проверить долю 5xx

• оценить задержку

• проверить нагрузку на сервер

• убедиться, что очередь запросов сокращается

• просмотреть новые ошибки в журналах

подтвердить работу из внешней сети.

Мини-пример: приложение запустилось, HTTP 200 вернулся, но оформление заказа всё ещё не работает из-за недоступной базы данных. Формально сервер «зелёный», фактически авария продолжается.

Когда нужна эскалация

Эскалировать инцидент следует, если

• причина не локализована за установленное время

• затронуты данные клиентов

• наблюдается риск потери или повреждения данных

• отказали несколько узлов

• требуется переключение базы данных

• нет доступа к серверу или панели управления

• подозревается атака

• временное решение не снижает влияние

восстановление превышает установленный RTO.

Runbook должен содержать конкретные контакты и порядок: кому звонить первым, через сколько минут подключать следующего специалиста и кто имеет право принимать решение о failover.

Локализация 5xx

DNS → TLS → Nginx → app → DB → resources.

DNS TLS nginx app db resources

HTTP-код → следующий шаг

Сценарий №2. На сервере заполнился диск

Действия при заполненном диске на сервере

Заполненный диск редко выглядит как аккуратная ошибка «место закончилось». Гораздо чаще начинают происходить странные вещи:

• приложение не может создать временный файл

• база данных перестаёт принимать запись

• служба не запускается после перезапуска

• логирование останавливается

• пакетный менеджер выдаёт ошибки

• SSH-сессия работает нестабильно

• сайт возвращает 500

файловая система переходит в режим только для чтения после сопутствующей ошибки.

Поэтому проверка диска должна присутствовать почти в каждом аварийном runbook.

Шаг 1. Понять, что именно закончилось

Сначала проверяем свободное место:

df -hT

Затем inode:

df -i

Это два разных ресурса.

Диск может иметь несколько свободных гигабайт, но не позволять создать новый файл, если закончились inode. Такое случается, когда приложение создаёт миллионы мелких файлов — например, сессии, кэш или временные данные.

Также проверьте точки монтирования:

findmnt

Не стоит автоматически считать, что заполнен корневой раздел. Проблема может находиться в отдельном томе /var, /var/lib/docker, каталоге базы данных или подключённом сетевом хранилище.

Шаг 2. Найти крупные каталоги

Для поиска внутри одной файловой системы:

sudo du -xhd1 / 2>/dev/null | sort -h

Если крупным оказался /var:

sudo du -xhd1 /var 2>/dev/null | sort -h

Дальше спускаемся на уровень ниже:

Поиск крупных каталогов в /var
sudo du -xhd1 /var/log 2>/dev/null | sort -h
sudo du -xhd1 /var/lib 2>/dev/null | sort -h

Ключ -x не даёт команде переходить на другие файловые системы. Это важно, чтобы поиск на корневом разделе случайно не начал часами обходить резервное или сетевое хранилище.

Шаг 3. Проверить журналы, контейнеры и временные данные

Для systemd journal:

sudo journalctl --disk-usage

Для Docker:

docker system df

Для поиска очень крупных файлов:

sudo find /var -xdev -type f -size +1G \

-printf '%s %p\n' 2>/dev/null | sort -n

Частые виновники

• журнал приложения без ротации

• включённый debug-режим

• Docker JSON logs

• core dump

• временные файлы обработки видео или архивов

• старые резервные копии на рабочем разделе

• кэш пакетного менеджера

• бинарные логи базы данных

• очередь, которую перестал разбирать обработчик

• миллионы файлов сессий

неудачная задача экспорта.

Мини-пример: команда удаляет несколько старых архивов и освобождает 10 ГБ. Через двадцать минут диск снова заполнен. Причина не в объёме старых данных, а в приложении, которое после ошибочного релиза пишет по 500 МБ логов в минуту. Пока источник роста не остановлен, очистка напоминает вычерпывание воды из лодки с открытой пробоиной.

Шаг 4. Найти удалённые, но открытые файлы

Иногда du показывает заметно меньше данных, чем df.

Одна из возможных причин — большой файл уже удалили, но процесс продолжает держать его открытым:

sudo lsof +L1

В Unix место такого файла освобождается только после закрытия последнего файлового дескриптора. Поэтому повторное удаление ничего не даст: нужно корректно перезапустить или переоткрыть журнал у процесса, который удерживает файл.

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

Шаг 5. Остановить источник роста

До очистки нужно понять, продолжает ли диск быстро заполняться.

Проверка:

Проверка скорости заполнения диска
df -h /
sleep 60
df -h /

При необходимости повторите для нужной точки монтирования.

Если размер свободного места заметно уменьшается каждую минуту:

• временно снизьте уровень логирования

• остановите неисправную фоновую задачу

• приостановите импорт или экспорт

• ограничьте приём новых заданий

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

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

Шаг 6. Освободить аварийный запас

Безопасный порядок обычно такой

Остановить неконтролируемый рост.

Сохранить небольшой фрагмент подозрительного журнала.

Удалить или архивировать только заведомо ненужные данные.

Освободить достаточно места для стабильной работы.

Восстановить сервисы.

Продолжить плановую очистку после стабилизации.

Для ограничения journal можно использовать, например:

sudo journalctl --vacuum-size=1G

Для обычного большого журнала иногда применяют:

sudo truncate -s 0 /var/log/myapp/error.log

Но только если:

• файл точно является журналом

• нужный фрагмент уже сохранён

• очистка разрешена runbook

• журнал не нужен для расследования безопасности

команда понимает, как процесс продолжит запись.

Ещё один вариант — принудительно запустить утверждённую ротацию:

sudo logrotate -f /etc/logrotate.conf

Перед этим полезно проверить конфигурацию в отладочном режиме:

sudo logrotate -d /etc/logrotate.conf

Чего нельзя делать вслепую

В аварийной инструкции должны быть отдельно перечислены запрещённые импровизации:

Опасные команды — не выполнять вслепую
rm -rf /var/log/*        # опасно
docker system prune -af  # опасно
find / -type f -delete   # опасно

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

Особенно опасна идея «удалим всё старое, потом разберёмся». После такой очистки разбираться может быть уже не с чем.

Шаг 7. Проверить восстановление

После освобождения места:

Проверка после освобождения места
df -hT
df -i
systemctl --failed

Затем нужно:

• перезапустить только затронутые службы

• проверить запись в журнал

• проверить приложение

• убедиться, что база данных принимает запросы

• убедиться, что свободное место не исчезает снова

• проверить отсутствие ошибок файловой системы

вернуть временно остановленные задачи под контролем.

Желательно освободить не несколько мегабайт, а нормальный рабочий запас. Если раздел после очистки остаётся заполненным на 98%, авария лишь отложена.

Что добавить в runbook после инцидента

Чтобы ситуация не повторилась, обычно нужны

• корректная ротация журналов

• лимиты Docker logs

• ограничение срока хранения

• алерты по свободному месту и inode

• отдельный раздел для данных приложения

• отдельный том для базы данных

• автоматическая очистка временных файлов

• контроль размера очередей

• запрет хранения резервных копий на том же разделе

увеличение диска или перенос данных.

Удобная схема порогов:

• 70% — информационное наблюдение

• 85% — предупреждение и поиск тренда

• 95% — критический инцидент

быстрый рост — критический инцидент независимо от текущего процента.

Порог нужно адаптировать к объёму и скорости записи. На диске размером 10 ТБ даже 5% — большой запас, а на маленьком системном разделе несколько свободных гигабайт могут исчезнуть за минуты.

Диск vs inode

df -hT и df -i — разные ресурсы.

свободные GB свободные inode

Заполненный диск

500, readonly FS, нет записи в БД, падает SSH.
Найти mount → du → stop growth → safe cleanup → verify.
70% observe · 85% warn · 95% incident · fast growth = incident.

Сценарий №3. Утёк SSH-ключ, API-токен или другой секрет

Главное правило этого сценария звучит жёстко: обнаруженный в публичном или неконтролируемом месте секрет считается скомпрометированным.

Неважно, успел ли кто-то им воспользоваться. Нельзя доказать, что ключ никто не скопировал. Поэтому первым действием должно быть не удаление сообщения или коммита, а отзыв либо ротация секрета.

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

Шаг 1. Не распространять секрет дальше

В аварийный канал не нужно копировать полный токен или приватный ключ.

Достаточно записать

• тип секрета

• систему, к которой он относится

• место обнаружения

• время возможной публикации

• имя владельца

• fingerprint или последние несколько символов

предполагаемый уровень прав.

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

Шаг 2. Быстро определить масштаб

Нужно выяснить:

• это тестовый или рабочий секрет

• к каким системам он даёт доступ

• имеет ли он права чтения, записи или администрирования

• используется ли один секрет несколькими сервисами

• есть ли срок действия

• можно ли немедленно отозвать его

• приведёт ли отзыв к остановке production

присутствует ли секрет в других репозиториях, образах и журналах.

При этом анализ масштаба не должен задерживать отзыв высокопривилегированного ключа.

Шаг 3. Отозвать или заблокировать старый секрет

Порядок зависит от типа.

Утёк SSH-ключ

Найти все серверы и учётные записи, где разрешён соответствующий публичный ключ.

Удалить его из authorized_keys, bastion host и систем централизованного доступа.

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

Создать новую пару ключей.

Выдать новый публичный ключ только там, где он действительно нужен.

Проверить журналы входа за период возможной компрометации.

Убедиться, что старый ключ больше не работает.

Fingerprint публичного ключа можно получить так:

ssh-keygen -lf compromised_key.pub

Для проверки журналов на системах с systemd:

sudo journalctl -u ssh --since "2026-08-14 08:00"

Название службы может быть ssh или sshd.

Утёк API-токен

Отозвать токен в системе-источнике.

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

Поместить его в менеджер секретов.

Обновить приложения и автоматизации.

Перезапустить или переразвернуть потребителей.

Проверить, что старый токен отклоняется.

Изучить журнал API-вызовов.

Не стоит заменять токен на новый с теми же избыточными полномочиями. Инцидент — хороший момент сократить scope и установить срок действия.

Утёк пароль базы данных

Безопаснее использовать двухэтапную ротацию:

Создать новую учётную запись или второй действующий пароль, если СУБД поддерживает такую схему.

Обновить приложение.

Убедиться, что все экземпляры используют новые данные.

Отозвать старые учётные данные.

Проверить отсутствие подключений старого пользователя.

Изучить журналы запросов и аудита.

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

Утёк приватный ключ TLS

Нужно:

Создать новую пару ключей.

Выпустить новый сертификат.

Развернуть его на всех точках завершения TLS.

Проверить цепочку сертификатов.

Отозвать старый сертификат, когда это применимо.

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

Простое повторное использование старого ключа при перевыпуске сертификата проблему не решает.

Шаг 4. Распространить новый секрет безопасно

Новый ключ нельзя отправлять тем же способом, который привёл к утечке.

Правильные каналы:

• Vault или другой менеджер секретов

• KMS

• защищённое хранилище CI/CD

• система управления конфигурациями

• временная ссылка с ограниченным сроком действия

утверждённый корпоративный менеджер паролей.

В runbook должны быть ссылки на конкретные процедуры: где создать секрет, как выдать сервису доступ и как выполнить ротацию без раскрытия значения оператору.

Шаг 5. Подтвердить, что старый секрет недействителен

Ротация не завершена, пока команда не проверила старые данные.

Проверка должна быть безопасной и заранее описанной. Например:

• попытка SSH-входа старым ключом отклоняется

• запрос со старым API-токеном получает 401 или 403

• старый пользователь базы данных больше не подключается

• старый сертификат заменён на всех балансировщиках

старый cloud access key имеет статус disabled или deleted.

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

Шаг 6. Проверить признаки использования

Нужно проанализировать период от возможной публикации до отзыва.

Ищем:

• входы с новых IP-адресов

• обращения из необычных стран и сетей

• активность в нетипичное время

• создание новых пользователей и ключей

• изменение прав

• выгрузку данных

• массовое чтение объектов

• отключение журналирования

• запуск новых виртуальных машин

• изменение firewall

• необычные API-вызовы

попытки закрепиться в системе.

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

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

Шаг 7. Удалить секрет из репозитория и других хранилищ

После отзыва можно заниматься очисткой.

Удалить файл в новом коммите недостаточно: секрет остаётся в истории Git.

Обычно процедура включает:

Переписывание истории с помощью подходящего инструмента.

Принудительное обновление веток и тегов.

Координацию со всеми разработчиками.

Очистку клонов.

Проверку форков, pull request и кэшей.

Обновление CI/CD.

Установку secret scanning и pre-commit-проверок.

Переписывание истории — отдельная операция с рисками. Старые ветки могут повторно вернуть удалённый секрет, если их просто слить с очищенной историей. GitHub прямо предупреждает о необходимости координации с владельцами клонов и форков.

Что записать в отчёт

Runbook должен требовать фиксации:

• где обнаружен секрет

• когда он мог стать доступен

• к чему давал доступ

• когда отозван

• кто выполнил ротацию

• какие системы обновлены

• когда подтверждена недействительность старого ключа

• какие журналы проверены

• найдены ли признаки использования

какие профилактические меры назначены.

Само значение секрета в отчёт не включается.

Ротация секрета

Stop leak → revoke → rotate → verify → audit.

contain revoke rotate verify audit

Сценарий №4. База данных недоступна

Восстановление при недоступной базе данных

Сообщение приложения «не удалось подключиться к базе данных» ещё не означает, что СУБД остановилась.

Причиной могут быть:

• DNS

• firewall

• сетевой маршрут

• неправильный пароль

• истёкший сертификат

• исчерпанный лимит соединений

• блокировки

• перегрузка CPU или диска

• заполненный раздел

• отказ primary

• ошибка connection pool

• слишком маленький timeout

неверная конфигурация после релиза.

Поэтому runbook должен проверять весь путь — от приложения до реального запроса.

Шаг 1. Выполнить проверку с узла приложения

Проверка с самого сервера базы данных может дать ложное успокоение. Локально СУБД отвечает, но приложение не видит её из-за сети, DNS или firewall.

Сначала:

getent hosts db.internal.example

Затем проверяем TCP-порт:

Для PostgreSQL:

nc -vz db.internal.example 5432

Для MySQL:

nc -vz db.internal.example 3306

Успешное TCP-соединение доказывает только доступность порта. Оно не проверяет пароль, права пользователя, выбранную базу и возможность выполнить запрос.

Шаг 2. Проверить PostgreSQL

Быстрая проверка состояния:

pg_isready \ -h db.internal.example \ -p 5432 \ -d appdb \ -t 5

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

Например:

psql "$DATABASE_URL" \ -v ON_ERROR_STOP=1 \ -c 'SELECT 1;'

Секрет не следует писать прямо в командной строке, где он может попасть в историю shell или список процессов. Используйте менеджер секретов, защищённый конфигурационный файл или утверждённый механизм окружения.

На сервере базы данных:

Диагностика MySQL
sudo systemctl status mysql --no-pager
sudo journalctl -u mysql --since "-30 minutes" --no-pager
sudo ss -lntp | grep 3306

Название службы может отличаться: mysql, mysqld или специализированный экземпляр.

Шаг 4. Проверить ресурсы и диск

uptimefree -hdf -hTdf -ivmstat 1 10

База данных часто оказывается первой системой, которая заметно страдает от заполнения диска или проблем с I/O.

Дополнительно:

iostat -xz 1 10

Если iostat установлен, он поможет увидеть высокую задержку дисковых операций и очередь устройств.

Мини-пример: приложение сообщает о таймаутах базы, команда увеличивает timeout с 5 до 30 секунд, и ошибки временно становятся реже. Но причина — перегруженный диск, на котором каждая операция ждёт десятки секунд. Увеличение timeout не лечит систему, а просто заставляет запросы дольше занимать соединения, постепенно усугубляя перегрузку.

Шаг 5. Проверить лимит соединений

Для PostgreSQL:

• SELECT state, count(*)FROM pg_stat_activityGROUP BY stateORDER BY count(*) DESC;SHOW max_connections

Для просмотра активных и ожидающих запросов:

• SELECT pid, usename, state, wait_event_type, wait_event, now() - query_start AS query_age, left(query, 200) AS queryFROM pg_stat_activityWHERE state <> 'idle'ORDER BY query_start

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

Для MySQL:

SHOW GLOBAL STATUS LIKE 'Threads_connected';SHOW VARIABLES LIKE 'max_connections';SHOW FULL PROCESSLIST;SHOW ENGINE INNODB STATUS\G

Если соединения закончились, нельзя сразу увеличивать max_connections. Сначала нужно понять, кто их занял.

Возможные причины:

• ошибка connection pool после релиза

• слишком много экземпляров приложения

• утечка соединений

• зависшие транзакции

• фоновые задачи

• медленные запросы

атака или резкий рост трафика.

Слепое увеличение лимита может просто перенести отказ на память и CPU.

Шаг 6. Выбрать ветку восстановления

Исчерпан лимит соединений

Определить источник соединений.

Приостановить неисправный сервис или задачу.

Уменьшить размер connection pool.

Завершить только те сессии, влияние которых понятно.

Восстановить минимальный резерв соединений для администрирования.

Проверить скорость повторного роста.

Не стоит массово завершать сессии одной командой без анализа. Среди них могут быть критичные транзакции.

Долгая транзакция или блокировка

Найти ожидающий запрос.

Найти блокирующую сессию.

Определить владельца и бизнес-операцию.

Оценить последствия rollback.

По согласованию завершить запрос или сессию.

Проверить восстановление очереди.

Иногда завершение блокирующей транзакции спасает сервис за минуту. Иногда запускает многочасовой rollback. Именно поэтому решение должно приниматься не по принципу «этот PID выглядит подозрительно», а на основе контекста.

Заполнен диск

Перейти к runbook «Заполнен диск».

Быстрое удаление файлов из каталога данных СУБД запрещено. Нельзя вручную удалять WAL, binlog, redo log, таблицы или временные файлы базы без специализированной процедуры.

Ошибка пароля или сертификата

Сравнить время начала ошибки со временем ротации.

Проверить текущую конфигурацию приложения.

Проверить срок действия сертификата.

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

По возможности использовать период перекрытия старых и новых данных.

Перезапустить connection pool контролируемо.

Проверить реальный SQL-запрос.

Отказал основной сервер базы данных

Failover должен выполняться по отдельному runbook для конкретной архитектуры.

Минимально он обязан включать:

Подтверждение отказа primary.

Блокировку, или fencing, старого primary.

Проверку состояния и отставания реплик.

Выбор подходящей реплики.

Перевод реплики в роль primary.

Обновление маршрутизации.

Переподключение приложений.

Проверку чтения и записи.

Проверку оставшихся реплик.

Отдельную процедуру возвращения старого узла.

Fencing особенно важен. Если старый primary внезапно оживёт и продолжит принимать запись одновременно с новым, возникает split-brain — две расходящиеся версии данных.

Переключение MySQL-источника также требует контроля состояния репликации и аккуратного переназначения source для оставшихся реплик; это не должно превращаться в импровизированный набор команд во время аварии.

Шаг 7. Снизить влияние на уровне приложения

Пока база восстанавливается, приложение может:

• перейти в режим только для чтения

• временно отключить некритичные функции

• поставить запись в очередь

• отдавать часть данных из кэша

• ограничить тяжёлые отчёты

• включить понятную страницу обслуживания

• уменьшить число повторных запросов

• использовать exponential backoff

ограничить connection pool.

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

Шаг 8. Проверить восстановление по всей цепочке

Для закрытия инцидента мало выполнить SELECT 1.

Нужно подтвердить:

• соединение с узла приложения

• чтение данных

• контролируемую тестовую запись

• работу транзакции

• нормальный уровень задержки

• отсутствие быстрого роста соединений

• отсутствие очереди блокировок

• состояние репликации

• успешность критичного пользовательского сценария

снижение ошибок приложения.

После переключения primary также проверяют, что приложения не продолжают обращаться к старому адресу из кэша DNS, старого connection pool или локального конфигурационного файла.

Цепочка DB outage

App → network → DB process → disk → connections → recovery.

app connectivity db service recovery branch

DB недоступна

status, journal, ss, connections, disk, replication lag.
status, journal, port 3306, slow queries, disk.
Read-only mode, queue writes, failover по runbook.

Как команда должна общаться во время аварии

Даже правильные технические действия теряют ценность, если никто не понимает, что происходит.

Аварийный канал не должен превращаться в поток догадок:

Может, база?

Я сейчас перезапущу Nginx.

А я уже поменял firewall.

Кто-нибудь сообщил поддержке?

Рабочее сообщение выглядит иначе:

Пример статус-сообщения в аварийный канал
SEV-1, 12:48 UTC.
С 12:42 сайт возвращает 502 примерно для 100% запросов.
DNS и Nginx доступны, приложение не отвечает на локальном порту.
Последний релиз был в 12:37, дальнейшие развёртывания остановлены.
Выполняется сбор журналов и подготовка отката.
Следующее обновление — 13:00 UTC.

В сообщении есть пять вещей:

• уровень инцидента

• время

• влияние

• подтверждённые факты

текущее действие и время следующего обновления.

Причину нельзя объявлять до подтверждения.

Фраза «инцидент вызван базой данных» звучит уверенно, но может оказаться неверной. Безопаснее написать: «Приложение не может установить соединение с базой; причина соединения уточняется».

Слово «неизвестно» допустимо. Неконтролируемая уверенность опаснее честного отсутствия данных.

Коммуникация

«Может база?» «Я перезапущу nginx» без координации.
SEV, время, влияние, факты, действие, next update.
Причину не объявлять до подтверждения.

Где хранить runbook

Инструкция должна быть доступна именно тогда, когда основная инфраструктура работает плохо.

Поэтому недостаточно положить её:

• только во внутреннюю wiki за корпоративным SSO

• только в Git-сервис, который зависит от той же базы данных

• только на файловый сервер в той же сети

только в голове ведущего администратора.

Практичная схема

• основная версия хранится в репозитории или базе знаний

• изменения проходят review

• мониторинговый алерт содержит прямую ссылку

• существует read-only-копия в независимом месте

• критичные контакты доступны вне корпоративной сети

• runbook можно открыть с телефона

в документе нет секретов.

Хорошая проверка проста: сможет ли дежурный открыть инструкцию, если VPN, SSO и внутренняя wiki одновременно недоступны?

Доступность runbook

Как тестировать и обновлять инструкции

Runbook, который никто не выполнял, — это гипотеза.

Его нужно проверять:

• после создания

• после крупных изменений инфраструктуры

• после смены адресов и доступов

• после обновления версий СУБД и операционной системы

• после реального инцидента

по регулярному расписанию.

Тест не обязательно должен быть разрушительным.

Можно

• выполнить диагностические команды на тестовом сервере

• смоделировать заполнение отдельного тестового тома

• отозвать тестовый API-токен

• отключить тестовую реплику

• провести настольное учение без изменений production

дать runbook инженеру, который его не писал.

Последний вариант особенно полезен. Автор автоматически заполняет пробелы знаниями из головы. Другой инженер быстро обнаруживает фразы вроде «переключите трафик обычным способом» или «проверьте основной лог».

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

После каждого инцидента задайте вопросы

Какой шаг был непонятен?

Какого доступа не хватило?

Какая команда устарела?

Где мы потеряли больше всего времени?

Какой алерт оказался шумным?

Какое действие можно автоматизировать?

Где требовалось решение, но не был указан ответственный?

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

Runbook должен меняться вместе с системой. Если приложение переехало с systemd в Kubernetes, старая команда systemctl restart не становится «примерно правильной». Она становится опасной и бесполезной.

Когда обновлять

Универсальный шаблон серверного runbook

Ниже — заготовка, которую можно перенести в корпоративную базу знаний.

Название

Симптом: краткое описание наблюдаемой проблемы.

Владелец документа

Команда:

Ответственный:

Замещающий:

Дата последнего обновления:

Дата последнего теста:

Следующая проверка:

Условия запуска

Какой алерт сработал?

Как пользователь видит проблему?

Как подтвердить инцидент?

Какие ложные срабатывания возможны?

Оценка влияния

Какие сервисы затронуты?

Какие пользователи затронуты?

Работает ли чтение?

Работает ли запись?

Есть ли риск потери данных?

Продолжается ли ущерб?

Какой уровень критичности?

Роли

Координатор:

Технический исполнитель:

Коммуникация:

Ведение хронологии:

Доступы

Панель управления:

Мониторинг:

Логи:

SSH/bastion:

Менеджер секретов:

Резервные копии:

Контакт провайдера:

Внутренняя эскалация:

Ограничения безопасности

Что запрещено выполнять:

Какие команды требуют согласования:

Что сохранить перед перезапуском:

Какие данные нельзя публиковать в аварийном канале:

Первичная диагностика

# Команды только для чтенияdatehostnameuptimefree -hdf -hTdf -isystemctl --failed

Дополнительные команды для конкретного сервиса:

# Вставить проверенные команды

Дерево решений

Если условие A — выполнить процедуру A.

Если условие B — выполнить процедуру B.

Если причина не определена за N минут — эскалировать.

Если есть риск данным — остановить изменения и подключить владельца данных.

Если подозревается компрометация — перейти к security playbook.

Восстановление

Для каждого действия:

Цель.

Команда.

Ожидаемый результат.

Возможный риск.

Способ отката.

Критерий перехода к следующему шагу.

Проверка

Сервис отвечает извне.

Критичный пользовательский сценарий работает.

Ошибки вернулись к нормальному уровню.

Нагрузка стабилизировалась.

Очереди сокращаются.

Данные доступны.

Репликация исправна.

Временное решение задокументировано.

Эскалация

Через сколько минут:

Кому:

Каким каналом:

Какие данные передать:

Кто принимает решение о failover, rollback или остановке сервиса:

Коммуникация

Шаблон первого сообщения:

Уровень инцидента:Время начала:Влияние:Подтверждённые симптомы:Текущие действия:Следующее обновление:

Завершение

Время восстановления:

Время полного закрытия:

Временные изменения:

Задачи на возврат к штатной конфигурации:

Ссылка на хронологию:

Ссылка на postmortem:

Изменения в runbook:

Шаблон runbook

Ошибки, которые превращают runbook в бесполезный документ

«Обратитесь к системному администратору»

Это не инструкция, а отказ от инструкции.

Если эскалация действительно нужна, должны быть указаны контакт, канал, время ожидания и информация, которую следует передать.

Слишком много теории

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

Ссылку на подробную архитектуру можно добавить отдельно.

Непроверенные команды

Команда, скопированная из случайной статьи, не становится безопасной только потому, что находится в корпоративной wiki.

Каждую команду нужно:

• проверить на актуальной версии системы

• выполнить в тестовой среде

• оценить права

• описать ожидаемый вывод

• снабдить предупреждением о рисках

указать альтернативу и откат.

Отсутствие проверки после восстановления

«Перезапустили сервис» — это действие.

«Пользователь снова может оформить заказ, доля 5xx ниже порога, задержка нормализовалась» — это результат.

Runbook должен вести к результату.

Несколько инженеров одновременно меняют production

Когда один человек перезапускает приложение, второй меняет конфигурацию, а третий переключает трафик, невозможно понять, какое действие помогло или навредило.

Во время серьёзного инцидента технические изменения должны координироваться через одного ответственного.

Устаревшие адреса и доступы

Runbook может быть технически безупречным, но бесполезным, если:

• сервер переименован

• IP изменился

• журнал переехал

• сотрудник уволился

• старая роль больше не выдаётся

ссылка на мониторинг ведёт на удалённый dashboard.

Поэтому у документа должен быть владелец и дата следующей проверки.

Попытка найти корневую причину до восстановления

Инженеры любят понимать систему. Это полезное качество, но во время аварии оно иногда мешает.

Если безопасный rollback возвращает сервис за пять минут, не стоит держать пользователей без сайта ещё час ради красивой гипотезы.

Сначала восстановление. Затем детальное расследование в контролируемой обстановке.

Типичные ошибки

«Проверьте логи приложения» без пути.
Пароли и ключи прямо в документе.
systemctl в мире Kubernetes без адаптации.
Откат без учёта необратимых миграций.

Заключение: хорошая аварийная инструкция экономит не команды, а решения

Runbook не предотвращает все сбои. Диск всё равно может заполниться, база данных — перестать отвечать, приложение — упасть после релиза, а ключ — случайно оказаться в репозитории.

Но инструкция убирает самую дорогую часть аварии: неопределённость.

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

Начать можно с четырёх сценариев:

• сайт недоступен

• диск заполнен

• секрет скомпрометирован

база данных не отвечает.

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

Каждый такой вопрос — не ошибка сотрудника, а найденный пробел в процессе.

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

Итог

Runbook экономит решения, а не команды.

симптомы шаги проверка
Как повысить антиплагиат: 8 эффективных способов 2021 года
Сайт

Как повысить антиплагиат: 8 эффективных способов 2021 года

Чем популярнее тема, тем сложнее написать уникальный текст. Большинство письменных трудов должно содержать цитаты, термины,

Медиасервер: зачем он вам нужен и как его настроить?
Решения для бизнеса

Медиасервер: зачем он вам нужен и как его настроить?

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

ІоВ – одна из главных технологических тенденций 2021 года
DDoS

ІоВ – одна из главных технологических тенденций 2021 года

Устройства из категории IoT (Internet of Things, «интернет вещей») уже прочно вошли в нашу жизнь. Если