Cache-репозитории

Уровень: expert ~35 мин Практика: Vikunja (продолжение) (AGPL-3.0)

Что нужно знать перед уроком

  • M8.01 — Линковка образов вглубь — продолжение серии продвинутых тем сборки Werf
  • M0.02 — Установка инструментов — нужно понимание CI-раннеров как эфемерного окружения без сохранения состояния между запусками

Что нужно знать перед уроком

M8 урок 1 — предыдущая продвинутая тема сборки. Этот урок разбирает --cache-repo — механизм, критичный для реального CI/CD с эфемерными раннерами.

Теория

Проблема: эфемерные CI-раннеры без локального кэша Docker

Локальная разработка обычно выигрывает от кэша слоёв Docker, сохраняющегося между запусками werf build на одной машине. В CI-окружении (GitLab CI Runner в Kubernetes, например) каждый job часто выполняется в новом, изолированном контейнере без какого-либо сохранённого состояния — весь локальный кэш слоёв теряется при каждом запуске, что превращает каждую сборку в сборку «с нуля», даже если исходный код не менялся.

--cache-repo — решение через отдельный registry-репозиторий

1
werf build --repo registry.mycompany.org/project --cache-repo localhost:5000/project

Можно указать один или несколько cache-репозиториев (--cache-repo можно передавать несколько раз, либо через переменные окружения $WERF_CACHE_REPO_1, $WERF_CACHE_REPO_2 и так далее). Логика такова: при пуше новых образов werf параллельно заполняет и primary repo, и cache-repo; при последующих сборках werf сначала пытается получить манифесты и образы из cache-repo (который обычно ближе к CI-раннеру по сети — например, в том же кластере или дата-центре) и только при отсутствии нужных данных в кэше обращается к primary repo. Cache-репозиторий имеет более высокий приоритет при получении кэша, чем основной.

Почему именно отдельный репозиторий, а не volume/PVC для кэша

Использование отдельного OCI-репозитория (вместо, например, персистентного volume, монтируемого в CI-раннер) даёт два практических преимущества: во-первых, registry по своей природе спроектирован для параллельного доступа множества независимых job’ов CI без конфликтов блокировок (в отличие от файловой системы, где параллельный доступ к одному и тому же кэшу требует более сложной синхронизации); во-вторых, cache-repo может физически размещаться ближе к раннерам по сети (например, локальный registry в том же Kubernetes-кластере, где выполняются CI job’ы), что даёт выигрыш по скорости передачи данных по сравнению с обращением к удалённому primary repo при каждой сборке.

Частые ошибки и подводные камни

  • Ожидать, что cache-repo полностью заменяет необходимость в primary repo. Cache-repo — это именно ускоритель, а не замена: при отсутствии данных в кэше werf всё равно обратится к primary repo, и итоговые опубликованные образы всё равно должны попасть в primary repo для последующего деплоя.
  • Не настраивать cache-repo в CI, полагаясь на локальный Docker-кэш раннера. В большинстве современных CI-систем (особенно с Kubernetes-раннерами) каждый job получает чистое окружение — надежда на «сохранившийся» локальный кэш обычно не оправдывается, что делает --cache-repo практически обязательным для приемлемой скорости CI.
  • Использовать один и тот же репозиторий для primary и cache без понимания последствий. Хотя технически возможно, разделение primary и cache-репозиториев даёт более чистую модель прав доступа (cache-repo может иметь более короткий retention/lifecycle policy на уровне самого registry, не мешая политике werf cleanup для primary).

Практика в кластере

Практики в кластере в этом уроке нет — материал относится к CI-инфраструктуре сборки, а не к состоянию кластера.

Практика разработки

🧩 Практика урока: Vikunja (продолжение) · лицензия AGPL-3.0

Добавьте в .gitlab-ci.yml пакета Vikunja переменную WERF_CACHE_REPO_1, указывающую на локальный registry в том же namespace CI-раннеров, и сравните время сборки при холодном и тёплом cache-repo:

1
time werf build --repo $CI_REGISTRY_IMAGE --cache-repo $CI_REGISTRY_IMAGE/cache

Шпаргалка команд урока

1
2
3
werf build --repo <primary> --cache-repo <cache1> --cache-repo <cache2>
export WERF_CACHE_REPO_1=<cache1>
export WERF_CACHE_REPO_2=<cache2>

Полная сводная таблица — 📋 werf .

Вопросы для самопроверки

Заменяет ли cache-repo необходимость в primary repo?

cache-repo — оптимизация скорости, а не замена основного хранилища образов.

Источник: Werf — документация — werf_build.html

Почему cache-repo особенно критичен для CI с Kubernetes-раннерами?

Эфемерность CI-окружения без cache-repo превращает каждую сборку в сборку 'с нуля'.

Источник: Рекомендуемая литература

Можно ли указать несколько cache-репозиториев одновременно?

Поддерживается указание нескольких cache-репозиториев.

Источник: Werf — документация — –cache-repo

В каком порядке werf обращается к репозиториям при получении кэша?

cache-repo проверяется первым для получения манифестов и образов.

Источник: Werf — документация — Add Caching Repository

Рекомендуемая литература

Официальная документация

Статьи и блоги

Книги

  • Nigel Poulton. Docker Deep Dive. 2023. ISBN 978-1916585206.

Связанные материалы