«А что будет, когда это сломается?» — вопрос, который отличает боевую систему от учебной. Сломается обязательно: упадёт узел, выйдет из строя зона, кто-то удалит не ту таблицу. Разница между катастрофой и штатной ситуацией — в том, подготовились ли вы заранее. Разберём два уровня подготовки. Оба стоят на нескольких зонах, поэтому начните с масштабирования и доступности, если ещё не читали.
Три разных отказа и три ответа: от дата-центра спасают копии по зонам, от ошибочного удаления только копии в проекте с другими правами, от потери региона межрегиональная реплика и глобальный балансировщик. Порядок внедрения обратный цене: сначала защита от удаления.
Отказоустойчивость против аварийного восстановления
Это два разных уровня, их полезно различать.
- Отказоустойчивость (high availability) — система переживает отказ части себя без остановки. Упал узел или целая зона — трафик ушёл на оставшиеся, пользователь ничего не заметил. Это про «продолжать работать».
- Аварийное восстановление (disaster recovery, DR) — как поднять систему после крупной аварии, которая всё-таки её уронила: потеря целого региона, порча данных, ошибочное массовое удаление. Это про «как вернуться к жизни и с какими потерями».
Первое строят заранее в архитектуре; второе — это план и бэкапы, которые понадобятся в худший день.
Зоны и мультирегион
Дата-центр, где стоят все ваши машины, встал целиком — и вместе с ним встал сервис. Основной инструмент против этого — распределение по зонам одного региона: независимые дата-центры, авария в одном не задевает другие. На практике: копии приложения в региональной группе экземпляров по зонам за балансировщиком, Cloud SQL в конфигурации высокой доступности с резервом в другой зоне и автопереключением.
От крупной аварии всего региона защищает мультирегиональная схема: копии приложения в нескольких регионах за глобальным балансировщиком (он сам направит пользователей в живой регион) и данные, реплицируемые между регионами. Это дороже и настраивается отдельно, но переживает потерю целого региона. Глобальный HTTP-балансировщик здесь один на все регионы, с одним anycast-адресом: не нужно ни DNS-переключения, ни отдельного балансировщика в каждом регионе, а пользователей он направляет в ближайший живой регион сам.
Про репликацию данных между регионами нужно понимать главное: она асинхронная. Записанное в одном регионе доезжает до второго с задержкой, поэтому при внезапной потере региона теряются последние секунды или минуты изменений. Это и есть RPO мультирегиональной схемы, и он не ноль. Синхронная запись через полмира стоила бы задержки в каждом запросе, и на неё идут только там, где потерять данные нельзя совсем.
Четыре стратегии восстановления
У темы есть стандартный язык, и его стоит знать — он одинаков во всех облаках, и разговор с бизнесом ведут именно в нём. Стратегии выстроены по возрастанию: выше — дешевле и медленнее, ниже — дороже и быстрее.
1. Копии и восстановление. Вы храните резервные копии, и всё. Случилась беда — разворачиваете инфраструктуру заново и заливаете данные. Дешевле некуда (платите только за хранение копий), а восстановление занимает часы и требует, чтобы описание инфраструктуры было под рукой и работало.
2. Дежурная лампочка. Постоянно работает только ядро — обычно межрегиональная реплика базы, которая получает свежие данные. Приложение, балансировщики и остальное выключено и поднимается при аварии. Восстановление — десятки минут, и потеря данных ограничена отставанием реплики (секунды-минуты, потому что репликация асинхронная).
3. Тёплый резерв. Во втором регионе работает уменьшенная, но живая копия всей системы: она либо обслуживает часть трафика, либо просто готова. При аварии её масштабируют до полного размера и переводят на неё весь трафик. Восстановление — минуты, платите постоянно за работающую копию.
4. Две живых площадки. Полноценные копии работают в двух регионах одновременно и обе обслуживают пользователей. Отказ одного региона означает, что трафик идёт во второй почти без паузы. Дороже всего и сложнее всего: данные надо синхронизировать в обе стороны, а конфликты — разрешать.
Порядки величин, чтобы сопоставлять со требованиями:
| Стратегия | RPO | RTO | Относительная цена |
|---|---|---|---|
| Копии и восстановление | часы | часы, иногда сутки | 5–10 % контура |
| Дежурная лампочка | минуты | десятки минут | 15–25 % |
| Тёплый резерв | секунды-минуты | минуты | 30–60 % |
| Две площадки | близко к нулю | секунды | 100 % и больше |
Как этим пользоваться: бизнес называет допустимые RPO и RTO, вы берёте первую сверху строку, которая в них укладывается. Обратный порядок («возьмём две площадки, чтобы наверняка») — самая частая дорогая ошибка в этой теме.
И практическое замечание для GCP: переход от первой стратегии ко второй здесь дешевле, чем кажется, потому что инфраструктура описывается кодом и разворачивается в новом регионе быстро, а межрегиональная реплика базы — это одна настройка. То есть «часы» превращаются в «десятки минут» за небольшие деньги, и это обычно самый выгодный шаг.
RPO и RTO: язык восстановления
Планируя восстановление, оперируют двумя числами.
- RPO (Recovery Point Objective) — сколько данных вы готовы потерять, измеряется временем. RPO = 1 час означает «в худшем случае теряем последний час изменений». Определяется частотой резервных копий.
- RTO (Recovery Time Objective) — как быстро надо вернуть сервис к жизни. RTO = 30 минут означает «через полчаса после аварии система снова работает».
Эти два числа — не технические детали, а бизнес-решение: чем меньше RPO и RTO, тем дороже подготовка. Сначала договариваются, что приемлемо, потом строят под это.
Резервные копии и репликация
Отказоустойчивость не спасает от порчи или удаления данных: если ошибочный запрос удалил строки, реплики честно повторят удаление. Здесь спасают только копии, отдельные от боевых данных:
- автоматические резервные копии Cloud SQL — снимок базы по расписанию. Сам по себе он задаёт RPO, равный промежутку между копиями: копия раз в сутки — значит, в худшем случае теряется день работы;
- восстановление на момент в прошлом (PITR) — отдельная возможность поверх копий: база хранит журналы транзакций, и вернуться можно на конкретную минуту, а не только на момент копии. Именно она превращает RPO из «суток» в «минуты» — но включена она не всегда и не везде: зависит от редакции Cloud SQL и от того, чем вы создавали экземпляр, консолью или Terraform. Проверьте у себя, а не считайте, что это есть по умолчанию;
- снимки дисков (snapshots) виртуальных машин — точечная копия состояния диска. С базой, живущей на такой машине, есть подвох: снимок работающей базы не согласован на уровне приложения. Вы копируете диск в произвольный момент, когда часть данных ещё в памяти и в незавершённых записях, — и получаете не бэкап, а его видимость. Чтобы снимок был рабочим, запись на время останавливают или заставляют базу сбросить буферы на диск;
- версионирование в Cloud Storage — защита от перезаписи и удаления: прежняя версия объекта остаётся рядом, и её можно вернуть. В ту же сторону работает мягкое удаление (soft delete), которое Google включает у новых бакетов по умолчанию: удалённое и перезаписанное ещё несколько дней (по умолчанию 7) лежит скрытым и восстанавливается;
- мультирегиональные бакеты — совсем про другое: они спасают не от кривого скрипта, а от потери региона, потому что держат копии файлов в нескольких регионах. Сами бэкапы при этом часто складывают в дешёвый класс Archive.
Ключевое правило, которое нарушают чаще всего: бэкап, который ни разу не восстанавливали, — это не бэкап, а предположение. Восстановление надо проверять, иначе в худший день выяснится, что копии битые или неполные.
Самый вероятный сценарий: удалили
Прежде чем строить второй регион, стоит закрыть то, что случается чаще любых отказов оборудования, — человеческую ошибку. В GCP у неё есть особенно неприятная форма.
Удалили проект — удалили всё внутри. Проект в GCP — граница всего, и его удаление уносит базы, хранилища, копии, настройки. Удаление не мгновенное (проект висит в состоянии «ожидает удаления» порядка месяца и его можно восстановить), и это единственное, что спасает — но рассчитывать на это как на защиту нельзя.
Что включают, чтобы этого не случилось:
Защита от удаления у ресурсов. У части ресурсов (машины, базы) есть признак, запрещающий удаление, пока его не снимут. Ставится одной командой и стоит того на всём боевом контуре.
gcloud compute instances update app-1 --deletion-protection
gcloud sql instances patch orders-db --deletion-protection
Копии в другом проекте. Правило, которое отличает настоящую защиту от формальной: копия лежит в проекте с другими правами. Тогда тот, кто может удалить данные, не может удалить копию — а именно это требуется от резерва. Для хранилища объектов это отдельный проект с отдельным списком доступа.
Блокировка хранения на бакете с копиями. Политика хранения с блокировкой делает удаление объектов невозможным до истечения срока — для всех, включая владельца. Разбор — в статье про объектное хранилище; для темы восстановления это опорный механизм.
Ограничение прав на удаление. Роль, которая позволяет создавать и менять, но не удалять, — обычная практика для команд; право удалять остаётся у узкой группы или только у конвейера.
Порядок внедрения: сначала это (дёшево, быстро, закрывает самый вероятный сценарий), потом высокая доступность в регионе, и только потом второй регион.
Где это применяется
Практический минимум для боевого сервиса: копии приложения в нескольких зонах за балансировщиком, Cloud SQL с резервом в другой зоне и автопереключением, регулярные копии с осознанным RPO и хотя бы раз проверенным восстановлением. Этого достаточно, чтобы пережить самые частые сбои без потери данных и с предсказуемым простоем.
Типичные ошибки новичков:
- всё в одной зоне — «отказоустойчивая» система падает целиком при аварии зоны;
- нет резервных копий, потому что «есть же реплики» — реплики повторяют и ошибочное удаление;
- никогда не проверяли восстановление — узнают о битых бэкапах в день аварии;
- не договорились про RPO/RTO — строят наугад, переплачивая или недозащищаясь.
Глубже: резерв базы это не реплика для чтениярасширенное
Частое и дорогое заблуждение: в режиме высокой доступности у управляемой базы есть резервный экземпляр, и кажется, что с него можно читать отчёты. Нельзя.
Резервный экземпляр не читается вовсе. Он существует только для переключения при отказе: данные на него приходят синхронно, но подключиться к нему нельзя. Это не удвоение мощности и не место для аналитики — это страховка.
Реплика для чтения — отдельный ресурс. Её создают явно, она асинхронная (отстаёт), и с неё читают тяжёлые запросы и отчёты. Отставание обычно небольшое, но «прочитать только что записанное» с неё нельзя — это надо учитывать в коде.
Для восстановления региона нужна межрегиональная реплика. Режим высокой доступности работает внутри региона (резерв в другой зоне) и не спасает от отказа региона целиком. Чтобы иметь возможность подняться в другом регионе, создают реплику в другом регионе — и именно её при аварии повышают до самостоятельной базы.
Три числа к этому: переключение на резервный экземпляр занимает порядка минуты и рвёт соединения (приложение обязано переподключиться); повышение межрегиональной реплики до самостоятельной базы — минуты, и операция односторонняя (обратно реплику так просто не сделать); автоматические копии по умолчанию хранятся около недели и позволяют восстановиться на момент времени внутри этого срока — но восстановление создаёт новый экземпляр, а не откатывает существующий.
Отсюда практическая раскладка: высокая доступность в регионе — почти всегда (это защита от обычных отказов), реплика для чтения — когда есть отчёты, межрегиональная реплика — когда требование к восстановлению региона записано, а не предполагается.
Глубже: как проверять восстановлениерасширенное
«Копия, из которой не восстанавливали, — не копия» — правило, у которого должна быть процедура.
Что делают. Раз в квартал восстанавливают копию базы в отдельный проект, поднимают там приложение и прогоняют проверки. Отдельный проект здесь принципиален: он изолирует учение от боевого контура и заодно проверяет, что описание инфраструктуры действительно работает с нуля.
Что замеряют. Три числа: сколько времени заняло восстановление (сравнить с заявленным RTO), сколько данных потеряно (сравнить с RPO), сколько шагов пришлось делать не по документу. Последнее — самое полезное: каждый такой шаг дописывают в процедуру.
Что проверяют, кроме данных. На учении выясняется, что данных недостаточно: нужны секреты (они в другом проекте и их надо продублировать), образы контейнеров (реестр региональный — нужна репликация), ключи шифрования (данные, зашифрованные ключом из упавшего региона, не расшифруются), записи в службе имён с коротким временем жизни, сертификаты, квоты в резервном регионе и права дежурного на переключение. Этот список каждый раз пополняется — и в этом смысл учений.
Как проверять отказы, а не только копии. Для управляемой базы есть штатная кнопка принудительного переключения — ей проверяют, переподключается ли приложение и сколько это занимает. Для отказа зоны — гашение всех экземпляров в зоне. Для отказа зависимости — искусственная задержка или обрыв. Начинают с самого дешёвого (отказ одного экземпляра) и идут вверх.
И то, что тренируют отдельно: возврат. Команда, которая переключалась и ни разу не возвращалась, в реальной аварии остаётся в резервном регионе на недели, потому что возврат требует обратной репликации, окна и решения о данных, накопленных за время аварии.
Результат учения — не отчёт «успешно», а список правок в процедуре и в инфраструктуре. Если после учения ничего не поправили, оно было формальным.
Коротко
- Отказоустойчивость переживает отказ части системы без остановки, восстановление поднимает систему после крупной аварии; первое строят в архитектуре, второе это план и копии.
- Зоны одного региона против отказа дата-центра, мультирегион с глобальным балансировщиком против аварии региона; репликация между регионами асинхронная, и последние секунды записей теряются.
- Четыре стратегии по возрастанию цены: копии и восстановление, дежурная лампочка с межрегиональной репликой, тёплый резерв, две живых площадки; берут первую сверху, которая укладывается в RPO и RTO, а в GCP переход к второй дёшев благодаря коду инфраструктуры.
- RPO это сколько данных теряем, RTO как быстро поднимаемся; оба числа называет бизнес.
- Реплики повторяют ошибочное удаление: спасают копии Cloud SQL по расписанию, PITR по журналам, снимки дисков с оговоркой о согласованности, версионирование и мягкое удаление в Cloud Storage; копия, которую не восстанавливали, это предположение.
- Резерв высокой доступности не читается, реплика для чтения это отдельный асинхронный ресурс, а для восстановления региона нужна межрегиональная реплика; переключение занимает минуту и рвёт соединения.
- Самый вероятный сценарий это удаление, в GCP вплоть до всего проекта: защита от удаления у ресурсов, копии в проекте с другими правами, блокировка хранения на бакете, право удалять у узкой группы.
- Учения: раз в квартал восстановить копию в отдельный проект, замерить время, потерю и шаги мимо документа, проверить секреты, образы и права, принудительно переключить базу и потренировать возврат.
Что почитать дальше
- Масштабирование и доступность в GCP — как строится доступность в норме.
- Cloud Storage — где хранят копии и что такое блокировка хранения.
- Основы GCP — проект как граница, которую уносит удаление.
- Отказоустойчивость и восстановление в облаке — та же пара задач без привязки к провайдеру.