From 0325f0f18b5221303aa98d2ab4a0f51717db8530 Mon Sep 17 00:00:00 2001 From: Timofey Kirillov Date: Wed, 14 Dec 2022 14:54:08 +0300 Subject: [PATCH] chore(docs): added build chapter all-in-one draft page Signed-off-by: Timofey Kirillov --- docs/pages_ru/usage/build_draft/all_in_one.md | 1015 +++++++++++++++++ 1 file changed, 1015 insertions(+) create mode 100644 docs/pages_ru/usage/build_draft/all_in_one.md diff --git a/docs/pages_ru/usage/build_draft/all_in_one.md b/docs/pages_ru/usage/build_draft/all_in_one.md new file mode 100644 index 0000000000..e955fde10b --- /dev/null +++ b/docs/pages_ru/usage/build_draft/all_in_one.md @@ -0,0 +1,1015 @@ +- [Обзор](#обзор) +- [Конфигурация образов](#конфигурация-образов) + - [Образы в werf.yaml](#образы-в-werfyaml) + - [Dockerfile](#dockerfile) + - [contextAddFiles](#contextaddfiles) + - [Stapel](#stapel) + - [Зависимости между образами](#зависимости-между-образами) +- [Сборочный процесс](#сборочный-процесс) + - [Параллельная сборка](#параллельная-сборка) + - [Послойное кеширование в container registry](#послойное-кеширование-в-container-registry) + - [Автотегирование / тегирование](#автотегирование--тегирование) + - [Синхронизация](#синхронизация) + - [Сборочный бэкенд](#сборочный-бэкенд) + - [Buildah](#buildah) + - [Системные требования](#системные-требования) + - [Включение Buildah](#включение-buildah) + - [Драйвер хранилища](#драйвер-хранилища) + - [Ulimits](#ulimits) + - [Работа в контейнерах](#работа-в-контейнерах) +- [Организация хранилища](#организация-хранилища) + - [Хранилище](#хранилище) + - [Именование стадий](#именование-стадий) + - [Первичный репозиторий](#первичный-репозиторий) + - [Вторичный репозиторий](#вторичный-репозиторий) + - [Кэширующий репозиторий](#кэширующий-репозиторий) + - [Финальный репозиторий](#финальный-репозиторий) + - [Примеры организации хранилища стадий](#примеры-организации-хранилища-стадий) + - [1. Стандарт](#1-стандарт) + - [2. Дополнительный кэш в локальной сети](#2-дополнительный-кэш-в-локальной-сети) + - [3. Полная оптимизация](#3-полная-оптимизация) + +## Обзор + +Чтобы доставить приложение в кубы как правило нужно собрать один или несколько образов приложения. + +От пользователя требуется предоставить сборочные инструкции в виде Dockerfile или альтернативного сборочного синтаксиса stapel. + +Предоставляется простой интерфейс для встараивания в CI/CD pipeline или для локального использования: команда `werf build [--repo REPO]`. Далее werf из коробки без специальной конфигурации берёт на себя всю работу по сборке, предоставляя следующие фичи: + +* оркестрация одновременной/параллельной сборки всех образов приложения; +* общий кеш промежуточных слоёв и образов в Container Registry, доступный с любых раннеров; +* оптимальная схема тегирования, основанная на содержимом образа, предотвращающая лишние пересборки и downtime приложения при дальнейшем выкате; +* система обеспечения воспроизводимости и неизменности образов для коммита: однажды собранные образы для коммита более не будут пересобраны (в рамках политик очистки — см. очистка); + +После прочтения данного раздела пользователь узнает как описать инструкции сборки образов, как работает механизм сборки, какие есть варианты конфигурации сборочного механизма и варианты организации хранилища под нужды проекта. + +## Конфигурация образов + +### Образы в werf.yaml + +> прим. для переводчика: на основе https://werf.io/documentation/v1.2/reference/werf_yaml.html#image-section + +Все требуемые образы должны быть сначала добавлены в werf.yaml проекта с помощью директивы `image` с указанием имени образа: + +```yaml +image: frontend +``` + +Имя образа — это короткое символьное имя, на которое мы будем ссылаться в других местах конфигурации и при вызове команд werf. Например, когда нам потребуется либо получить полное имя опубликованного в container registry образа, либо при запуске команд внутри собранного образа через `werf kube-run` и т.п. + +Если в файле конфигурации описывается только один образ, то он может быть безымянным: + +```yaml +image: ~ +``` + +Если в файле конфигурации описывается более одного образа, то **каждый образ** должен иметь собственное имя. Также один образ может иметь несколько имен, указываемых в виде YAML-списка (это эквивалентно описанию нескольких одинаковых образов с разными именами): + +```yaml +image: frontend +--- +image: backend +--- +image: [database, postgre] +``` + +#### Dockerfile + +Для описания сборочных инструкций образа поддерживается стандартный Dockerfile. + +[Dockerfile Reference](https://docs.docker.com/engine/reference/builder/) поможет при написании инструкций Dockerfile. +TODO: link to dockerfile writing guides. + +werf требует минимальной конфигурации для сборки одного или нескольких Dockerfile-ов проекта. + +Ниже приведен пример описания образа по имени `example` в werf.yaml: + +```yaml +image: example +dockerfile: Dockerfile +``` + +Также, вы можете описывать несколько образов из одного и того же Dockerfile: + +```yaml +image: backend +dockerfile: Dockerfile +target: backend +--- +image: frontend +dockerfile: Dockerfile +target: frontend +``` + +И конечно, вы можете описывать образы, основанные на разных Dockerfile: + +```yaml +image: backend +dockerfile: dockerfiles/Dockerfile.backend +--- +image: frontend +dockerfile: dockerfiles/Dockerfile.frontend +``` + +##### contextAddFiles + +Контекст сборки Dockerfile-образа включает только файлы из текущего коммита репозитория проекта, которые содержатся в директории, заданной директивой `context` (по умолчанию это директория проекта). + +Директива `contextAddFiles` позволяет дополнить контекст сборки файлами из директории проекта, которые не хранятся в git: + +```yaml +image: app +context: app +contextAddFiles: + - file1 + - dir1/ + - dir2/file2.out +``` + +В данной конфигурации контекст сборки будет состоять из следующих файлов: + +- `app/**/*` из текущего коммита репозитория проекта; +- Файлы `app/file1`, `app/dir2/file2.out` и директория `dir1`, которые находятся в директории проекта. + +Файлы `contextAddFiles` имеют больший приоритет, чем файлы из репозитория проекта, поэтому при пересечении пользователь будет работать с ними. + +> По умолчанию, использование директивы `contextAddFiles` запрещено гитерминизмом (подробнее об этом в [статье]({{ "/advanced/giterminism.html#contextaddfiles" | true_relative_url }})) + +#### Stapel + +В werf встроен альтернативный синтаксис описания сборочных инструкций называемый stapel, который открывает доступ к следующим возможностям сборщика: +* Обеспечивает интеграцию с git и инкрементальную пересборку с учетом истории git-репозитория. +* Позволяет использовать golang-шаблонизацию для описания сборочных инструкций в werf.yaml + +Пример минимальной конфигурации stapel образа в werf.yaml: + +```yaml +image: app +from: ubuntu:22.04 +``` + +Добавим исходники из git в наш образ: + +```yaml +image: app +from: ubuntu:22.04 +git: +- add: / + to: /app +``` + +Доступно 4 стадии для описания произвольных shell-инструкций, а также директива `git.stageDependencies` для настройки триггеров пересборки этих стадий при изменении соответствующих стадий (см. [подробнее](TODO)): + +```yaml +image: app +from: ubuntu:22.04 +git: +- add: / + to: /app + stageDependencies: + install: + - package-lock.json + - Gemfile.lock + beforeSetup: + - app/webpack/ + - app/assets/ + setup: + - config/templates/ +shell: + beforeInstall: + - apt update -q + - apt install -y libmysqlclient-dev mysql-client g++ + install: + - bundle install + - npm install + beforeSetup: + - bundle exec rails assets:precompile + setup: + - rake generate:configs +``` + +Поддерживаются вспомогательные образы, из которых можно импортировать файлы в целевой образ, а также golang-шаблонизация: + +```yaml +{{ $_ := set . "BaseImage" "ubuntu:22.04" }} + +{{ define "package:build-essential" }} + - apt install -y gcc g++ build-essential make +{{ end }} + +image: builder +from: {{ .BaseImage }} +shell: + beforeInstall: +{{ include "package:build-essentials" }} + install: + - cd /app + - make build +--- +image: app +from: alpine:latest +import: +- image: builder + add: /app/build/app + to: /usr/local/bin/app + after: install +``` + +### Зависимости между образами + +По умолчанию все образы объявленные в werf.yaml будут собираться параллельно. Неявно задают порядок сборки образов вспомогательные образы, из которых импортируются файлы: зависимый образ должен быть собран перед сборкой целевого образа, в который осуществляется импорт файлов. + +werf позволяет явно задать порядок сборки образов, объявляя для образа один или несколько зависимых образов. После сборки зависимого образа в целевом образе будут доступны переменные окружения и build-arguments, в которых будет полный адрес опубликованного в container registry образа, а также его digest. + +Такая возможность позволяет, например, использовать одну из стадий Dockerfile в качестве базового образа для другой стадии в том же или другом Dockerfile. При этом оба образа будут автоматически собраны и скомпонованы за один вызов `werf build`, а при изменении соответствующих сборочных инструкций базового образа будет автоматически работать пересборка и базового образа и зависящего от этого базового образа. Также имя и digest базового образа могут быть произвольно использованы в сборочных инструкциях целевого образа. + +Например, соберём 2 образа `base` и `app`. `base` будет использоваться в качестве базового образа для `app`, также в файле `/base_image_id` образа `app` будет сохранён digest базового образа из container registry. + +```yaml +# werf.yaml +image: base +dockerfile: Dockerfile.base +--- +image: app +dockerfile: Dockerfile.app +dependencies: +- image: base + imports: + - type: ImageName + targetBuildArg: BASE_IMAGE + - type: ImageID + targetBuildArg: BASE_IMAGE_ID +``` + +```Dockerfile +# Dockerfile.base +FROM ubuntu:22.04 +RUN apt update -q && apt install -y python3 +``` + +```Dockerfile +# Dockerfile.app +ARG BASE_IMAGE +FROM ${BASE_IMAGE} +ARG BASE_IMAGE_ID +RUN echo ${BASE_IMAGE_ID} > /base_image_id +``` + +## Сборочный процесс + +TODO: как это работает, как конфигурируется: parallel, buildah/docker, режимы buildah, синхронизация+конфигурация + +### Параллельная сборка + +Параллельная сборка в werf регулируется двумя параметрами `-p, --parallel` и `--parallel-tasks-limit`. По умолчанию параллельная сборка включена и собирается не более 5 образов одновременно. + +После построение дерева зависимостей образов, werf разбивает сборку на этапы. Каждый этап содержит набор независимых образов, которые могут собираться параллельно. + +```shell +┌ Concurrent builds plan (no more than 5 images at the same time) +│ Set #0: +│ - ⛵ image common-base +│ - 🛸 artifact jq +│ - 🛸 artifact libjq +│ - 🛸 artifact kcov +│ +│ Set #1: +│ - ⛵ image base-for-go +│ +│ Set #2: +│ - 🛸 artifact terraform-provider-vsphere +│ - 🛸 artifact terraform-provider-gcp +│ - 🛸 artifact candictl +│ - ⛵ image candictl-tests +│ - 🛸 artifact helm +│ - 🛸 artifact controller +│ +│ Set #3: +│ - ⛵ image base +│ +│ Set #4: +│ - ⛵ image tests +│ - ⛵ image app +└ Concurrent builds plan (no more than 5 images at the same time) +``` + +### Послойное кеширование в container registry + +TODO +Оптимальное использование CR: собрано один раз, больше не пересобирается, конечные образы, слои + +### Автотегирование / тегирование + +TODO + +### Синхронизация + +TODO: как работает по умолчанию, как настроить свой сервер + +### Сборочный бэкенд + +werf поддерживает использование Docker Server или Buildah в качестве бекенда для сборки образов. Buildah поддерживает полноценную работу в контейнерах и послойную сборку Dockerfile-ов с кешированием всех промежуточных слоёв в container registry. + +Более подробную информацию о Buildah можно получить в разделе [Режим сборки с использованием Buildah.]({{ "/advanced/buildah_mode.html" | true_relative_url }}) + +#### Buildah + +> ПРИМЕЧАНИЕ: werf поддерживает сборку образов с _использованием Docker-сервера_ или _с использованием Buildah_. Поддерживается сборка как Dockerfile-образов, так и stapel-образов через Buildah. + +Для сборки без Docker-сервера werf использует встроенный Buildah в rootless-режиме. + +##### Системные требования + +TODO: перенести в установку или уже там есть — проверить (?) + +Требования к хост-системе для запуска werf в Buildah-режиме без Docker/Kubernetes можно найти в [инструкциях по установке](/installation.html). А для запуска werf в Kubernetes или в Docker-контейнерах требования следующие: +* Если ваше ядро Linux версии 5.13+ (в некоторых дистрибутивах 5.11+) **рекомендуется** режим работы через модуль ядра `overlay`: + * Убедитесь, что модуль ядра `overlay` загружен с `lsmod | grep overlay`. + * Убедитесь, что настройка ядра `CONFIG_USER_NS=y` включена в вашем ядре с помощью `grep CONFIG_USER_NS /boot/config-VERSION`. + * При использовании ядра в debian-системах команда `sysctl kernel.unprivileged_userns_clone` должна вернуть `1`. В ином случае выполните: + ```shell + echo 'kernel.unprivileged_userns_clone = 1' | sudo tee -a /etc/sysctl.conf + sudo sysctl -p + ``` + * Команда `sysctl user.max_user_namespaces` должна вернуть по меньшей мере `15000`. В ином случае выполните: + ```shell + echo 'user.max_user_namespaces = 15000' | sudo tee -a /etc/sysctl.conf + sudo sysctl -p + ``` +* Если ядро более старое или у вас не получается активировать модуль ядра `overlay`, то установите `fuse-overlayfs`, который обычно доступен в репозиториях вашего дистрибутива. В крайнем случае может быть использован драйвер хранилища `vfs`. + +##### Включение Buildah + +Buildah включается установкой переменной окружения `WERF_BUILDAH_MODE` в один из вариантов: `auto`, `native-chroot`, `native-rootless`. Большинству пользователей для включения режима Buildah достаточно установить `WERF_BUILDAH_MODE=auto`. + +* `auto` — автоматический выбор режима в зависимости от платформы и окружения; +* `native-chroot` работает только в Linux и использует `chroot`-изоляцию для сборочных контейнеров; +* `native-rootless` работает только в Linux и использует `rootless`-изоляцию для сборочных контейнеров. На этом уровне изоляции werf использует среду выполнения сборочных операций в контейнерах (runc, crun, kata или runsc). + +> ПРИМЕЧАНИЕ: На данный момент Buildah доступен только для пользователей Linux и Windows с включённой подсистемой WSL2. Для пользователей MacOS на данный момент предлагается использование виртуальной машины для запуска werf в режиме Buildah. + +##### Драйвер хранилища + +werf может использовать драйвер хранилища `overlay` или `vfs`: + +* `overlay` позволяет использовать файловую систему OverlayFS. Можно использовать либо встроенную в ядро Linux поддержку OverlayFS (если она доступна), либо реализацию fuse-overlayfs. Это рекомендуемый выбор по умолчанию. +* `vfs` обеспечивает доступ к виртуальной файловой системе вместо OverlayFS. Эта файловая система уступает по производительности и требует привилегированного контейнера, поэтому ее не рекомендуется использовать. Однако в некоторых случаях она может пригодиться. + +Как правило, достаточно использовать драйвер по умолчанию (`overlay`). Драйвер хранилища можно задать с помощью переменной окружения `WERF_BUILDAH_STORAGE_DRIVER`. + +##### Ulimits + +По умолчанию Buildah режим в werf наследует системные ulimits при запуске сборочных контейнеров. Пользователь может переопределить эти параметры с помощью переменной окружения `WERF_BUILDAH_ULIMIT`. + +Формат `WERF_BUILDAH_ULIMIT=type:softlimit[:hardlimit][,type:softlimit[:hardlimit],...]` — конфигурация лимитов, указанные через запятую: +* "core": maximum core dump size (ulimit -c) +* "cpu": maximum CPU time (ulimit -t) +* "data": maximum size of a process's data segment (ulimit -d) +* "fsize": maximum size of new files (ulimit -f) +* "locks": maximum number of file locks (ulimit -x) +* "memlock": maximum amount of locked memory (ulimit -l) +* "msgqueue": maximum amount of data in message queues (ulimit -q) +* "nice": niceness adjustment (nice -n, ulimit -e) +* "nofile": maximum number of open files (ulimit -n) +* "nproc": maximum number of processes (ulimit -u) +* "rss": maximum size of a process's (ulimit -m) +* "rtprio": maximum real-time scheduling priority (ulimit -r) +* "rttime": maximum amount of real-time execution between blocking syscalls +* "sigpending": maximum number of pending signals (ulimit -i) +* "stack": maximum stack size (ulimit -s) + +### Работа в контейнерах + +TODO + +## Организация хранилища + +В данной статье описано, как устроено хранилище собираемых образов в werf, какие бывают типы хранилища, какие функции выполняют эти хранилища, а также различные варианты организации хранилища в проекте. + +### Хранилище + +werf собирает образы, состоящие из одной или нескольких стадий. Все стадии собираемых образов сохраняются в так называемое **хранилище стадий** по мере сборки. Хранилище хранит стадии и метаданные проекта. Эти данные могут храниться локально на хост-машине, либо в container registry. + +Большинство команд werf требуют указания места размещения _хранилища_ с помощью ключа `--repo` или переменной окружения `WERF_REPO`. + +Есть два вида хранилища стадий: **локальное** и **репозиторий** (container registry). + +* Локальное хранилище стадий может быть использовано _только для локальной разработки_. В качестве локального хранилища выступает docker server или buildah storage. Локальное хранилище стадий будет задействовано, например, если вызвать команду `werf build` без аргумента `--repo`. +* Во всех остальных случаях (т.е. кроме локальной разработки) в качестве хранилища стадий всегда выступает репозиторий в container registry. Если запустить сборку с хранилищем стадий в репозитории (например, `werf build` с параметром `--repo ghcr.io/example/myrepo`), то werf сначала проверит наличие требуемых стадий в локальном хранилище и скопирует оттуда подходящие стадии, чтобы не пересобирать эти стадии заново. + + **ЗАМЕЧАНИЕ** Каждый проект должен использовать в качестве хранилища уникальный адрес репозитория, который используется только этим проектом. + +Стадии будут [именоваться по-разному](#именование-стадий) в зависимости от типа используемого хранилища. + +При использовании container registry для хранения стадий, локальный docker-server на всех хостах, где запускают werf, используется как кеш. Этот кеш может быть очищен автоматически самим werf-ом, либо удалён с помощью других инструментов (например `docker rmi`) без каких-либо последствий. + +Предполагается, что хранилище стадий инсталляции не может быть удалено или очищено сторонними средствами без негативных последствий для работы werf *(например, см. [первичный репозиторий](#первичный-репозиторий))*. Исключение составляют некоторые типы хранилищ, которые могут быть безопасно удалены в любой момент времени *(например, см. [кэширующий репозиторий](#кэширующий-репозиторий))*. + + +#### Именование стадий + +Стадии в _локальном хранилище_ именуются согласно следующей схемы: `PROJECT_NAME:STAGE_DIGEST-TIMESTAMP_MILLISEC`. Например: + +``` +myproject 9f3a82975136d66d04ebcb9ce90b14428077099417b6c170e2ef2fef-1589786063772 274bd7e41dd9 16 seconds ago 65.4MB +myproject 7a29ff1ba40e2f601d1f9ead88214d4429835c43a0efd440e052e068-1589786061907 e455d998a06e 18 seconds ago 65.4MB +myproject 878f70c2034f41558e2e13f9d4e7d3c6127cdbee515812a44fef61b6-1589786056879 771f2c139561 23 seconds ago 65.4MB +myproject 5e4cb0dcd255ac2963ec0905df3c8c8a9be64bbdfa57467aabeaeb91-1589786050923 699770c600e6 29 seconds ago 65.4MB +myproject 14df0fe44a98f492b7b085055f6bc82ffc7a4fb55cd97d30331f0a93-1589786048987 54d5e60e052e 31 seconds ago 64.2MB +``` + +Стадии в _удалённом хранилище_ именуются согласно следующей схемы: `CONTAINER_REGISTRY_REPO:STAGE_DIGEST-TIMESTAMP_MILLISEC`. Например: + +``` +localhost:5000/myproject-stages d4bf3e71015d1e757a8481536eeabda98f51f1891d68b539cc50753a-1589714365467 7c834f0ff026 20 hours ago 66.7MB +localhost:5000/myproject-stages e6073b8f03231e122fa3b7d3294ff69a5060c332c4395e7d0b3231e3-1589714362300 2fc39536332d 20 hours ago 66.7MB +localhost:5000/myproject-stages 20dcf519ff499da126ada17dbc1e09f98dd1d9aecb85a7fd917ccc96-1589714359522 f9815cec0867 20 hours ago 65.4MB +localhost:5000/myproject-stages 1dbdae9cc1c9d5d8d3721e32be5ed5542199def38ff6e28270581cdc-1589714352200 6a37070d1b46 20 hours ago 65.4MB +localhost:5000/myproject-stages f88cb5a1c353a8aed65d7ad797859b39d357b49a802a671d881bd3b6-1589714347985 5295f82d8796 20 hours ago 65.4MB +localhost:5000/myproject-stages 796e905d0cc975e718b3f8b3ea0199ea4d52668ecc12c4dbf85a136d-1589714344546 a02ec3540da5 20 hours ago 64.2MB +``` + +- `PROJECT_NAME` — имя проекта; +- `CONTAINER_REGISTRY_REPO` — репозиторий, заданный опцией `--repo`; +- `STAGE_DIGEST` — дайджест стадии. Дайджест является идентификатором содержимого стадии и также зависит от истории правок в git репозитории, которые привели к такому содержимому. +- `TIMESTAMP_MILLISEC` — уникальный идентификатор, который генерируется в процессе [процедуры сохранения стадии]({{ "internals/build_process.html#сохранение-стадий-в-хранилище" | true_relative_url }}) после того как стадия была собрана. + +#### Первичный репозиторий + +* Задаётся параметром `--repo` (или переменной окружения `WERF_REPO`). +* У проекта всегда есть только один такой репозиторий. + +Данное хранилище является основным и объединяет в себе несколько функций: + +1. История проекта. + - Хранилище метаданных, связанных с Git-репозиторием, для собираемых образов и стадий. + - История проекта позволяет реализовать продвинутый алгоритм безопасной очистки старых стадий на основе истории Git-репозитория (команда `werf cleanup`). +1. Синхронизация сборки в распределённом окружении. + - Данное хранилище позволяет запускать сборку в распределённом окружении и эффективно переиспользовать собираемые стадии в таком окружении. Это возможно за счёт механизмов распределённой синхронизации, встроенных в werf. Эти механизмы работают исключительно с первичным репозиторием. + - Как только стадия попадает в первичный репозиторий, эта стадия может быть переиспользована другими сборочными процессами, которые могут быть запущены с произвольного хоста. +1. Сборочный кэш ранее собранных стадий. + - Ранее собранные стадии по возможности переиспользуются вместо того, чтобы собираться заново. + - Данная функция схожа с привычным локальным сборочным кэшом в Docker server, однако в случае werf этот кэш находится в container registry. +1. Хранилище финальных образов, используемых при запуске приложения в Kubernetes. + - Kubernetes будет скачивать образы из этого репозитория для запуска контейнеров приложения. + - В качестве финальных образов напрямую используются те же стадии, из которых состоит собранный образ. + +**Очистка (ВАЖНО!).** Для корректной и полноценной работы werf первичный репозиторий должен быть надёжным (persistent) хранилищем, образы из которого удаляются лишь специальной командой очистки `werf cleanup`. Первичный репозиторий — это не просто сборочный кэш проекта, но и хранилище его истории, похожее на историю коммитов в Git-репозитории. + +Помимо первичного репозитория в werf есть другие типы репозиториев, которые могут выполнять часть его функций. Они будут рассмотрены далее. Стоит помнить, что **без первичного репозитория werf не работает, а все другие репозитории — дополнительные**; они были созданы, чтобы снять часть функций первичного репозитория в вашей инсталляции проекта. + +#### Вторичный репозиторий + +* Задаётся параметром `--secondary-repo` (или переменной окружения `WERF_SECONDARY_REPO_`). +* Может быть указан один или несколько таких репозиториев. + +Данное хранилище — это репозиторий только для чтения (read-only), выполняющий функцию сборочного кэша ранее собранных стадий *(см. функции [первичного репозитория](#первичный-репозиторий))*. + +Как правило, в качестве secondary-repo может быть указан уже существующий первичный репозиторий от другой инсталляции проекта. Отсутствующие стадии по мере необходимости будут скопированы из вторичного репозитория в первичный вместо сборки с нуля. Вновь собранные же стадии будут помещены только в первичный репозиторий, потому что вторичный репозиторий всегда read-only, т.е. мы не имеем права в него записывать новые данные. + +**Очистка** вторичного репозитория не требуется, т.к. этот репозиторий в то же время является первичным для другой инсталляции проекта и его данные управляются там. + +#### Кэширующий репозиторий + +* Задаётся параметром `--cache-repo` (или переменной окружения `WERF_CACHE_REPO_`). +* Может быть указан один или несколько таких репозиториев. + +Выполняет функцию сборочного кэша ранее собранных стадий *(см. функции [первичного репозитория](#первичный-репозиторий))*. Кэширующий репозиторий отличается от вторичного тем, что он read-write, т.е. используется как для записи новых стадий в кэш, так и для использования собранных стадий из этого кэша. + +Существующие стадии будут скопированы из кэширующего репозитория в первичный, поскольку первичный репозиторий обязан содержать все собранные стадии образов проекта. Вновь собранные стадии будут опубликованы и в первичный репозиторий, и в кэширующий репозиторий. + +Стадии, которые используются в качестве базовых для сборки новых стадий: +* будут скачиваться из кэша, +* если их нет в кэширующем репозитории — будут скачиваться из первичного репозитория, а затем загружены в кэширующий для дальнейшего использования. + +Другими словами, кэширующий репозиторий заполняется не только вновь собираемыми стадиями, но и базовыми стадиями, используемыми для сборки новых стадий. + +Кэширующий репозиторий никогда не используется при запуске приложения в Kubernetes. + +**Очистка** кэширующего репозитория осуществляется путём его полного удаления. После очистки такой репозиторий будет вновь наполнен актуальными часто используемыми данными. + +#### Финальный репозиторий + +* Задаётся параметром `--final-repo` (или переменной окружения `WERF_FINAL_REPO`). +* Может быть указан только один такой репозиторий. + +Данный репозиторий будет использоваться исключительно для публикации финальных образов, задействованных для деплоя приложения в Kubernetes. +- Вновь собираемые образы попадают сначала в первичный репозиторий, и затем копируются в финальный. +- Финальный репозиторий никогда не хранит промежуточные стадии образов, в нем есть лишь последняя стадия образа. +- Финальный репозиторий никогда не хранит промежуточные образы (артефакты), нужные для сборки конечных образов. Сюда попадают только конечные образы, используемые в Kubernetes. + +**Очистка** данного репозитория выполняется командой `werf cleanup` в паре с первичным репозиторием (для этого необходимо указывать два параметра команде `werf cleanup`: `--repo` и `--final-repo`). + +### Примеры организации хранилища стадий + +Рассмотрим варианты использования и комбинации описанных репозиториев. Стоит отметить, что любой из описанных вариантов требует указания [первичного репозитория](#первичный-репозиторий). + +#### 1. Стандарт + +* **Первичный** репозиторий доступен со всех сборочных хостов, а также из кластера Kubernetes. Другие репозитории не используются. +* При сборке образов сборочный кэш будет скачиваться и загружаться в первичный репозиторий. При выкате Kubernetes будет скачивать финальные образы приложения из данного репозитория. +* В большинстве случаев следует использовать именно эту простую схему. Также данная схема подходит, если нет уверенности в том, что требуется для проекта. + +#### 2. Дополнительный кэш в локальной сети + +* **Первичный** репозиторий доступен со всех сборочных хостов, а также из кластера Kubernetes. +* **Кэширующий** репозиторий работает в локальной сети с быстрым доступом. +* При сборке образов сборочный кэш загружается и в первичный репозиторий, и в кэширующий репозиторий. Стадии образов, требуемые для сборки других стадий, будут скачиваться из кэширующего репозитория. + +#### 3. Полная оптимизация + +* **Первичный** репозиторий располагается в локальной сети с быстрым доступом и доступен со всех сборочных хостов. Доступ к данному репозиторию из кластера Kubernetes не требуется. В отличие от кэширующего репозитория, первичный не может быть полностью очищен или удалён без последствий для работы werf, поэтому требуется обеспечить персистивность и надёжность данного хранилища. +* Опционально могут быть подняты дополнительные **кэширующие** репозитории в локальной сети с быстрым доступом. +* **Финальный** репозиторий располагается близко к кластеру Kubernetes для того, чтобы запускаемое приложение быстро скачивало образы приложения (скачивание финальных образов со стороны Kubernetes будет происходить чаще, чем их загрузка со сборочных хостов). Также к финальному репозиторию требуется доступ на запись со всех сборочных хостов. В финальный репозиторий будут загружены лишь конечные образы приложения (без промежуточных образов артефактов, которые нужны для сборки других образов). + + +