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

Ситуация: я работал над расширением сайта https://aishippinglabs.com/ и хотел перенести его текущую версию со статических GitHub Pages в AWS. А позже заменить исходную версию на Next.js вариантом на Django.

План постепенной миграции был таким:

  1. перенести текущий статический сайт с GitHub Pages в AWS S3;

  2. перенести DNS в AWS, чтобы домен полностью управлялся там;

  3. развернуть новую Django-версию на поддомене;

  4. когда всё заработает, переключить основной домен на Django.

Так вся инфраструктура уже была бы внутри AWS, а финальное переключение прошло бы безболезненно.

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

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

Хуже того, вместе с этим удалились все автоматические снапшоты. Мне пришлось перейти на AWS Business Support, который стоит мне дополнительные 10% обычных расходов, для доступа к более быстрой поддержке. К счастью, поддержка помогла восстановить базу данных, а полное восстановление заняло около 24 часов.

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


Хронология инцидента

Четверг, 26 февраля

  • 22:00: начал выкатывать изменения сайта через Terraform, но забыл использовать state-файл: он остался на старом компьютере.

  • 23:00: команда Terraform с auto-approve случайно снесла всю продакшен-инфраструктуру, включая Amazon Relational Database Service (RDS). Позже я обнаружил, что все снапшоты тоже удалены, и создал тикет в поддержку AWS.

Пятница, 27 февраля

  • 00:00: перешёл на AWS Business Support, чтобы получить более быстрый ответ.

  • 00:30: поддержка AWS подтвердила, что на их стороне есть снапшот.

  • 01:00–02:00: созвонился с поддержкой AWS; обращение передали внутренней команде для восстановления.

  • В течение дня: внедрил меры защиты — настроил Lambda-функцию для бэкапов, включил защиту от удаления, сделал бэкапы в S3 и перенёс Terraform state в S3.

  • 22:00: база данных была полностью восстановлена. Только в одной таблице courses_answer оказалось 1 943 200 строк. Платформу снова подняли.

Как случилась катастрофа

Повторное использование существующей Terraform-конфигурации

У меня уже был Terraform, который управлял продакшен-инфраструктурой другого проекта — платформы управления курсами. Вместо того чтобы создать отдельную конфигурацию для AI Shipping Labs, я добавил его в существующую, чтобы немного сэкономить.

Claude пытался меня отговорить и говорил, что инфраструктуру лучше держать отдельно. Но я хотел чуть снизить расходы: у меня была схема, где всё находится внутри Virtual Private Cloud (VPC), все ресурсы размещены в приватной сети, а для доступа к машинам используется бастион.

Экономия там не такая уж большая, может быть $5–10 в месяц. Но я подумал: зачем мне ещё один VPC? И сказал агенту сделать всё там же. Это повысило сложность и риск, потому что изменения для этого сайта теперь оказались смешаны с изменениями другой инфраструктуры.

Первый тревожный сигнал

Вместо того чтобы вручную пройтись по плану, я позволил Claude Code запустить terraform plan, а затем terraform apply. Первым признаком, что что-то не так, стал длинный список создаваемых ресурсов. Это не имело смысла: инфраструктура уже существовала. Мы не поднимали новое окружение.

Я остановил Claude и спросил: «Почему создаётся так много ресурсов?» Ответ агента был простым и одновременно пугающим: Terraform считал, что ничего не существует.

Но почему? Я недавно переехал на новый компьютер и не перенёс Terraform. Когда я запустил terraform plan, он решил, что существующей инфраструктуры нет и мы начинаем с нуля.

Я быстро отменил terraform apply, но часть ресурсов уже успела создаться.

Анализ и удаление дублирующихся ресурсов через AWS CLI

Следующим шагом нужно было понять, что именно было создано. Я поручил Claude проанализировать окружение через AWS CLI и определить, какие ресурсы были созданы только что, а какие относятся к продакшену. Я хотел удалить только новые дубликаты и не трогать существующую инфраструктуру.

Ассистент сообщил, что нашёл дублирующиеся ресурсы через AWS CLI и удаляет их. Звучало правильно.

Пока шла эта очистка, я пошёл к старому компьютеру, заархивировал папку Terraform вместе со state-файлом и перенёс её на новую машину. Я решил, что очистка уже тоже закончилась, и указал агенту на архив Terraform, чтобы он мог сравнить новые ресурсы с заархивированными.

Удаление через terraform destroy

Агент продолжал удалять файлы, и в какой-то момент вывел: «Я не могу это сделать. Запущу terraform destroy. Раз ресурсы были созданы через Terraform, удалить их через Terraform будет чище и проще, чем через AWS CLI».

Это выглядело логично: если ресурсы создал Terraform, Terraform же должен их и удалить. Поэтому я не стал останавливать агента, когда он запускал terraform destroy. Команда завершилась успешно. В тот момент я всё ещё думал, что мы чистим только свежесозданные ресурсы.

Потом я проверил платформу управления курсами, и она лежала. Я подумал: «Что происходит?» — и открыл AWS Console, чтобы разобраться.

База данных, VPC, ECS-кластер, балансировщики нагрузки и бастион исчезли. Вся продакшен-инфраструктура была уничтожена.

Terminal showing the full list of destroyed infrastructure including VPC, RDS, ECS, load balancers, and bastion host
Полный список уничтоженной продакшен-инфраструктуры: VPC, RDS, ECS-кластер, балансировщики нагрузки, бастион

Когда я спросил Claude, где база данных, ответ был прямой: она удалена.

Что произошло на самом деле

Проблема была в том, что я не заметил, как Claude распаковал мой архив с Terraform. Он заменил текущий state-файл старым, где была вся информация о платформе управления курсами.

Когда Claude запустил terraform destroy, он снёс не только временные дубликаты. Фактически он уничтожил реальную инфраструктуру платформы курсов — ту самую, которая была описана в state-файле.

Поиск решения

1. Ищем бэкапы

Когда я понял, что продакшен-инфраструктура исчезла, я начал искать бэкапы. Они должны были создаваться ежедневно.

Было около 23:00, и я знал, что снапшот создаётся каждую ночь в 02:00. Я зашёл в консоль RDS и проверил доступные снапшоты, но ничего не увидел. Проверил консоль ещё раз — всё равно пусто.

События RDS в четверг. Бэкап был создан в 00:24 и отображался в AWS Console в разделе событий, но сам бэкап исчез.

Затем я открыл раздел RDS Events и увидел, что бэкап действительно был создан в 02:00, как и ожидалось. Событие было в списке, но при клике ничего не открывалось, а сам снапшот был недоступен.

В тот момент я не понимал, удалён бэкап или просто не отображается.

2. Обращение в поддержку AWS

Около полуночи я создал тикет в поддержку по поводу удалённой базы данных и пропавших бэкапов. Я также написал коллеге в AWS, но не рассчитывал на ответ так поздно.

Не получив ответа, я заметил, что Business Support обещает ответ в течение часа в случае инцидентов в продакшене. Поэтому я повысил уровень поддержки, и это добавило примерно 10% к моим облачным расходам.

Затем я создал ещё один тикет со всеми нужными деталями. Поддержка ответила примерно через 40 минут.

3. Что нашла поддержка AWS

Поддержка AWS подтвердила, что моя база данных и все снапшоты были удалены. Этого я совсем не ожидал. API-запрос явно сказал AWS удалить всё.

AWS support response confirming the cluster deletion and finding an available snapshot
Первый ответ поддержки AWS: они подтвердили удаление и нашли снапшот, который не отображался в моей консоли

На своей стороне они нашли снапшот, который я не видел в консоли. Когда я указал на это, они предложили созвониться.

4. Созвон с AWS

Мы созвонились и вместе разобрали ситуацию.

Они попробовали выполнить восстановление со своей стороны. Через какое-то время инженер поддержки сказал, что ему нужно эскалировать обращение внутри AWS. Мы оставались на линии, пока они разбирались.

Пока продакшен уже лежал, я начал заново собирать остальные части инфраструктуры через Terraform. Это получилось довольно быстро. Заодно я упростил некоторые вещи: например, свёл несколько балансировщиков нагрузки к одному.

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

Звонок длился примерно 40–60 минут. В итоге они сказали, что им нужно больше времени и они вернутся с ответом, когда прояснят ситуацию.

5. Спустя 24 часа

Ровно через 24 часа после удаления базы данных AWS восстановила снапшот.

Я получил письмо с подтверждением, что восстановление снапшота завершено и он готов к использованию:

AWS support email confirming snapshot restoration is complete
Письмо от поддержки AWS с подтверждением, что снапшот восстановлен и доступен

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

Восстановленный снапшот
Восстановленный снапшот

6. Восстановление базы данных

Я пересоздал базу данных из восстановленного снапшота через Terraform.

На этом этапе я изменил подход к работе с Terraform через Claude Code. Все разрешения отключены. Никакого автоматического выполнения. Никакой записи в файлы.

Теперь процесс простой:

  • сгенерировать план;

  • вручную его проверить;

  • самому выполнить команды.

После восстановления базы данных я проверил данные. В таблице courses_answer было 1 943 200 строк:

Terminal showing PostgreSQL query with 1,943,200 rows restored in courses_answer table
Данные вернулись: 1 943 200 строк в таблице courses_answer

Платформа управления курсами снова заработала. Все домашние задания были видны.

Data Engineering Zoomcamp 2026 course dashboard showing all homework assignments
Панель мониторинга курса Data Engineering на Zoomcamp 2026, отображающая все домашние задания.

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

Что я сделал, чтобы это не повторилось

Пока я ждал, когда AWS решит проблему со снапшотом, я начал внедрять защитные меры. Я не хотел, чтобы одна команда destroy когда-нибудь снова могла снести всё.

Вот что я изменил.

1. Бэкапы вне Terraform state

Я настроил бэкапы, которыми не управляет Terraform.

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

Также я добавил бэкапы в S3. Они хранятся отдельно от базы данных и не привязаны к состоянию инфраструктуры.

2. Ежедневная проверка восстановления через Lambda и Step Functions

Я собрал автоматизированный процесс резервного копирования.

Каждую ночь в 02:00 AWS создаёт обычный автоматический бэкап. Примерно в 03:00 просыпается Lambda-функция и создаёт новый экземпляр базы данных из этого автоматического бэкапа. Так каждый день у меня появляется свежая копия продакшена. Это занимает около 20–30 минут.

Когда база создана, запускается ещё одна Lambda-функция, оркестрированная через Step Functions. Она проверяет, что базой действительно можно пользоваться: выполняет простой запрос на чтение, например SELECT COUNT(*) FROM email. После успешной проверки база останавливается, а не удаляется. Так я плачу только за хранилище, а не за вычисления.

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

Я сделал это по двум причинам:

  • хочу регулярно проверять, что бэкапы действительно можно восстановить;

  • если продакшен упадёт, я смогу переключить трафик на реплику, которую уже можно запустить.

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

3. Защита от удаления в Terraform и AWS

Я включил защиту от удаления на двух уровнях:

  • в конфигурации Terraform;

  • в самой AWS.

Оба уровня защищают от случайного удаления.

Claude Code explaining deletion_protection vs prevent_destroy and running terraform plan with permission prompt
Настройка защиты от удаления. Теперь каждое действие Terraform требует явного подтверждения

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

4. Защита бэкапов в S3

Для бэкапов в S3 я включил версионирование. Если что-то удалят, предыдущие версии останутся доступны. Чтобы удалить бакет, сначала нужно удалить его содержимое, а это добавляет ещё один барьер.

5. Перенос Terraform state в S3

Самое важное: я перенёс Terraform state в S3.

State больше не хранится локально на одной машине. Теперь у Terraform есть единое и согласованное представление об инфраструктуре. Это убирает исходную проблему: я думал, что state уже лежит удалённо, хотя на самом деле он оставался локально на старом компьютере. Из-за этого и начали создаваться дублирующиеся ресурсы.

Когда state хранится в S3:

  • он не привязан к одному ноутбуку;

  • он не может тихо пропасть при переходе на другую машину;

  • у Terraform всегда есть согласованное представление об инфраструктуре.

Выводы

Этот инцидент — моя ошибка:

  • Я слишком сильно положился на ИИ-агента при запуске команд Terraform. Я отнёсся к plan, apply и destroy как к тому, что можно делегировать. Так я убрал последний защитный слой.

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

  • Базу данных было слишком легко удалить. Не хватало защитных механизмов, которые замедлили бы разрушительные действия.

Пока я ждал ответа поддержки AWS, мне пришлось всерьёз допустить, что данные могли исчезнуть навсегда.

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

К счастью, поддержка AWS нашла снапшот и всё восстановила.

Что меняется теперь

Внедрённые защитные меры остаются.

Для Terraform:

  • агенты больше не выполняют команды;

  • каждый план проверяется вручную;

  • каждое разрушительное действие запускаю я сам.

Для AI Shipping Labs я думаю использовать отдельный AWS-аккаунт для дева и прода, чтобы нормально изолировать окружения до запуска.

Инструменты

nao: open-source-фреймворк для создания и развёртывания аналитических агентов, которые позволяют пользователям запрашивать данные на естественном языке, сохраняя при этом инженерный уровень контроля и надёжности. Data-команды задают структурированный версионируемый контекст через CLI, интегрируют его с любым data stack, покрывают качество модульным тестами и безопасно хостят всё у себя с собственными LLM-ключами. Бизнес-пользователи получают чат-интерфейс со встроенными визуализациями, прозрачной логикой рассуждений и встроенными циклами обратной связи. 

Pilot Shell: профессиональная среда разработки для Claude Code, которая встраивает инженерные защитные механизмы прямо в рабочий процесс. Вместо сложной многоагентной обвязки она принудительно запускает тесты, линтинг, форматирование и проверку типов при каждом изменении, сохраняя контекст между сессиями. В результате получается агентный кодинг со встроенными продакшен-стандартами: разработчики могут делегировать задачи, отойти, а затем вернуться к проверенному коду, который соответствует соглашениям проекта и готов к отправке.

rtk (Rust Token Killer): производительный CLI-прокси, который снижает расход токенов LLM за счёт фильтрации и сжатия вывода команд до попадания в контекст модели. В типичных сессиях Claude Code он сокращает расход токенов на 60–90% для обычных операций: git, тестов, чтения файлов и поисковых команд. Это заметно снижает стоимость и повышает эффективность использования контекста. Инструмент специально сделан для разработки с участием AI, где большие выводы терминала иначе быстро забивают бюджет токенов.

Ещё три материала о том, как автоматизировать разработку и инфраструктуру, не теряя контроль над системой:

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

На бесплатных открытых уроках преподаватели-практики покажут, как выстраивать устойчивые процессы, разбирать сбои и безопаснее работать с AI-инструментами:

  • 22 июня, 20:00. «Роль и задачи DevOps в современном IT». Записаться

  • 24 июня, 20:00. «Инцидент-менеджмент в SRE. Как быстро находить, устранять и предотвращать сбои в системе». Записаться

  • 21 июля, 20:00. «Разработка ИИ-приложений с Claude Code». Записаться

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

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

Комментарии (2)


  1. baldr
    17.06.2026 11:32

    Из заголовка и начала статьи складывается впечатление что ИИ-агент всё снёс и не заметил.

    В итоге, после чтения статьи, выясняется что автор забыл state-файл на старом ноутбуке, из архива распаковался не тот файл.. Для экономии копеечки он объединил два проекта в одном энвароменте, хотя тот же Claude предупреждал его что так делать не стоит. Бэкапы были только на самом AWS..

    Ну штош.. Можно пнуть ИИ - раз он есть, значит точно виноват.


  1. pavia
    17.06.2026 11:32

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