adr: записана локальная сборка образов вместо Yandex Container Registry
Постфактум по сегодняшней работе: почему ушли от cr.yandex к роли app_image (упрощение деплоя без раннера + сокращение секретов) и чем за это платим.
This commit is contained in:
@@ -0,0 +1,78 @@
|
|||||||
|
# Локальная сборка образов вместо Yandex Container Registry
|
||||||
|
|
||||||
|
- Дата: 2026-07-25
|
||||||
|
|
||||||
|
## Контекст
|
||||||
|
|
||||||
|
Три приложения собственной разработки — homepage, transcriber, remembos —
|
||||||
|
деплоились через Yandex Container Registry. Схема у всех одинаковая: образ
|
||||||
|
собирается локально, пушится в `cr.yandex/...` отдельным плейбуком
|
||||||
|
(`playbook-*-registry.yml`), плейбук деплоя делает `docker_login` с
|
||||||
|
`yc_oauth_token`, а compose тянет образ по registry-пути с тегом, зашитым в git.
|
||||||
|
|
||||||
|
Схема тянула за собой три проблемы.
|
||||||
|
|
||||||
|
**Секрет несопоставимого радиуса.** Ради одного `docker login` в vault лежал
|
||||||
|
OAuth-токен всего аккаунта Yandex Cloud — реестр, виртуалки, биллинг. 24 июля он
|
||||||
|
вместе с ещё 52 переменными ушёл открытым текстом в транскрипт: цена одной такой
|
||||||
|
утечки — весь аккаунт, а не один сервис.
|
||||||
|
|
||||||
|
**Разнесённый деплой.** Сборка жила в `task deploy` репозитория приложения,
|
||||||
|
который сам звал `ansible-playbook`. У transcriber этот таск дополнительно правил
|
||||||
|
`vars/transcriber.images.yml` в чужом репозитории через `yq` и делал там `git
|
||||||
|
commit` с новым тегом. У remembos registry-плейбука не было вовсе — образ пушился
|
||||||
|
руками, а в compose стоял тег `v0.2.0`, вбитый в git. У homepage тег был
|
||||||
|
плавающий `:latest`, то есть ночной `docker image prune` мог подтянуть другое
|
||||||
|
содержимое без возможности отката.
|
||||||
|
|
||||||
|
**Автоматизировать сборку пока нечем.** Стабильного онлайн-раннера для
|
||||||
|
workflow gitea у нас нет (отдельная задача — раннер on-demand), так что уехать в
|
||||||
|
CI сборки не могут. Плюс после переезда сервера в Timeweb реестр остался
|
||||||
|
единственной ниткой, тянущейся в Yandex Cloud.
|
||||||
|
|
||||||
|
## Решение
|
||||||
|
|
||||||
|
Приложения переведены на общую роль `app_image` (канон —
|
||||||
|
`~/projects/private/ansible-roles`, в репозитории лежит завендоренная копия в
|
||||||
|
`roles/`, синхронизация — `inv roles-pull`/`roles-push`). Роль:
|
||||||
|
|
||||||
|
1. генерит случайный `BUILD_ID` — он же тег образа;
|
||||||
|
2. запускает в директории приложения его собственную команду сборки (контракт —
|
||||||
|
`task image`, `BUILD_ID` приходит через окружение), приложение обязано собрать
|
||||||
|
полный образ и затегать его `<app_image_name>:$BUILD_ID`;
|
||||||
|
3. печатает размер архива, везёт его на сервер через `docker save` → `copy` →
|
||||||
|
`docker load`;
|
||||||
|
4. отдаёт факт `app_image_tag`, которым compose-шаблон подставляет образ
|
||||||
|
(`pull_policy: never` — в реестре образа нет).
|
||||||
|
|
||||||
|
Два мотива за этим. Первый — **упростить деплой**, пока нет стабильного
|
||||||
|
онлайн-раннера: теперь `inv pl -- <app>` собирает, доставляет и запускает
|
||||||
|
приложение одной командой, отдельного ритуала в репозитории приложения не
|
||||||
|
осталось. Второй — **сократить набор секретов**: реестр и OAuth-токен выпали из
|
||||||
|
схемы, `yc_oauth_token`, `yc_container_registry` и
|
||||||
|
`yc_container_registry_repository` удалены из vault (коммит `6a0d786`).
|
||||||
|
|
||||||
|
Registry-плейбуки и `vars/transcriber.images.yml` удалены; у remembos заодно
|
||||||
|
снесены gitea-workflow с goreleaser — они существовали только ради пуша образа в
|
||||||
|
`cr.yandex`.
|
||||||
|
|
||||||
|
## Последствия
|
||||||
|
|
||||||
|
- `+` Из деплоя ушли внешний реестр и токен на весь аккаунт облака; в vault на
|
||||||
|
три переменные меньше.
|
||||||
|
- `+` Деплой любого из трёх приложений — одна команда `inv pl -- <app>`;
|
||||||
|
«правка тега в чужом репозитории + коммит» как шаг деплоя исчезла.
|
||||||
|
- `+` Тег каждого деплоя уникален, плавающего `:latest` больше нет. Откат —
|
||||||
|
повторный деплой нужного коммита приложения.
|
||||||
|
- `-` Дедупликации по слоям нет: каждый деплой везёт полный архив. Замеры
|
||||||
|
`docker save`: homepage — 61 МБ, transcriber — 73 МБ, remembos — 21 МБ. Для
|
||||||
|
ручного нечастого деплоя размен принят осознанно.
|
||||||
|
- `-` Для деплоя нужен ноутбук с docker и тулчейнами: с чужой машины
|
||||||
|
задеплоить нельзя, а `playbook-all-applications.yml` теперь собирает три
|
||||||
|
образа за прогон.
|
||||||
|
- `-` На сервере копятся образы от каждого прогона; чистит их ночной
|
||||||
|
`docker image prune -af` (см. `playbook-system.yml`).
|
||||||
|
- Контракт для новых приложений: чтобы деплоиться этой ролью, приложение должно
|
||||||
|
иметь `task image`, тегающий образ из `$BUILD_ID`.
|
||||||
|
- Осталось: `buckland/playbook-trackers.yml` всё ещё ходит в `cr.yandex` со своей
|
||||||
|
копией токена в собственном vault — пока он жив, отзывать токен в облаке рано.
|
||||||
@@ -63,6 +63,7 @@
|
|||||||
|
|
||||||
| Дата | Запись | Статус |
|
| Дата | Запись | Статус |
|
||||||
| ---------- | ---------------------------------------------------------------------------------------------- | ------ |
|
| ---------- | ---------------------------------------------------------------------------------------------- | ------ |
|
||||||
|
| 2026-07-25 | [Локальная сборка образов вместо Yandex Container Registry](ADR-2026-07-25-local-image-build.md) | — |
|
||||||
| 2026-06-22 | [Разнесение restic-операций на фазы под Intelligent Tiering](ADR-2026-06-22-restic-intelligent-tiering-phases.md) | — |
|
| 2026-06-22 | [Разнесение restic-операций на фазы под Intelligent Tiering](ADR-2026-06-22-restic-intelligent-tiering-phases.md) | — |
|
||||||
| 2026-05-23 | [Переезд сервера с Yandex Cloud на Timeweb VPS](ADR-2026-05-23-migrate-to-timeweb.md) | — |
|
| 2026-05-23 | [Переезд сервера с Yandex Cloud на Timeweb VPS](ADR-2026-05-23-migrate-to-timeweb.md) | — |
|
||||||
| 2026-04-04 | [Apprise как шлюз уведомлений](ADR-2026-04-04-apprise-notifications.md) | — |
|
| 2026-04-04 | [Apprise как шлюз уведомлений](ADR-2026-04-04-apprise-notifications.md) | — |
|
||||||
|
|||||||
Reference in New Issue
Block a user