golang

Автоматизиция деплоя контейнеров в Yandex Cloud с помощью Terraform и LLM

  • пятница, 10 апреля 2026 г. в 00:00:10
https://habr.com/ru/articles/1020612/

Хочу поделиться историей о том, как вайб-кодинг решил мою вполне реальную инженерную боль. Без пафоса, без “я построил 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, а дальше — ручной труд. Как и большинство инженеров, я ленив в правильном смысле этого слова. А ещё у меня есть почётное звание вайб-кодера и бейдж в подтверждение.

Официальный Vibe coder 😄
Официальный Vibe coder 😄

Поиск готового решения

Первым делом пошёл искать готовое решение в официальных примерах 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)

Сценарий:

  1. docker push

  2. Container Registry генерирует событие

  3. Trigger вызывает Cloud Function

  4. Функция создаёт новую ревизию Serverless Container

Итог — ноль ручных действий.

Как было

Состояние до автоматизации
Состояние до автоматизации

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

Как стало

Решение состоит из двух workflow:

  1. Создание автоматизации (один раз)

Создание функции и триггера
Создание функции и триггера

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

  1. Автоматический редеплой (событие обновления версии образа)

Схема автоматизации
Схема автоматизации

Теперь после 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 справился, но не с первого раза. Несколько итераций с походами в документацию, уточнениями — и нужный набор ролей собрался. Для запуска функции, создания ревизий контейнера, работы с триггерами. Терраформ всё это аккуратно описал.

Минимальный набор ролей, который у меня заработал:

Role

Purpose

container-registry.images.puller

Стягивание образова с Container Registry

functions.editor

Создание и управление Cloud Functions

iam.serviceAccounts.admin

Создание и связывание runtime сервисных аккаунтов

resource-manager.admin

Управление ресурсами папки

serverless-containers.editor

Создание и управление Serverless Containers

serverless.functions.invoker

Вызов Cloud Functions

Без них вы почти гарантированно получите 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, формат был примерно знаком. Для того чтобы мне получить полный формат сообщений ранее смотрел скринкаст от сотрудников облака, в котором они показали полный пример обработки сообщений с описанием контракта.

Докинул агенту контекст про структуру событий, подправил обработчик — и получил рабочую версию.

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

Как повторить

  1. Клонировать репозиторий: https://github.com/sshaplygin/redeploy-container-yc

  2. Настроить переменные Terraform

  3. Запустить:

terraform init
terraform apply
  1. Запушить новый образ:

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 и уходить на ферму растить гусей?

Кому интересно, как трансформируется сфера разработки, рекомендую посмотреть: