Хочу поделиться историей о том, как вайб-кодинг решил мою вполне реальную инженерную боль. Без пафоса, без “я построил SaaS стартап за вечер” — просто задача, Claude и пару вечеров свободного времени.
Делюсь мыслями о работе, жизни и небольшими наблюдениями из будней разработчика в своём Telegram-канале
После показа драфта статьи Николай М. подсказал готовый репозиторий GitHub Action для деплоя Serverless Container в Yandex Cloud, который решает проблему с автоматизацией. Этот факт меня не остановил, чтобы поделиться своим опытом
О чём эта статья
В этой статье покажу, как автоматизировать деплой Serverless Container в Yandex Cloud при пуше нового образа в Container Registry.
Что вы получите:
готовый подход к автоматическому редеплою контейнеров на Go
пример архитектуры на CR Trigger + Cloud Function
Terraform-конфигурацию для развёртывания
список необходимых IAM-ролей (самая болезненная часть)
Проблема
Я использую Yandex Cloud как площадку для экспериментов. Быстро поднять сервис, проверить гипотезу, поиграться — для этого облако подходит отлично.
Но одна вещь меня бесила.
После каждого docker push приходилось:
открыть веб консоль
найти контейнер
вручную обновить образ
создать новую ревизию
Кадый. Раз.
Всё до Container Registry уже автоматизировано (CI/CD) с помощью github actions, а дальше — ручной труд. Как и большинство инженеров, я ленив в правильном смысле этого слова. А ещё у меня есть почётное звание вайб-кодера и бейдж в подтверждение.

Поиск готового решения
Первым делом пошёл искать готовое решение в официальных примерах Yandex Cloud. Ничего. Для меня до сих пор странно, что такой базовой функции нет из коробки — пушнул образ, контейнер обновился. Казалось бы.
Обратился в саппорт. К слову, по моему опыту поддержка в облаке Yandex Cloud — один из самых профессиональных. Они не раз выручали в различных вопросах. В этот раз ответ был честный:
“Готового решения нет, стройте своё”
Ближе всего по архитектуре оказался yc-cr-image-scanning — пример с триггером на Container Registry и облачной функцией. Как раз данный функционал уже доступен из коробки облака. Отправная точка нашлась.
Окей.
Сдул пыль с подписки на Claude, заварил чай и отправился в увлекательное путешествие с бездушной машиной в качестве напарника.
Задача
Дано: образ пушится в Container Registry Нужно: Serverless Container автоматически переезжает на новую версию образа. Ограничения: подписка Claude Code за $20, примерно час вечернего времени и горящее нетерпение от ручных кликов.
Архитектура решения
Решение состоит из двух частей.
1. Развёртывание инфраструктуры (один раз)
Terraform
Cloud Function (Go)
Container Registry Trigger
Service Account + IAM роли
2. Автоматический редеплой (каждый push)
Сценарий:
docker pushContainer Registry генерирует событие
Trigger вызывает Cloud Function
Функция создаёт новую ревизию Serverless Container
Итог — ноль ручных действий.
Как было

Всё до Container Registry работало автоматически. А дальше — ручной труд: открыть консоль, найти контейнер, обновить образ, раскатить. Пунктиром — то, что хотелось автоматизировать.
Как стало
Решение состоит из двух workflow:
Создание автоматизации (один раз)

Terraform через GitHub Actions создаёт всю инфраструктуру: облачную функцию, триггер на Container Registry и сервисный аккаунт с нужными ролями.
Автоматический редеплой (событие обновления версии образа)

Теперь после docker push всё происходит само: триггер ловит событие, функция подхватывает и создаёт новую ревизию контейнера с обновлённым образом. Ноль кликов.
Реализация
В место моих рук, за меня практически все кодогенерировал мой напарник - Claude Code.
Cloud Function (Go)
Функция получает событие о пуше образа и извлекает имя образа:
// упрощённый пример func Handler(ctx context.Context, event TriggerEvent) (string, error) { // Парсинг события обновлении версии образа eventData, _ := parseEvent() // Получение данных для ЧТО хотим обновить config, _ := parseConfig() // Получение IAM-токена для проведения операции token, _ := getIAMToken() // Получение текущей ревизии контейнера для обновления rev, _ := getCurrentRevision() // вызов API для создания новой ревизии return deployRevision(token, containerID, rev) }
Ключевая задача — корректно распарсить событие.
Terraform
Terraform создаёт всю инфраструктуру:
Cloud Function
Trigger
Service Account
Подробнее можно ознакомиться в исходниках
Роли и доступы
Это основная болененная часть.
Этот этап занял достаточно времени на вымайнивание правильных ролей для сервисного аккаунта. Тот, кто работал с IAM в облаках, знает это ощущение — когда всё логично, но permission denied сыплется на каждом шагу без какой-либо дополнительной инфомарции.
Claude справился, но не с первого раза. Несколько итераций с походами в документацию, уточнениями — и нужный набор ролей собрался. Для запуска функции, создания ревизий контейнера, работы с триггерами. Терраформ всё это аккуратно описал. Важный момент, который легко упустить: наборов ролей здесь два, и принадлежат они разным сервисным аккаунтам. Путать их не стоит — это разница между «функция умеет обновить контейнер» и «функция умеет всё в каталоге».
1. Сервисные аккаунты рантайма — то, с чем живёт решение постоянно
Role | Кому | Зачем |
|---|---|---|
| SA функции | Создание новой ревизии контейнера |
| SA функции | Ревизия копируется вместе с |
| SA функции | Если в конфигурации ревизии есть подключение к VPC — облако проверяет |
| SA триггера | Вызов функции по событию из Container Registry |
Никакого resource-manager.* тут нет и не нужно.
2. Сервисный аккаунт, от которого выполняется terraform apply — живёт в CI и нужен только в момент раскатки:
Role | Зачем |
|---|---|
| Создание функции и триггеров |
| Создание runtime-аккаунтов и привязка их к функции и триггеру |
| Назначение ролей на каталог |
И вот resource-manager.admin — ровно то место, где хочется поставить роль поуже и не получится. resource-manager.editor умеет создавать и удалять каталоги, но не умеет менять права доступа: разрешения setAccessBindings / updateAccessBindings есть только у resource-manager.admin (и у примитивной admin). А Terraform здесь как раз раздаёт роли сервисным аккаунтам через yandex_resourcemanager_folder_iam_member — то есть на editor всё упадёт с permission denied прямо на apply.
Если широкая роль в CI смущает — а смущать она должна — лечится это не заменой роли, а выносом IAM за пределы CI: один раз создать оба сервисных аккаунта и выдать им роли отдельно, под администратором, а из основного конфига yandex_resourcemanager_folder_iam_member убрать. Тогда деплойному аккаунту хватит functions.editor плюс iam.serviceAccounts.user на два конкретных SA — и resource-manager.* не нужен вовсе. Цена — роли перестают быть частью того же terraform apply.
Рантайм тоже можно сузить. serverless-containers.editor на каталог означает, что функция может переписать ревизию любого контейнера в нём. Список целевых контейнеров у функции и так зафиксирован в IMAGE_CONTAINER_MAP, так что роль выдаётся на конкретный контейнер через yandex_serverless_container_iam_binding, а iam.serviceAccounts.user — на конкретный аккаунт через yandex_iam_service_account_iam_member. Для vpc.user ресурса уровня сети в провайдере нет, она остаётся на каталоге.
Ещё одна роль, которую регулярно приписывают не туда, — container-registry.images.puller. Ни деплойному аккаунту, ни функции она не нужна: образ тянет сервисный аккаунт самого контейнера при старте ревизии.
Без нужных ролей вы почти гарантированно получите permission denied на каждом шаге — причём облако не подскажет, какой именно роли не хватает.
Формат событий
А вот тут было интересно.
Агент не знал формат событий Container Registry. Это не SQS, хотя Yandex Message Queue рядом и API вроде бы “SQS-compatible”. На практике формат событий для обработчиков отличается, и примеров в открытом доступе мало.
Формат событий для YMQ:
{ "messages": [ { "event_metadata": { "event_id": "abc123", "event_type": "yandex.cloud.events.containerregistry.ImagePushed", "created_at": "2026-03-19T18:12:00Z", "cloud_id": "b1g...", "folder_id": "b1f..." }, "details": { "registry_id": "crp123", "repository_name": "crp123/urlshortener", "tag": "latest", "image_id": "sha256:abc...", "image_digest": "sha256:def..." } } ] }
Как я дошел до того, что события имеют формат YMQ? Мне помогло немного наблюдения. В интерфейсе заметил, что у триггеров есть dead letter queue. Предположил, что под капотом события летят через очередь. А так как раньше уже писал обработку событий из Yandex Message Queue, формат был примерно знаком. Для того чтобы мне получить полный формат сообщений ранее смотрел скринкаст от сотрудников облака, в котором они показали полный пример обработки сообщений с описанием контракта.
Докинул агенту контекст про структуру событий, подправил обработчик — и получил рабочую версию.
Момент, когда после пуша образа контейнер сам обновился, ощущался как маленькая победа.
Как повторить
Настроить переменные Terraform
Запустить:
terraform init terraform apply
Запушить новый образ:
docker push $your_image_name
После этого контейнер обновится автоматически. Подробнее по шагам все есть в README.md проекта
Роль AI (и где он не справился)
Большая часть кода была сгенерирована с помощью LLM.
Что он сделал хорошо:
ускорил написание Terraform
помог с IAM ролями
сократил цикл «гипотеза → проверка»
Где не справился:
не знал формат событий
не хватало контекста по Yandex Cloud. Пришлось явно указывать документации на terraform ресурса
Результат
Получился открытый репозиторий — облачная функция на Go + Terraform для всей инфраструктуры. При пуше образа в Container Registry функция автоматически создаёт новую ревизию Serverless Container с обновлённым образом. Надеюсь, что коллеги из облака возьмут мои наработки и по умолчанию добавят возможность обновления контейнеров по аналогии с функцией проверки образов на уязвмости.
Бонусом — деплой новой функции и триггера через GitHub Actions, без необходимости запускать Terraform локально.
Послесловие
Справился бы я без ИИ-агента? Конечно. Но потратил бы пару не вечеров, а скорее все выходные. Основная ценность — не в том, что агент написал код за меня, а в том, что он сократил цикл «гипотеза → проверка → исправление».
Особенно в работе с IAM-ролями и незнакомым API, где каждый шаг — это поход в документацию, которой может в природе еще и не существовать.
При этом агент не справился бы сам. Контекста про формат событий Yandex Cloud в открытом интернете недостаточно. Понадобился мой опыт и инженерная интуиция — подсказать, куда смотреть и как интерпретировать то, что вижу в интерфейсе. Вайб-кодинг — это не «агент делает всё», это совместная работа. Ты ведёшь, он ускоряет.
AI — это инструмент получения быстрого прототипа, но не замена инженера.
Если вы используете Yandex Cloud и сталкивались с ручным редеплоем контейнеров — этот подход может сэкономить вам время.
Что думаете — вайб-кодинг делает нас эффективнее, или пора бросать IT и уходить на ферму растить гусей?
Кому интересно, как трансформируется сфера разработки, рекомендую посмотреть:
Исследование Anthropic «How AI Impacts Skill Formation» — эксперимент показал, что чрезмерная зависимость от ИИ при изучении нового может ослаблять формирование навыков. Продуктивность — не то же самое, что обучение
Доклад Стэнфорда об эффективности инженеров с ИИ с взгляд исследователей на то, как ИИ-инструменты меняют работу разработчиков
UPD: Спасибо за комментарий от @KonkovDV Полез самостоятельно в доку, чтобы верифицировать набор ролей и предоставляемых доступов, которые нужны для все процесса. Актуализировал блок про Роли и доступы и подробнее описал что и кому нужно

