Основы параметризации

Содержимое словаря $.Values можно использовать для параметризации шаблонов. Каждый чарт имеет свой словарь $.Values. Словарь формируется слиянием параметров, полученных из файлов параметров, опций командной строки и других источников.

Простой пример параметризации через values.yaml:

# values.yaml:
myparam: myvalue
# templates/example.yaml:
{{ $.Values.myparam }}

Результат:

myvalue

Более сложный пример:

# values.yaml:
myparams:
- value: original
# templates/example.yaml:
{{ (index $.Values.myparams 0).value }}
werf render --set myparams[0].value=overriden

Результат:

overriden

Источники параметров и их приоритет

Словарь $.Values формируется объединением параметров из источников параметров в указанном порядке:

  1. values.yaml текущего чарта.
  2. secret-values.yaml текущего чарта (только в werf).
  3. Словарь в values.yaml родительского чарта, у которого ключ — алиас или имя текущего чарта.
  4. Словарь в secret-values.yaml родительского чарта (только в werf), у которого ключ — алиас или имя текущего чарта.
  5. Файлы параметров из переменной WERF_VALUES_*.
  6. Файлы параметров из опции --values.
  7. Файлы секретных параметров из переменной WERF_SECRET_VALUES_*.
  8. Файлы секретных параметров из опции --secret-values.
  9. Параметры в set-файлах из переменной WERF_SET_FILE_*.
  10. Параметры в set-файлах из опции --set-file.
  11. Параметры из переменной WERF_SET_STRING_*.
  12. Параметры из опции --set-string.
  13. Параметры из переменной WERF_SET_*.
  14. Параметры из опции --set.
  15. Служебные параметры werf.
  16. Параметры из директивы export-values родительского чарта (только в werf).
  17. Параметры из директивы import-values дочерних чартов.

Правила объединения параметров:

  • простые типы данных перезаписываются;

  • списки перезаписываются;

  • словари объединяются;

  • при конфликтах параметры из источников выше по списку перезаписываются параметрами из источников ниже по списку.

Параметризация чарта

Чарт можно параметризовать через его файл параметров:

# values.yaml:
myparam: myvalue
# templates/example.yaml:
{{ $.Values.myparam }}

Результат:

myvalue

Также добавить/переопределить параметры чарта можно и аргументами командной строки:

werf render --set myparam=overriden  # или WERF_SET_MYPARAM=myparam=overriden werf render
werf render --set-string myparam=overriden  # или WERF_SET_STRING_MYPARAM=myparam=overriden werf render

… или дополнительными файлами параметров:

# .helm/values-production.yaml:
myparam: overriden
werf render --values .helm/values-production.yaml  # или WERF_VALUES_PROD=.helm/values-production.yaml werf render

… или файлом секретных параметров основного чарта (только в werf):

# .helm/secret-values.yaml:
myparam: <encrypted>
werf render

… или дополнительными файлами секретных параметров основного чарта (только в werf):

# .helm/secret-values-production.yaml:
myparam: <encrypted>
werf render --secret-values .helm/secret-values-production.yaml  # или WERF_SECRET_VALUES_PROD=.helm/secret-values-production.yaml werf render

… или set-файлами:

# myparam.txt:
overriden
werf render --set-file myparam=myparam.txt  # или WERF_SET_FILE_PROD=myparam=myparam.txt werf render

Результат везде тот же:

overriden

Параметризация зависимых чартов

Зависимый чарт можно параметризовать как через его собственный файл параметров, так и через файл параметров родительского чарта.

К примеру, здесь параметры из словаря mychild в файле values.yaml чарта myparent перезаписывают параметры в файле values.yaml чарта mychild:

# Chart.yaml:
name: myparent
dependencies:
- name: mychild
# values.yaml:
mychild:
  myparam: overriden
# charts/mychild/values.yaml:
myparam: original
# charts/mychild/templates/example.yaml:
{{ $.Values.myparam }}

Результат:

overriden

Обратите внимание, что словарь, находящийся в values.yaml родительского чарта и содержащий параметры для зависимого чарта, должен иметь в качестве имени alias (если есть) или name зависимого чарта.

Также добавить/переопределить параметры зависимого чарта можно и аргументами командной строки:

werf render --set mychild.myparam=overriden  # или WERF_SET_MYPARAM=mychild.myparam=overriden werf render
werf render --set-string mychild.myparam=overriden  # или WERF_SET_STRING_MYPARAM=mychild.myparam=overriden werf render

… или дополнительными файлами параметров:

# .helm/values-production.yaml:
mychild:
  myparam: overriden
werf render --values .helm/values-production.yaml  # или WERF_VALUES_PROD=.helm/values-production.yaml werf render

… или файлом секретных параметров основного чарта (только в werf):

# .helm/secret-values.yaml:
mychild:
  myparam: <encrypted>
werf render

… или дополнительными файлами секретных параметров основного чарта (только в werf):

# .helm/secret-values-production.yaml:
mychild:
  myparam: <encrypted>
werf render --secret-values .helm/secret-values-production.yaml  # или WERF_SECRET_VALUES_PROD=.helm/secret-values-production.yaml werf render

… или set-файлами:

# mychild-myparam.txt:
overriden
werf render --set-file mychild.myparam=mychild-myparam.txt  # или WERF_SET_FILE_PROD=mychild.myparam=mychild-myparam.txt werf render

… или директивой export-values (только в werf):

# Chart.yaml:
name: myparent
dependencies:
- name: mychild
  export-values:
  - parent: myparam
    child: myparam
# values.yaml:
myparam: overriden
werf render

Результат везде тот же:

overriden

Использование параметров зависимого чарта в родительском

Для передачи параметров зависимого чарта в родительский можно использовать директиву import-values в родительском чарте:

# Chart.yaml:
name: myparent
dependencies:
- name: mychild
  import-values:
  - child: myparam
    parent: myparam
# values.yaml:
myparam: original
# charts/mychild/values.yaml:
myparam: overriden
# templates/example.yaml:
{{ $.Values.myparam }}

Результат:

overriden

Глобальные параметры

Параметры чарта доступны только в этом же чарте (и ограниченно доступны в зависимых от него). Один из простых способов получить доступ к параметрам одного чарта в других подключенных чартах — использование глобальных параметров.

Глобальный параметр имеет глобальную область видимости — параметр, объявленный в родительском, дочернем или другом подключенном чарте становится доступен во всех подключенных чартах по одному и тому же пути:

# Chart.yaml:
name: myparent
dependencies:
- name: mychild1
- name: mychild2
# charts/mychild1/values.yaml:
global:
  myparam: myvalue
# templates/example.yaml:
myparent: {{ $.Values.global.myparam }}
# charts/mychild1/templates/example.yaml:
mychild1: {{ $.Values.global.myparam }}
# charts/mychild2/templates/example.yaml:
mychild2: {{ $.Values.global.myparam }}

Результат:

myparent: myvalue
---
mychild1: myvalue
---
mychild2: myvalue

Секретные параметры (только в werf)

Для хранения секретных параметров можно использовать файлы секретных параметров, хранящиеся в зашифрованном виде в Git-репозитории.

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

# .helm/values.yaml:
plainParam: plainValue
# .helm/secret-values.yaml:
secretParam: 1000625c4f1d874f0ab853bf1db4e438ad6f054526e5dcf4fc8c10e551174904e6d0
{{ $.Values.plainParam }}
{{ $.Values.secretParam }}

Результат:

plainValue
secretValue

Работа с файлами секретных параметров

Порядок работы с файлами секретных параметров:

  1. Возьмите существующий секретный ключ или создайте новый командой werf helm secret generate-secret-key.

  2. Сохраните секретный ключ в переменную окружения WERF_SECRET_KEY, либо в файлы <корень Git-репозитория>/.werf_secret_key или <домашняя директория>/.werf/global_secret_key.

  3. Командой werf helm secret values edit .helm/secret-values.yaml откройте файл секретных параметров и добавьте/измените в нём расшифрованные параметры.

  4. Сохраните файл — файл зашифруется и сохранится в зашифрованном виде.

  5. Закоммитите в Git добавленный/изменённый файл .helm/secret-values.yaml;

  6. При дальнейших вызовах werf секретный ключ должен быть установлен в вышеупомянутых переменной окружения или файлах, иначе файл секретных параметров не сможет быть расшифрован.

Имеющий доступ к секретному ключу может расшифровать содержимое файла секретных параметров, поэтому держите секретный ключ в безопасном месте!

При использовании файла <корень Git-репозитория>/.werf_secret_key обязательно добавьте его в .gitignore, чтобы случайно не сохранить его в Git-репозитории.

Многие команды werf можно запускать и без указания секретного ключа благодаря опции --ignore-secret-key, но в таком случае параметры будут доступны для использования не в расшифрованной форме, а в зашифрованной.

Дополнительные файлы секретных параметров

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

# .helm/secret-values-production.yaml:
secret: 1000625c4f1d874f0ab853bf1db4e438ad6f054526e5dcf4fc8c10e551174904e6d0
werf --secret-values .helm/secret-values-production.yaml

Информация о собранных образах (только в werf)

werf хранит подробную информацию о собранных образах в $.Values.global.werf.images, доступную во всех чартах (основном и зависимых):

global:
  werf:
    images:
      backend:
        # Адрес container registry:
        registry: example.org
        # Пространство имён репозитория:
        namespace: apps
        # Короткое имя образа:
        name: myapp
        # Тег образа:
        tag: a243949601ddc3d4133c4d5269ba23ed58cb8b18bf2b64047f35abd2-1598024377816
        # Дайджест образа:
        digest: sha256:ece15c4a8e7e04dd0afa25b85a51e3fba35eb31e0e1489a2f3e916da77e4e865
        # Тег и дайджест вместе:
        tag_digest: "a243949...816@sha256:ece15c4a..."
        # Полное имя образа без тега (registry + repository):
        image: example.org/apps/myapp
        # Полный путь репозитория (namespace + name):
        repository: apps/myapp
        # Полная ссылка на образ с дайджестом:
        ref: "example.org/apps/myapp:a243949...816@sha256:ece15c4a..."
        # Полная ссылка на образ с тегом:
        ref_tag: "example.org/apps/myapp:a243949...816"
        # Путь репозитория с тегом и дайджестом:
        repository_ref: "apps/myapp:a243949...816@sha256:ece15c4a..."
        # Путь репозитория с тегом:
        repository_tag: "apps/myapp:a243949...816"
        # Короткое имя с тегом и дайджестом:
        name_ref: "myapp:a243949...816@sha256:ece15c4a..."
        # Короткое имя с тегом:
        name_tag: "myapp:a243949...816"

Этот структурированный формат позволяет использовать отдельные компоненты образа, что удобно при работе с внешними чартами, ожидающими значения образов в структурированном формате:

image:
  registry: {{ $.Values.global.werf.images.backend.registry }}
  repository: {{ $.Values.global.werf.images.backend.repository }}
  tag: {{ $.Values.global.werf.images.backend.tag }}

Поскольку $.Values.global.werf имеет глобальную область видимости, images доступен во всех зависимых чартах. Также можно использовать export-values для передачи отдельных полей образа в формате, который ожидает внешний чарт:

# .helm/Chart.yaml:
dependencies:
- name: postgres-operator
  export-values:
  - parent: global.werf.images.pg.registry
    child: image.registry
  - parent: global.werf.images.pg.repository
    child: image.repository
  - parent: global.werf.images.pg.tag
    child: image.tag

Чарт postgres-operator получит:

image:
  registry: example.org
  repository: apps/pg
  tag: a243949601ddc3d4133c4d5269ba23ed58cb8b18bf2b64047f35abd2-1598024377816

Информация о релизе

werf хранит информацию о релизе в свойствах объекта $.Release:

# Устанавливается ли релиз в первый раз:
IsInstall: true
# Обновляется ли уже существующий релиз:
IsUpgrade: false
# Имя релиза:
Name: myapp-production
# Имя Kubernetes Namespace:
Namespace: myapp-production
# Номер ревизии релиза:
Revision: 1

… и в $.Values.global.werf, доступном во всех чартах (только в werf):

global:
  werf:
    # Имя werf-проекта:
    name: myapp
    # Окружение:
    env: production
    # Kubernetes Namespace:
    namespace: myapp-production

Для обратной совместимости те же значения также доступны в $.Values.werf.

Пример использования:

{{ $.Release.Namespace }}
{{ $.Values.global.werf.env }}

Результат:

myapp-production
production

Информация о чарте

werf хранит информацию о текущем чарте в объекте $.Chart:

# Является ли чарт основным:
IsRoot: true

# Содержимое Chart.yaml:
Name: mychart
Version: 1.0.0
Type: library
KubeVersion: "~1.20.3"
AppVersion: "1.0"
Deprecated: false
Icon: https://example.org/mychart-icon.svg
Description: This is My Chart
Home: https://example.org
Sources:
  - https://github.com/my/chart
Keywords:
  - apps
Annotations:
  anyAdditionalInfo: here
Dependencies:
- Name: redis
  Condition: redis.enabled

Пример использования:

{{ $.Chart.Name }}

Результат:

mychart

Информация о шаблоне

werf хранит информацию о текущем шаблоне в свойствах объекта $.Template:

# Относительный путь к директории templates чарта:
BasePath: mychart/templates
# Относительный путь к текущему файлу шаблона:
Name: mychart/templates/example.yaml

Пример использования:

{{ $.Template.Name }}

Результат:

mychart/templates/example.yaml

Информация о Git-коммите (только в werf)

werf хранит информацию о Git-коммите, на котором он был запущен, в $.Values.global.werf.commit, доступном во всех чартах:

global:
  werf:
    commit:
      date:
        # Дата Git-коммита, на котором был запущен werf (человекочитаемая форма):
        human: 2022-01-21 18:51:39 +0300 +0300
        # Дата Git-коммита, на котором был запущен werf (Unix time):
        unix: 1642780299
      # Хэш Git-коммита, на котором был запущен werf:
      hash: 1b28e6843a963c5bdb3579f6fc93317cc028051c

Для обратной совместимости те же значения также доступны в $.Values.werf.commit.

Пример использования:

{{ $.Values.global.werf.commit.hash }}

Результат:

1b28e6843a963c5bdb3579f6fc93317cc028051c

Информация о возможностях кластера Kubernetes

werf предоставляет информацию о возможностях кластера Kubernetes, в который werf стал бы применять Kubernetes-манифесты, через свойства объекта $.Capabilities:

KubeVersion:
  # Полная версия кластера Kubernetes:
  Version: v1.20.0
  # Мажорная версия кластера Kubernetes:
  Major: "1"
  # Минорная версия кластера Kubernetes:
  Minor: "20"
# API, поддерживаемые кластером Kubernetes:
APIVersions:
- apps/v1
- batch/v1
- # ...

… и методы объекта $.Capabilities:

  • APIVersions.Has <arg> — поддерживается ли кластером Kubernetes указанное аргументом API (например, apps/v1) или ресурс (например, apps/v1/Deployment).

Пример использования:

{{ $.Capabilities.KubeVersion.Version }}
{{ $.Capabilities.APIVersions.Has "apps/v1" }}

Результат:

v1.20.0
true