Управление конфигурацией приложения

Прямо сейчас мы пишем новые главы самоучителя!
Эта страница находится в разработке.

Показать, что уже готово

Приложение в этой главе не предназначено для использования в production без доработки. Готовое к работе в production приложение мы получим в конце руководства.

Подготовка окружения

Подготовьте рабочее окружение согласно инструкциями главы “Подготовка окружения”, если это ещё не сделано.

Рабочее окружение работало, но перестало? Инструкции из этой главы не работают? Может помочь:

Работает ли Docker?

Запустим приложение Docker Desktop. Приложению понадобится некоторое время для того, чтобы запустить Docker. Если никаких ошибок в процессе запуска не возникло, то проверим, что Docker запущен и корректно настроен:

docker run hello-world

Результат успешного выполнения команды:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:9f6ad537c5132bcce57f7a0a20e317228d382c3cd61edae14650eec68b2b345c
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

При возникновении проблем обратитесь к документации Docker для их устранения.

Запустим приложение Docker Desktop. Приложению понадобится некоторое время для того, чтобы запустить Docker. Если никаких ошибок в процессе запуска не возникло, то проверим, что Docker запущен и корректно настроен:

docker run hello-world

Результат успешного выполнения команды:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:9f6ad537c5132bcce57f7a0a20e317228d382c3cd61edae14650eec68b2b345c
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

При возникновении проблем обратитесь к документации Docker для их устранения.

Запустим Docker:

sudo systemctl restart docker

Убедимся, что Docker запустился:

sudo systemctl status docker

Результат выполнения команды, если Docker успешно запущен:

● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2021-06-24 13:05:17 MSK; 13s ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 2013888 (dockerd)
      Tasks: 36
     Memory: 100.3M
     CGroup: /system.slice/docker.service
             └─2013888 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

dockerd[2013888]: time="2021-06-24T13:05:16.936197880+03:00" level=warning msg="Your kernel does not support CPU realtime scheduler"
dockerd[2013888]: time="2021-06-24T13:05:16.936219851+03:00" level=warning msg="Your kernel does not support cgroup blkio weight"
dockerd[2013888]: time="2021-06-24T13:05:16.936224976+03:00" level=warning msg="Your kernel does not support cgroup blkio weight_device"
dockerd[2013888]: time="2021-06-24T13:05:16.936311001+03:00" level=info msg="Loading containers: start."
dockerd[2013888]: time="2021-06-24T13:05:17.119938367+03:00" level=info msg="Loading containers: done."
dockerd[2013888]: time="2021-06-24T13:05:17.134054120+03:00" level=info msg="Daemon has completed initialization"
systemd[1]: Started Docker Application Container Engine.
dockerd[2013888]: time="2021-06-24T13:05:17.148493957+03:00" level=info msg="API listen on /run/docker.sock"

Теперь проверим, что Docker доступен и корректно настроен:

docker run hello-world

Результат успешного выполнения команды:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:9f6ad537c5132bcce57f7a0a20e317228d382c3cd61edae14650eec68b2b345c
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

При возникновении проблем обратитесь к документации Docker для их устранения.

Перезагружали компьютер после подготовки окружения?

Запустим кластер minikube, уже настроенный в начале главы “Подготовка окружения”:

minikube start

Выставим Namespace по умолчанию, чтобы не указывать его при каждом вызове kubectl:

kubectl config set-context minikube --namespace=werf-guide-app

Результат успешного выполнения команды:

😄  minikube v1.20.0 on Ubuntu 20.04
✨  Using the docker driver based on existing profile
👍  Starting control plane node minikube in cluster minikube
🚜  Pulling base image ...
🎉  minikube 1.21.0 is available! Download it: https://github.com/kubernetes/minikube/releases/tag/v1.21.0
💡  To disable this notice, run: 'minikube config set WantUpdateNotification false'

🔄  Restarting existing docker container for "minikube" ...
🐳  Preparing Kubernetes v1.20.2 on Docker 20.10.6 ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/google_containers/kube-registry-proxy:0.4
    ▪ Using image k8s.gcr.io/ingress-nginx/controller:v0.44.0
    ▪ Using image registry:2.7.1
    ▪ Using image docker.io/jettech/kube-webhook-certgen:v1.5.1
    ▪ Using image docker.io/jettech/kube-webhook-certgen:v1.5.1
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🔎  Verifying registry addon...
🔎  Verifying ingress addon...
🌟  Enabled addons: storage-provisioner, registry, default-storageclass, ingress
🏄  Done! kubectl is now configured to use "minikube" cluster and "werf-guide-app" namespace by default

Убедитесь, что вывод команды содержит строку:

Restarting existing docker container for "minikube"

Если её нет, значит был создан новый кластер minikube вместо использования старого. В таком случае повторите установку рабочего окружения с minikube с самого начала.

Теперь запустите команду в фоновом PowerShell-терминале и не закрывайте его:

minikube tunnel --cleanup=true

Запустим кластер minikube, уже настроенный в начале главы “Подготовка окружения”:

minikube start --namespace werf-guide-app

Выставим Namespace по умолчанию, чтобы не указывать его при каждом вызове kubectl:

kubectl config set-context minikube --namespace=werf-guide-app

Результат успешного выполнения команды:

😄  minikube v1.20.0 on Ubuntu 20.04
✨  Using the docker driver based on existing profile
👍  Starting control plane node minikube in cluster minikube
🚜  Pulling base image ...
🎉  minikube 1.21.0 is available! Download it: https://github.com/kubernetes/minikube/releases/tag/v1.21.0
💡  To disable this notice, run: 'minikube config set WantUpdateNotification false'

🔄  Restarting existing docker container for "minikube" ...
🐳  Preparing Kubernetes v1.20.2 on Docker 20.10.6 ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/google_containers/kube-registry-proxy:0.4
    ▪ Using image k8s.gcr.io/ingress-nginx/controller:v0.44.0
    ▪ Using image registry:2.7.1
    ▪ Using image docker.io/jettech/kube-webhook-certgen:v1.5.1
    ▪ Using image docker.io/jettech/kube-webhook-certgen:v1.5.1
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🔎  Verifying registry addon...
🔎  Verifying ingress addon...
🌟  Enabled addons: storage-provisioner, registry, default-storageclass, ingress
🏄  Done! kubectl is now configured to use "minikube" cluster and "werf-guide-app" namespace by default

Убедитесь, что вывод команды содержит строку:

Restarting existing docker container for "minikube"

Если её нет, значит был создан новый кластер minikube вместо использования старого. В таком случае повторите установку рабочего окружения с minikube с самого начала.

Случайно удаляли Namespace приложения?

Если вы непреднамеренно удалили Namespace приложения, то необходимо выполнить следующие команды, чтобы продолжить прохождение руководства:

kubectl create namespace werf-guide-app
kubectl create secret docker-registry registrysecret \
  --docker-server='https://index.docker.io/v1/' \
  --docker-username='<имя пользователя Docker Hub>' \
  --docker-password='<пароль пользователя Docker Hub>'

Результат успешного выполнения команды:

namespace/werf-guide-app created
secret/registrysecret created
Ничего не помогло, окружение или инструкции по-прежнему не работают?

Если ничего не помогло, то пройдите главу “Подготовка окружения” с начала, подготовив новое окружение с нуля. Если и это не помогло, тогда, пожалуйста, расскажите о своей проблеме в нашем Telegram или оставьте Issue на GitHub, и мы обязательно вам поможем.

Подготовка репозитория

Обновим существующий репозиторий с приложением:

Выполним следующий набор команд в PowerShell:

cd ~/werf-guide/app

# Чтобы увидеть, какие изменения мы собрались вносить далее в этой главе, заменим все файлы приложения
# в репозитории новыми, уже измененными файлами приложения, которые содержат описанные далее изменения.
git rm -r .
cp -Recurse -Force ~/werf-guide/guides//* .
git add .
git commit -m WIP
Посмотреть, какие именно изменения мы произведём
# Показать, какие файлы мы собираемся изменить
git show --stat
# Показать изменения
git show

Выполним следующий набор команд в Bash:

cd ~/werf-guide/app

# Чтобы увидеть, какие изменения мы собрались вносить далее в этой главе, заменим все файлы приложения
# в репозитории новыми, уже измененными файлами приложения, которые содержат описанные далее изменения.
git rm -r .
cp -rf ~/werf-guide/guides//. .
git add .
git commit -m WIP
Посмотреть, какие именно изменения мы произведём
# Показать, какие файлы мы собираемся изменить
git show --stat
# Показать изменения
git show

Не работает? Попробуйте инструкции на вкладке “Начинаю проходить руководство с этой главы” выше.

Подготовим новый репозиторий с приложением:

Выполним следующий набор команд в PowerShell:

# Склонируем репозиторий с примерами в ~/werf-guide/guides, если он ещё не был склонирован
if (-not (Test-Path ~/werf-guide/guides)) {
  git clone https://github.com/werf/werf-guides $env:HOMEPATH/werf-guide/guides
}

# Скопируем файлы приложения (пока без изменений) в ~/werf-guide/app
rm -Recurse -Force ~/werf-guide/app
cp -Recurse -Force ~/werf-guide/guides/ ~/werf-guide/app

# Сделаем из директории ~/werf-guide/app git-репозиторий
cd ~/werf-guide/app
git init
git add .
git commit -m initial

# Чтобы увидеть, какие изменения мы собрались вносить далее в этой главе, заменим все файлы приложения
# в репозитории новыми, уже измененными файлами приложения, которые содержат описанные далее изменения.
git rm -r .
cp -Recurse -Force ~/werf-guide/guides//* .
git add .
git commit -m WIP
Посмотреть, какие именно изменения мы произведём
# Показать, какие файлы мы собираемся изменить
git show --stat
# Показать изменения
git show

Выполним следующий набор команд в Bash:

# Склонируем репозиторий с примерами в ~/werf-guide/guides, если он ещё не был склонирован
test -e ~/werf-guide/guides || git clone https://github.com/werf/werf-guides ~/werf-guide/guides

# Скопируем файлы приложения (пока без изменений) в ~/werf-guide/app
rm -rf ~/werf-guide/app
cp -rf ~/werf-guide/guides/ ~/werf-guide/app

# Сделаем из директории ~/werf-guide/app git-репозиторий
cd ~/werf-guide/app
git init
git add .
git commit -m initial

# Чтобы увидеть, какие изменения мы собрались вносить далее в этой главе, заменим все файлы приложения
# в репозитории новыми, уже измененными файлами приложения, которые содержат описанные далее изменения.
git rm -r .
cp -rf ~/werf-guide/guides//. .
git add .
git commit -m WIP
Посмотреть, какие именно изменения мы произведём
# Показать, какие файлы мы собираемся изменить
git show --stat
# Показать изменения
git show

Использование werf предполагает описание полной конфигурации сборки и выката приложения в git-репозитории приложения вместе с его кодом. Инфраструктура описывается как код и к ней применимы те же методы разработки, что и для самого приложения. Чтобы внести изменение в инфраструктуру мы правим код и применяем новую версию через утилиту werf. Такой подход называют infrastructure-as-code (IaC).

Чтобы эффективно и удобно описывать конфигурацию приложения werf предоставляет следующее:

  • шаблонизация werf.yaml;
  • шаблонизация .helm/templates;
  • конфигурация входных данных для шаблонов helm через values-файлы;
  • хранение секретных данных в репозитории приложения;
  • мощный инструмент для обеспечения воспроизводимости конфигураций — гитерминизм;
  • возможность определять разные окружения одного приложения с помощью параметра env;
  • возможность выносить отдельные самодостаточные компоненты в так называемые chart’ы;
  • возможность выносить переиспользуемые шаблоны в так называемые library chart’ы;
  • использование нескольких образов в werf.yaml для разных целей.

Далее в главе будут подробно рассмотрены все указанные пункты с примерами.

## Подготовка Возьмём за основу web-приложение из раздела "первые шаги". Состояние директории `rails-app` должно соответствовать шагу `examples/rails/019_fixup_consistency`: ``` git clone https://github.com/werf/werf-guides cp -r werf-guides/examples/rails/019_fixup_consistency rails-app cd rails-app git init git add . git commit -m "initial" ```

0. Что-то про типы и виды конфигурации приложения в Kubernetes

Приложение конфигурится через переменные окружения, ConfgiMaps и Secrets.

Переменные окружения:

  • взять из CM
    • большие штуки
  • взять из секрета
    • пароль от базы
  • выставить явно в .helm/templates

описать когда что использовать

1. Шаблонизируем описание образов и манифестов Kubernetes

werf как и другие решения связанные с Kubernetes написан на Golang и использует gotemplates для шаблонизации на уровне генерирования текста конфигов — yaml-файлов.

Допустим, мы хотим использовать и стабильную версию ruby и новейшую одновременно для нашего rails приложения. Хотим чтобы часть реплик в production работало на старой версии ruby, а часть на новой. Для начала нам надо будет собрать отдельные образы для каждой версии ruby.

TODO: выставим состояние приложения 1100_configuration_image_per_ruby

Добавим образы в werf.yaml

  • werf.yaml используется для описания образов приложения.
  • werf.yaml позволяет описать сразу несколько образов приложения.

Мы будем генерировать набор образов в werf.yaml, подставляя базовый образ через параметр dockerfile build arg RUBY_VERSION.

Для начала превратим наш Dockerfile в шаблон добавив build argument RUBY_VERSION:

snippetcut_example Dockerfile // TODO

Сгенерируем 2 отдельных образа в werf.yaml для версий ruby 2.7.3 — назовём образ basicapp-stable, и ruby 3.0.1 — назовём образ basicapp-experimental:

snippetcut_example werf.yaml image_per_ruby // TODO

Проверим в результирующий рендер конфига:

werf config render --dev

Результат должен быть следующим:

...
---
image: basicapp-stable-ruby
dockerfile: Dockerfile
args:
  RUBY_VERSION: 2.7.3
---
image: basicapp-experimental-ruby
dockerfile: Dockerfile
args:
  RUBY_VERSION: 3.0.1
...

Используем образы в Helm

Все файлы в .helm/templates являются golang-шаблонами, результатом рендера которых является набор yaml-манифестов, разделённых через ---.

Ранее у нас использовался один Deployment basicapp. Теперь, используя шаблонизацию, сделано так, что в файле .helm/templates/deployment.yaml Deployment генерируется 2 Deployment’а — один по-прежнему называется basicapp, но использует образ basicapp-stable-ruby, второй называется basicapp-experimental и он использует образ basicapp-experimental-ruby.

snippetcut_example .helm/templates/deployment.yaml

Обратим внимание на использование конструкции index .Values.werf.image .ImageName — этот синтаксис позволяет достать из маппинга .Values.werf.image значение по ключу, записанному в переменную .ImageName. Также такой синтаксис может быть использован в случае использования символа - в названии образа: дело в том, что go-шаблоны не позволяют написать .Values.werf.image.basicapp-stable из-за символа -, поэтому в таком случае тоже используется функция index для получения значения по произвольному ключу в общей форме.

Обратим внимание, что оба Deployment’а basicapp и basicapp-experimental используют label.app=basicapp для создаваемых подов. Из этого следует, что Service с именем basicapp будет выбирать и балансировать нагрузку на Pod’ы, создаваемые Deployment basicapp и basicapp-experimental:

snippetcut_example .helm/templates/service.yaml

Выкатываем

TODO проверить что оно работает и написать команду

2. Конфигурируем входные данные для Helm и werf.yaml

При описании конфигурации удобно разделять входные данные для шаблонизации и сами шаблоны конфигурации. Почему:

  • Данные могут быть собраны в одном месте, а не размазаны по всем шаблонам в папке .helm/templates.
  • Данные предоставляют “рычаги управления”, по сути это интерфейс для изменения поведения шаблонов.
  • Шаблоны при этом реализуют лишь алгоритмы обработки этих данных и генерируют манифесты.

Примеры таких данных:

  • Для собираемых образов через werf.yaml:
    • Имя базового образа.
    • Версия языка программирования и каких-то системных библиотек встроенных в образ.
    • Версия сборочного кеша, при изменении которой инициируется полная пересборка образов.
    • И т.п.
  • Для манифестов объявляемых в .helm/templates:
    • Базовый url приложения.
    • Url внешнего сервиса, используемый в приложении.
    • Количество реплик для разных компонентов (backend, frontend и т.п.).
    • Лимиты memory и cpu для разных компонентов (backend, frontend, mysql, redis, sidekiq, и т.п.).
    • Имя пользователя, пароль, адрес и имя для внешней базы данных, которая задеплоена вне приложения.
    • И т.п.

Обратим внимание, что как для werf.yaml, так и для .helm/templates часто возникает необходимость передать секретные данные, такие как пароли, токены для внешних git репозиториев с зависимостями приложения,

Гитерминизм

  • Базовое требование werf: все входные данные для конфигурации werf.yaml должны храниться в git-репозитории проекта.
  • werf построен так, что:
    • Верифицирует все используемые файлы в момент билда/деплоя на наличие некоммитнутых в гит изменений, и читает все файлы только из текущего гит-коммита.
    • Не позволяет читать переменные окружения во время рендеринга werf.yaml.
    • А также не позволяет использовать директивы stapel-сборщика fromLatest, git.branch и прочие.
    • Подробнее про гитерминизм: https://ru.werf.io/documentation/v1.2/advanced/giterminism.html
  • Данным строгим правилам werf следует всегда по умолчанию.
    • В некоторых ситуациях от правил можно отходить.
    • Есть конфигурационный файл werf-giterminism.yaml, который как раз позволяет описывать те места, где мы отходим от гитерминизма.
      • Однако рекомендуется как можно меньше использовать werf-giterminism.yaml для построения более простых, надёжных и воспроивзодимых конфигураций.

В данной статье нам понадобится настраивать werf-giterminism.yaml далее, а пока просто примем к сведению.

Конфигурируем werf.yaml

werf.yaml является центральным конфигом werf и точкой входа, поэтому отдельного файла для входных данных шаблонизации werf.yaml werf не предоставляет. Обычно такие данные описываются прямо в начале файла werf.yaml:

snippetcut_example 1101 werf.yaml

Рассмотрим что тут происходит.

Во-первых версии ruby для stable и experimental образов из предыдущего пункта главы заданы в начале файла через ключи .StableRubyVersion и .ExperimentalRubyVersion.

Также туда добавлено глобальное значение .CacheVersion=1: изменяя цифру вручную пользователь получает возможность правильным способом инициировать пересборку всех образов Правильным в данном случае потому, что эта цифра зафиксирована в werf.yaml и хранится в git-репозитории. Этот способ даёт гитерминированность и воспроизводимость, в отличие от такого способа сброса кеша, когда мы вручную удаляем ранее созданные образы и слои и вызываем пересборку — в этом случае повторный вызов сборки, например, для старого коммита выдаст новый кеш, что является нарушением принципа воспроизводимости кеша.

Помимо прочего наше приложение теперь требует передачи секретного токена в сборочный процесс, так как в Gemfile былa добавленa библиотека из приватного репозитория на гитхабе. Токен передаётся через переменную окружения GITHUB_TOKEN.

Использование переменной окружения GITHUB_TOKEN является отступлением от принципов гитерминизма. По умолчанию werf не позволяет использовать переменные окружения. Следующий конфиг werf-giterminism.yaml разрешает использование этой переменной:

snippetcut_example 1101 werf-giterminism.yaml

Обратим внимание, что глобальные переменные $.CacheVersion и $.GithubToken, заданные в начале файла werf.yaml, передаются в сборку нашего Dockerfile в качестве build arguments CACHE_VERSION и GITHUB_TOKEN соответственно:

snippetcut_example 1101 Dockerfile

GITHUB_TOKEN тут попадает в параметр BUNDLE_GITHUB__COM для bundle install. Далее этот токен будет автоматически использован для скачивание зависимостей приложения, указанных в Gemfile через url github.com:

snippetcut_example 1101 Gemfile

Обратим внимание на использование конструкции $_ := set . "KEY" "VALUE" в werf.yaml. Данная конструкция создаёт в корневом контексте (что такое контекст шаблона можно почитать ТУТ) новый ключ KEY и прописывает в него значение VALUE. Использование $_ := в данном случае обязательно, иначе возвращаемое значение функции set попадёт в рендер результирующего werf.yaml, если же результирующее значение запомнить в переменной, то данная конструкция не повлияет на рендер (просто особенность go-templates, о которой надо знать).

Конфигурируем Helm

Встроенный в werf Helm предоставляет такой механизм конфигурирования шаблонов как values. Values — это произвольная структура данных, которая доступна для использования в шаблонах Helm.

Values могут быть описаны через yaml-файлы, либо переданы через CLI с помощью параметров --set, --set-string, --set-file. По умолчанию используется файл .helm/values.yaml, также можно передать дополнительные файлы через параметр --values.

werf также предоставляет средства для передачи секретных данных в шаблоны — через так называемые secret values. По умочанию используется файл .helm/secret-values.yaml, также можно передать дополнительные файлы через параметр --secret-values.

werf в соответствии с принципами гитерминизма вводит требование, чтобы все values файлы и secret-values файлы, а также файлы, переданные конструкцией --set-file обязательно были коммитнуты в git-репозиторий проекта.

Все values и secret-values файлы, а также параметры переданные через --set-* совмещаются в одну единую структуру данных, к которой можно обращаться из шаблонов Helm с помощью конструкции .Values.

В нашем примере воспользуемся стандартными файлами .helm/values.yaml и .helm/secret-values.yaml.

snippetcut_examle 1101 .helm/values.yaml

replicas url mysql username & password (SECRETS!) лимиты cpu & memory также для примера передадим параметры для подключения к внешнему сервису (см. главу про S3 TODO).

  • В нашем случае был использован такой 128-битный ключ WERF_SECRET_KEY=f1305914ac3394cac6d95225e6231d3e для симметричного шифрования алгоритмом AES-128.
  • Использовать секретные данные в процессе деплоя, или расшифровать их для простмотра, или отредактировать их можно только зная этот ключ симметричного шифрования.
    • ВАЖНО! Данный ключ никогда не хранится в git-репозитории проекта и всегда передаётся извне через переменную окружения.
      • Чаще всего это секретная переменная окружения в CI/CD системе (подробнее см. раздел TODO).

Посмотрим что за секретные данные у нас зашифрованы, для этого откроем режим редактивания .helm/secret-values.yaml:

WERF_SECRET_KEY=f1305914ac3394cac6d95225e6231d3e werf helm secret values edit .helm/secret-values.yaml

— должен открыться стандартный системный редактор, в котором будет расшифрованное содержимое данного файла, после сохранения и закрытия редактора werf зашифрует обновлённые данные и сохранит в .helm/secret-values.yaml. (Если редактор не открывается, следует попробовать явно установить переменную окружения EDITOR=..., например EDITOR=vi WERF_SECRET_KEY=... werf helm secret values edit ...).

werf поддерживает и другие способы расшифровки и зашифровки секретных переменных. Подробнее о них и в целом о секретах можно узнать в статьях документации:

  • https://ru.werf.io/documentation/v1.2/advanced/helm/configuration/values.html#%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D0%BA%D0%B8%D0%B5-%D1%81%D0%B5%D0%BA%D1%80%D0%B5%D1%82%D1%8B
  • https://ru.werf.io/documentation/v1.2/advanced/helm/configuration/secrets.html

Обратим внимание что структура данного secret-values файла совпадает со структурой файла .helm/values.yaml, лишь за тем отличием, что в данном файле передаются секретные ключи, а в обычном values файле не секретные. Итоговые .Values в шаблонах будут совмещены автоматически.

3. Кастомизируем конфигурацию под окружение

В werf имеется такой параметр, как --env (или переменная окружения WERF_ENV) — параметр окружения. Любая высокоуровневая команда werf принимает опциональный параметр окружения. С помощью данного параметра можно рендерить разную версию конфигов как для сборки образов, так и для деплоя в Kubernetes.

В качестве значения передаётся произвольная строка, например: production, dev, stage или test. Переданный параметр будет доступен в go-шаблонах и его можно будет использовать в условных конструкциях, чтобы генерировать разные манифесты для разных окружений, использовать

и подобных местах.

Завязать на параметр RAILS_ENV. Разный набор ресурсов для разных окружений. Разное количество реплик.

backend: replicas: 5

Разный набор гемов для разных окружений. Передаём env через dockerfile-build-args.

Пару слов о том, что можно передать разные values-файлы для разных окружений. Такая схема тоже допустима и реализуется путём явной передачи параметров --values и --secret-values из разных окружений CI/CD системы, откуда происходит вызов werf (см. подробнее статью …).

4. Выделим общие шаблоны

DRY

5. Подключаем внешние чарты