Все уроки
Linux и серверыПродвинутый15 мин чтенияВ моём стеке

Продакшен-инфраструктура: лучшая конфигурация для каждого этапа

Эталонные архитектуры от одного грамотно настроенного VPS до Kubernetes и как безопасно переходить между ними.

  • Reference setup
  • Staging
  • Backups
  • Monitoring
  • Scaling path
Шаг 1/4
Один сервер, очень много пользователей. CPU на 100%, все ждут. Так себе.

За 30 секунд

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

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

  • Я веду продакшен для своих и клиентских проектов на Laravel и Next.js — от общих серверов с панелью до выделенного сервера для multi-tenant SaaS, — поэтому выбираю архитектуру по этапу, а не по моде.
  • Я видел, сколько денег и внимания переусложнённая инфраструктура тратит впустую на небольших проектах и насколько хрупки недоделанные конфигурации без бэкапов и мониторинга.
  • Сейчас я сам консолидирую серверы, так что сценарий миграции в этом уроке — тот, которому я действительно следую.

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

01Принципы важнее диаграмм

Хорошая инфраструктура скучна: предсказуемые деплои, понятная зона ответственности и сбои, которые замечают и после которых можно восстановиться. Прежде чем выбирать инструменты, ответьте на четыре вопроса. Какой простой может выдержать бизнес (целевая доступность)? Сколько данных он может потерять (RPO) и как быстро нужно восстановиться (RTO)? Кто будет это обслуживать в 3 часа ночи? Каков месячный бюджет? Затем растите по шагам. Каждый шаг должен устранять реальное узкое место или риск, который вы можете назвать: база данных, отбирающая память у приложения, загрузки, застрявшие на одном диске, единственный сервер как единая точка отказа или команда, деплоящая десятки сервисов. Слишком ранний переход на следующий этап добавляет стоимость и сложность без пользы; слишком поздний означает аварии. На любом этапе описывайте инфраструктуру в коде или хотя бы в письменных runbook, чтобы её можно было пересобрать.

02Этап 1: один правильно настроенный VPS

Для MVP, сайта небольшого бизнеса или внутреннего инструмента один хорошо настроенный сервер (2–8 GB RAM) часто оказывается лучшим выбором: дёшево, быстро, легко понять. nginx терминирует HTTPS и маршрутизирует запросы к приложениям; PHP-FPM и Node работают под собственными пользователями; база данных и Redis слушают localhost; воркеры работают под supervisor или systemd. Docker Compose — хороший вариант, чтобы воспроизводимо упаковать всё это. «Правильно настроенным» его делает всё, что вокруг приложений: базовый набор защиты, Cloudflare впереди, ночные дампы базы, скопированные за пределы сервера, снапшоты провайдера, алерты по доступности и диску и скриптовый деплой с папками релизов. Его слабость — он единая точка отказа, поэтому важна скорость восстановления: вы должны уметь пересобрать его из скриптов и бэкапов за часы и хотя бы раз это отрепетировать.

  • Cloudflare (DNS, WAF, CDN) → nginx → процессы приложений → локальные БД/Redis.
  • Бэкапы вне площадки, снапшоты включены, восстановление проверено.
  • Типичная стоимость: десятки долларов в месяц.

03Этап 2: сервер приложения + управляемая БД + объектное хранилище + CDN

Когда данные становятся ценными или базе нужно больше памяти, вынесите состояние с сервера приложения. Управляемая база данных даёт автоматические бэкапы, восстановление на момент времени и опциональный резервный узел. Пользовательские загрузки уходят в S3-совместимое объектное хранилище вместо локального диска и отдаются через CDN. Сессии и кэш уходят в Redis — управляемый или на приватном сервере. Теперь сервер приложения не хранит уникальных данных, и это ключевое изменение: его можно пересобрать или заменить в любой момент, изменить размер с минимальным риском, а позже добавить второй. Конфигурация и секреты приходят из переменных окружения, а деплой собирает один и тот же артефакт для staging и продакшена. Этот этап — золотая середина для многих прибыльных продуктов, и при хорошем кэшировании и индексах он выдерживает удивительно большой трафик.

  • Сервер приложения без состояния: только код и конфигурация.
  • База данных: управляемая, доступ только из частной сети, PITR включён.
  • Файлы: объектное хранилище + CDN; никаких загрузок на диске сервера.

04Этап 3: балансировщик, несколько серверов приложений, реплики и очереди

Когда одного сервера приложения уже не хватает или бизнесу нужно переживать отказ сервера, поставьте балансировщик нагрузки перед двумя или более одинаковыми серверами приложений, в идеале в разных зонах доступности. Балансировщик проверяет их health checks и перестаёт отправлять трафик на сломанный. Деплой прокатывается по серверам по одному. База данных получает реплики для чтения под тяжёлый трафик на чтение и отчёты, а также резервный узел для failover. Медленная работа (письма, PDF, обработка изображений, вебхуки, импорты) уходит в фоновые очереди с выделенными серверами-воркерами, чтобы веб-запросы оставались быстрыми, а пики сглаживались. Следите за скрытым состоянием: загрузки файлов, сессии, задачи по расписанию (запускайте планировщик только на одном узле или используйте блокировку) и кэши в памяти — всё это должно быть общим или согласованным. Отставание репликации также означает, что пользователь может не сразу прочитать с реплики то, что только что записал.

05Этап 4: контейнеры и Kubernetes

Контейнеры упаковывают каждый сервис вместе с его зависимостями, так что один и тот же образ работает на ноутбуке, в CI и в продакшене. Docker Compose на одном или нескольких серверах покрывает очень многое. Kubernetes (или управляемая альтернатива вроде ECS, Cloud Run или управляемого сервиса Kubernetes) добавляет планирование по множеству машин, самовосстановление, rolling updates, автомасштабирование и обнаружение сервисов. Он окупается, когда вы запускаете много сервисов, несколько команд деплоят независимо или трафик сильно колеблется. Цена реальна: платформа, которую нужно изучить и эксплуатировать, больше YAML, больше способов ошибиться в настройке сети и безопасности и обычно более высокий счёт. Управляемый control plane снимает часть боли, но не сложность самих нагрузок. Многим успешным продуктам он так и не понадобился; переходите на него, когда цена координации без него явно выше.

06Окружения, секреты, DR, мониторинг и стоимость

Каждому этапу нужно как минимум staging-окружение, повторяющее продакшен по версиям и конфигурации, со своей базой данных и учётными данными, чтобы изменения проверялись до того, как их увидят клиенты. Секреты подставляются для каждого окружения из env-файлов или менеджера секретов, никогда не делятся между staging и продакшеном и никогда не попадают в Git. Аварийное восстановление (DR) — это записанные и отрепетированные шаги: где лежат бэкапы, как пересобрать сервер, как переключить базу данных на резерв, кто принимает решения. Мониторинг состоит из трёх частей: метрики (CPU, память, диск, задержки, доля ошибок, длина очередей, например через Prometheus и Grafana), централизованно собираемые логи (Loki или облачный сервис) и алерты, которые будят человека только при реальном влиянии на пользователей, плюс внешние проверки доступности. Пересматривайте расходы ежемесячно: неиспользуемые серверы, завышенные инстансы, старые снапшоты и плата за egress тихо накапливаются.

  • dev → staging → production, и дальше продвигается один и тот же артефакт сборки.
  • Алерты по симптомам (ошибки, задержки, простой), расследование по метрикам и логам.
  • Помечайте ресурсы тегами проекта и окружения, чтобы видеть, куда уходят деньги.

07Миграция или объединение серверов без потери данных

Перенос сайтов на новый сервер или объединение нескольких серверов в меньшее число — это в основном аккуратный учёт. Сначала инвентаризация: каждый домен, приложение, база данных, cron-задача, воркер, сертификат, почтовый ящик, env-файл и папка загрузок на старом сервере. Соберите новый сервер по базовому набору, затем скопируйте код, файлы и базы данных и проверьте: запустите приложения через переопределение в hosts-файле, сравните число строк и файлов, посмотрите логи. За день до переключения уменьшите TTL в DNS. В момент переключения ненадолго переведите старое приложение в режим обслуживания, выполните финальную инкрементальную синхронизацию файлов и свежий дамп базы, импортируйте его, затем переключите DNS (с прокси Cloudflare это мгновенно). Оставьте старый сервер работающим и нетронутым, пока трафик, данные и бэкапы на новом не будут проверены в течение нескольких дней; только после этого, сделав финальный бэкап, выводите его из эксплуатации.

bash
# 1. Initial copy of code and uploads (preserves owners, permissions, links)
rsync -aHAX --info=progress2 [email protected]:/var/www/shop/ /var/www/shop/
 
# 2. At cutover: maintenance mode on the old server, then final delta sync
ssh [email protected] 'cd /var/www/shop && php artisan down'
rsync -aHAX --delete [email protected]:/var/www/shop/storage/ /var/www/shop/storage/
 
# 3. Fresh database copy streamed directly to the new server
ssh [email protected] 'mysqldump --single-transaction --routines --triggers shop_db' | mysql shop_db
 
# 4. Verify before switching DNS
mysql -e "SELECT COUNT(*) FROM shop_db.orders;"
ssh [email protected] "mysql -e 'SELECT COUNT(*) FROM shop_db.orders;'"
curl -sI --resolve example.com:443:127.0.0.1 https://example.com | head -1

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

  • Этап 1 — для MVP, небольшого бизнеса и внутренних инструментов со скромным трафиком и бюджетом.
  • Этап 2 — когда данные становятся ценными или загрузки и память базы перерастают одну машину.
  • Этап 3 — когда нужно переживать отказ сервера или одного сервера приложения уже не хватает.
  • Этап 4 — когда много сервисов и команд деплоят независимо и стоимость платформы оправдана.

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

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

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

  • PaaS (Laravel Cloud, Vercel, Render, Fly.io и подобные)

    Большую часть инфраструктуры берут на себя за вас; выше стоимость единицы ресурса и меньше контроля.

  • Serverless-функции

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

  • Управляемые контейнеры (ECS, Cloud Run)

    Оркестрация контейнеров без самостоятельной эксплуатации Kubernetes; частый промежуточный шаг.

  • Хостинг-панели

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

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

  1. Выбирайте самый простой этап, который удовлетворяет вашим требованиям к доступности, RPO/RTO и бюджету, и записывайте эти цели.
  2. Рано делайте серверы приложений stateless: загрузки в объектном хранилище, сессии и кэш в Redis.
  3. Держите staging близким к продакшену и продвигайте один и тот же артефакт сборки.
  4. Разделяйте секреты по окружениям и держите их вне Git.
  5. Бэкапы вне площадки с плановыми учениями по восстановлению и письменный DR-runbook.
  6. Ставьте алерты на симптомы, видимые пользователям, и храните метрики и централизованные логи для диагностики.
  7. Пересматривайте счёт ежемесячно и удаляйте то, чем никто не пользуется.

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

  • Переусложнение: кластер, service mesh и пять окружений для приложения с сотней пользователей.
  • Недоделанность: один сервер без бэкапов вне площадки и без мониторинга, на котором держится платящий бизнес.
  • Горизонтальное масштабирование серверов приложений, пока загрузки и сессии всё ещё лежат на диске каждого сервера.
  • Переключение DNS при миграции без снижения TTL, финальной синхронизации и проверки — и слишком раннее удаление старого сервера.
  • Одна общая база данных или один набор учётных данных для staging и продакшена.

Глубже

08Математика доступности: «девятки», зависимости и error budget

Цель по доступности превращается в конкретный допустимый объём простоя. За 30-дневный месяц 99.5 процента дают около 3.6 часа, 99.9 процента — около 43 минут, а 99.99 процента — около 4.3 минуты, чего не выдержит ни один процесс дежурств с людьми без автоматического failover. Последовательные зависимости перемножаются: если приложению нужны сервер, база и платёжный API, каждый с 99.9 процента, весь путь — примерно 99.7 процента. Параллельное резервирование её повышает: два независимых сервера приложения, каждый из которых недоступен 0.1 процента времени, лежат одновременно лишь около 0.0001 процента — если их отказы действительно независимы, а общая база, регион или деплой часто эту независимость ломают. Разница между вашим SLO и 100 процентами — это error budget. Когда он в порядке, выпускайте фичи быстрее; когда исчерпан — притормозите и вкладывайтесь в надёжность. Так споры о надёжности превращаются в число, с которым согласны и бизнес, и инженеры.

09Стратегии деплоя и миграции expand-contract

Rolling deploy заменяет инстансы за балансировщиком по одному: дёшево, но какое-то время старая и новая версии обслуживают трафик вместе. Blue-green поднимает полное второе окружение и переключает трафик сразу, с мгновенным откатом обратным переключением, но на время релиза стоимость удваивается. Canary отправляет на новую версию небольшую долю трафика, скажем 5 процентов, и расширяет её, только если доля ошибок и задержка остаются в норме. Все три подхода требуют, чтобы две версии кода могли работать с одной и той же базой. Это делает возможным паттерн expand-contract: сначала expand (добавить новую колонку или таблицу, nullable, ничего не удаляя), задеплоить код, который пишет в обе и читает новую, сделать backfill пачками и только в одном из следующих релизов выполнить contract — удалить старую колонку. Никогда не переименовывайте и не удаляйте колонку в том же релизе, который перестаёт её использовать. Именно эта дисциплина, а не инструмент деплоя, делает релизы без простоя реальностью.

  • Релиз 1: добавить nullable-колонку, задеплоить код, который пишет в старую и новую.
  • Backfill небольшими пачками, вне пиковых часов, с логированием прогресса.
  • Релиз 2: читать только новую колонку. Релиз 3: удалить старую.

10Алерты на то, что чувствуют пользователи: SLO и burn rate

Алерты на CPU или память создают шум: сервер с CPU на 90 процентах, который быстро обслуживает каждый запрос, — это нормально. Будите людей по симптомам, а при диагностике используйте метод RED для сервисов (rate, errors, duration) и USE для ресурсов (utilisation, saturation, errors). Самый надёжный паттерн — burn-rate алерт из Google SRE workbook: алерт срабатывает, когда error budget расходуется намного быстрее, чем позволяет SLO, с проверкой по длинному и короткому окну, чтобы он быстро срабатывал при реальных инцидентах и быстро гас после них. Burn rate 14.4, державшийся час, съедает 2 процента 30-дневного бюджета — ради этого стоит кого-то разбудить. Более медленный расход превращается в тикеты, а не в пейджи. Держите под контролем кардинальность меток Prometheus: ID пользователей или полные URL в качестве меток создают миллионы рядов и могут положить систему мониторинга ровно тогда, когда она нужна.

yaml
groups:
  - name: slo
    rules:
      - 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)
        for: 2m
        labels:
          severity: page
        annotations:
          summary: "99.9% SLO error budget burning 14x too fast"

11Планирование мощностей по закону Литтла

Закон Литтла гласит: среднее число запросов в системе равно скорости поступления, умноженной на время пребывания в ней. При 200 запросах в секунду и среднем времени ответа 250 ms в каждый момент обрабатывается около 50 запросов, значит, нужно минимум 50 воркеров PHP-FPM или эквивалентная параллельность плюс запас. Если задержка удвоится из-за замедления базы, тому же трафику понадобится 100 воркеров — вот почему медленные зависимости так внезапно исчерпывают пулы воркеров. Планируйте под пики, а не под средние значения: у многих продуктов в часы пик или во время кампаний трафик в три–десять раз выше среднего. Держите загрузку в стабильном режиме около 50–70 процентов, чтобы отказ узла или всплеск не опрокинули остальные. Перед запусками проводите нагрузочное тестирование инструментом вроде k6, наращивая нагрузку, пока задержка не начнёт расти, и запишите, где это происходит: это и есть ваша реальная мощность. Стоимость подчиняется той же логике: подбирайте размер по измеренным пикам и следите за egress и хранилищем, которые растут незаметно.

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

01

Кампания принесёт в десять раз больше трафика, чем обычно

Проблема

Маркетинг объявляет телерекламу в пятницу вечером. Продукт работает на одном сервере приложения с managed-базой, и никто не знает, какую нагрузку он выдержит.

Как решить

Сначала измерьте: нагрузочно протестируйте staging с данными, похожими на продакшен, через k6, наращивая нагрузку, пока не вырастет задержка, и отметьте, какой ресурс упирается первым. Затем сократите работу на запрос: закэшируйте лендинги и публичные ответы API в CDN, добавьте короткий microcache в nginx, перенесите письма и вебхуки в очереди. Временно масштабируйте узкое место, например сервер приложения или инстанс базы побольше, заказанный за день. В день кампании заморозьте деплои, подготовьте лёгкую статическую fallback-страницу и выведите дашборды ошибок, задержки, длины очереди и соединений с базой на один экран. После сравните фактический пик с тестом, чтобы откалибровать будущее планирование.

02

Единственный продакшен-сервер умирает в 3 часа ночи

Проблема

Провайдер сообщает об аппаратном сбое. VPS не загружается, бизнес работает на нём, снимки есть, но самый свежий — со вчерашней ночи.

Как решить

Действуйте по runbook, а не импровизируйте. Быстро решите, ждать провайдера или пересобирать; известная оценка времени восстановления обычно говорит в пользу пересборки. Создайте сервер из последнего снимка или по эталонным скриптам, восстановите самый свежий удалённый бэкап базы и проиграйте журналы, если настроен point-in-time recovery, и синхронизируйте загрузки из объектного хранилища. Проверьте через переопределение в файле hosts, затем направьте DNS или floating IP на новую машину. Опубликуйте обновление статуса пораньше. После этого напишите blameless-разбор: фактические RTO и RPO против целевых и что дальше — managed-база или standby-сервер.

03

Консолидация серверов с переносом почты

Проблема

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

Как решить

Относитесь к почте как к отдельной миграции. Создайте ящики у нового провайдера, за день снизьте TTL у MX и связанных записей, затем скопируйте существующую почту инструментом IMAP-синхронизации вроде imapsync. При переключении смените MX-записи, опубликуйте SPF include и DKIM-ключи провайдера и держите DMARC в режиме мониторинга (p=none), пока отчёты не покажут, что всё сходится. После распространения MX запустите финальную инкрементальную IMAP-синхронизацию, чтобы подхватить запоздавшие письма. Приложения, отправлявшие почту через старый сервер, нужно переключить на SMTP провайдера или почтовый API. Перед выводом из эксплуатации оставьте старый почтовый сервис на несколько недель в режиме только для чтения.

Шпаргалка

Проверить текущий ответ DNS и TTL
dig +noall +answer example.com A
Проверить новый сервер до переключения DNS
curl -sI --resolve example.com:443:203.0.113.20 https://example.com
Отрепетировать синхронизацию без копирования
rsync -aHAXn --delete --itemize-changes src/ dest/
Вывести итоговый конфиг Compose
docker compose -f compose.yml -f compose.prod.yml config
Быстрый нагрузочный тест
k6 run --vus 50 --duration 2m load-test.js
Допустимый простой за 30 дней
99.5% = 3.6 h, 99.9% = 43 min, 99.95% = 22 min, 99.99% = 4.3 min
Нужное число воркеров (закон Литтла)
concurrency = requests per second x average latency in seconds
Режим обслуживания Laravel с секретом для обхода
php artisan down --secret="your-random-token"
Проверить записи SPF и DMARC
dig +short TXT example.com && dig +short TXT _dmarc.example.com

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

  • Я веду четыре продакшен-сервера на Ubuntu в DigitalOcean: два сервера с хостинг-панелью и множеством сайтов на Laravel и Next.js, один выделенный сервер для multi-tenant POS SaaS и один для e-commerce-платформы.
  • SaaS-сервер работает на Docker Compose с отдельными переопределениями для dev, prod, TLS и observability, с nginx, PostgreSQL, Redis, воркерами BullMQ, Prometheus, Grafana и Loki, плюс runbook и скрипты бэкапа.
  • Мой подход к консолидации — четыре сервера в два (SaaS отдельно, все остальные сайты вместе) без панели, с переносом почты к облачному провайдеру, DNS в Cloudflare, бэкапами за пределами сервера и загрузками в S3-совместимом хранилище.
  • При объединении я следую схеме: инвентаризация, копирование, проверка, переключение DNS — и старый сервер остаётся, пока всё не проверено.

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

Q1Какую инфраструктуру вы бы порекомендовали для нового стартап-продукта?

Обычно один хорошо настроенный сервер или простой PaaS, а не кластер. Один VPS с nginx, приложением, локальной или небольшой управляемой базой данных, Redis и Cloudflare впереди выдерживает гораздо больше трафика, чем получает большинство новых продуктов. На чём я настаиваю с первого дня, так это на эксплуатационных основах: защита сервера, staging, скриптовый деплой, бэкапы вне площадки с проверенным восстановлением, мониторинг доступности и ошибок. Я проектирую приложение без состояния — загрузки в объектном хранилище, сессии в Redis, конфигурация из переменных окружения, — чтобы последующий переход на управляемую базу и несколько серверов приложений был изменением конфигурации, а не переписыванием. Тратьте деньги на продукт, пока реальная нагрузка или требования к доступности не оправдают большего.

Q2Как масштабироваться с одного сервера на несколько?

Сначала я убираю состояние с сервера приложения: база данных переезжает на собственный приватный или управляемый инстанс, загрузки уходят в объектное хранилище за CDN, сессии, кэш и блокировки — в Redis, а задачи по расписанию запускаются один раз с блокировкой. Затем ставлю балансировщик с health checks перед двумя или более одинаковыми серверами приложений, собранными из одного образа или скрипта, и прокатываю деплой по ним по одному. Медленная работа уходит на воркеры очередей, которые масштабируются отдельно. Если доминирует чтение, добавляю реплики для чтения и направляю туда отчёты. Перед всем этим я профилирую, потому что недостающий индекс часто даёт больше, чем второй сервер.

Q3Когда Kubernetes имеет смысл?

Когда проблема координации, которую он решает, больше, чем платформа, которой он требует. Обычно это означает много сервисов, несколько команд, деплоящих независимо, переменный трафик, выигрывающий от автомасштабирования, или потребность в единообразном самовосстановлении и rolling updates на множестве машин. Для одного или нескольких приложений Docker Compose на паре серверов или управляемый контейнерный сервис вроде ECS или Cloud Run дают большую часть пользы при гораздо меньшей эксплуатационной нагрузке. Kubernetes нужны люди, которые разбираются в сетях, лимитах ресурсов, политиках безопасности и обновлениях, даже с управляемым control plane. Я лучше буду хорошо вести простую конфигурацию, чем плохо — сложную.

Q4Как перенести продакшен-сайт на новый сервер без потери данных?

Инвентаризировать всё на старом сервере: домены, приложения, базы данных, cron-задачи, воркеры, сертификаты, env-файлы, загрузки и почту. Собрать новый сервер по базовому набору, скопировать код и файлы через rsync, восстановить копию базы и проверить сайт через переопределение в hosts-файле. За день снизить TTL в DNS. В момент переключения включить режим обслуживания, выполнить финальный инкрементальный rsync и свежий дамп базы с импортом, сравнить число строк и файлов, затем переключить DNS. Следить за логами и трафиком на новом сервере, оставить старый нетронутым на несколько дней как вариант отката, сделать его финальный бэкап и только потом вывести из эксплуатации.

Q5Чем staging отличается от продакшена и насколько они должны быть похожи?

Продакшен обслуживает реальных пользователей и данные. Staging — репетиционное окружение, где вы проверяете релизы, миграции и конфигурацию до того, как они попадут в продакшен. Он должен совпадать с продакшеном по версиям ПО, структуре конфигурации, процессу сборки и форме инфраструктуры, чтобы проблемы проявлялись сначала там, но со своей базой данных, учётными данными и интеграциями в режиме sandbox и обычно на серверах поменьше. Реальные персональные данные не стоит копировать в staging без анонимизации. Из staging в продакшен должен переходить один и тот же артефакт сборки, чтобы вы тестировали ровно то, что выпускаете. Чем ближе они друг к другу, тем меньше сюрпризов, хотя staging, стоящий столько же, сколько продакшен, для небольших команд редко оправдан.

Q6Что должен включать минимальный мониторинг и алертинг?

Четыре вещи. Внешние проверки доступности ключевых URL и API с алертами в чат или на телефон. Метрики хоста: место на диске, память, нагрузка на CPU и соединения с базой, с алертами до заполнения дисков. Сигналы приложения: трекинг ошибок со стек-трейсами, задержки запросов и доля ошибок, длина очередей и упавшие задачи. И истечение сертификатов плюс успешность задач бэкапа — два сбоя, которые молчат, пока не ударят. Логи должны собираться централизованно с достаточным сроком хранения для расследования инцидентов. Алертов должно быть немного, и по каждому должно быть понятно, что делать; если люди их игнорируют, это шум. Стек Prometheus, Grafana и Loki покрывает всё это при самостоятельном хостинге, а облачные инструменты обменивают деньги на меньшие затраты на обслуживание.

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

S1Когда оправдана мультирегиональная схема?

Для небольших и средних продуктов — редко. Один регион с несколькими зонами доступности уже переживает отказ сервера или дата-центра; полный отказ региона бывает нечасто. Мультирегиональность добавляет трудные задачи: репликацию базы через сотни миллисекунд задержки, выбор между асинхронной репликацией с возможной потерей данных и синхронной с медленной записью, маршрутизацию пользователей и тестирование failover, который редко используется. Стоимость примерно удваивается. Это оправдано, когда договоры требуют устойчивости к отказу региона, законы о локализации данных требуют локального хранения или пользователям на разных континентах нужна низкая задержка записи. Более дешёвый компромисс — warm standby: бэкапы и инфраструктурный код наготове во втором регионе с проверенным временем восстановления в часах, а не секундах.

S2Спроектируйте disaster recovery для SaaS с RPO 5 минут и RTO 1 час.

RPO в пять минут исключает ночные дампы: нужно непрерывное архивирование WAL или binlog в хранилище в другом аккаунте или регионе либо managed-база с point-in-time recovery, плюс загрузки в реплицируемом объектном хранилище. RTO в один час означает, что пересборка должна быть автоматизирована: infrastructure as code или скриптовые эталоны, образы контейнеров в registry, секреты, восстанавливаемые из менеджера секретов, и DNS с низким TTL или балансировщик, который можно перенаправить. Тёплая standby-реплика сокращает часть с базой до минут вместо восстановления. Затем это нужно доказать: ежеквартальные учения с восстановлением в чистое окружение только из удалённых копий, с замером времени против обеих целей, письменным runbook и назначенными поимённо ответственными за решения.

S3Своя observability или облачный сервис?

Свои Prometheus, Grafana и Loki почти ничего не стоят в лицензиях и держат данные под вашим контролем, что подходит для одного выделенного окружения или строгих правил обращения с данными. Но это ещё одна продакшен-система: хранилище растёт, обновления ломают дашборды, а если она работает на том же сервере, который мониторит, то умирает в том же инциденте. Облачные инструменты берут деньги за хосты, ряды или объём логов и могут стать дорогими при метриках с высокой кардинальностью или многословных логах, зато доступны, когда ваша инфраструктура недоступна, и не требуют обслуживания. Мой обычный ответ: внешние проверки доступности и трекинг ошибок — всегда в облаке; метрики и логи — на своём отдельном небольшом сервере, когда важен бюджет, и в облаке, когда время команды стоит дороже счёта.

S4Как избежать vendor lock-in при выборе managed-сервисов?

Lock-in — это издержка, которой надо управлять, а не то, чего нужно избегать любой ценой; managed-сервисы существуют потому, что экономят реальное время. Я предпочитаю сервисы на открытых интерфейсах: PostgreSQL или MySQL вместо проприетарных баз, S3-совместимое объектное хранилище, Redis-совместимые кэши, контейнеры и стандартные протоколы вроде SMTP и OpenTelemetry. Код приложения общается с ними через абстракции фреймворка, например драйверы filesystem, queue и mail в Laravel, так что смена провайдера — вопрос конфигурации. Infrastructure as code документирует всё, что пришлось бы воссоздавать. Более глубокую привязку я принимаю только там, где сервис даёт явное преимущество, и сохраняю возможность выгрузить данные с регулярными бэкапами вне вендора, потому что труднее всего переносить всегда данные, а не вычисления.

Глоссарий

SLO
Service level objective: внутренняя цель по надёжности, например 99.9 процента успешных запросов за 30 дней.
SLA
Service level agreement: договорное обещание клиентам, обычно мягче SLO, со штрафами при нарушении.
Error budget
Допустимый по SLO объём ненадёжности; его расход подсказывает, выпускать фичи или чинить стабильность.
Единая точка отказа
Один компонент, отказ которого кладёт весь сервис, например единственный сервер или база.
Stateless-сервер
Сервер приложения без уникальных данных, поэтому его можно в любой момент заменить или продублировать.
Blue-green deploy
Работа двух полных окружений и одномоментное переключение трафика со старого на новое.
Canary release
Сначала небольшая доля трафика идёт на новую версию, и она расширяется, только если версия ведёт себя хорошо.
Expand-contract
Изменение схемы базы обратно совместимыми шагами, чтобы старый и новый код могли работать одновременно.
Burn rate
Скорость расхода error budget относительно скорости, при которой он был бы исчерпан ровно к концу периода.
Egress
Данные, переданные из сети облачного провайдера наружу; часто тарифицируются за гигабайт, и о них легко забыть.

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

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