Исходный код модуля и правила его сборки должны находиться в директории с определенной структурой. Ближайший аналог — Helm chart. На этой странице вы найдете описание директорий и файлов структуры модуля.

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

Пример структуры папки модуля, созданного из шаблона, содержащий правила сборки и публикации с помощью GitHub Actions:

1📁 my-module/
2├─ 📁 .github/
3│  ├─ 📁 workflows/
4│  │  ├─ 📝 build_dev.yaml
5│  │  ├─ 📝 build_prod.yaml
6│  │  ├─ 📝 checks.yaml
7│  │  ├─ 📝 deploy_dev.yaml
8│  │  └─ 📝 deploy_prod.yaml
9├─ 📁 .werf/
10│  ├─ 📁 workflows/
11│  │  ├─ 📝 bundle.yaml
12│  │  ├─ 📝 images.yaml
13│  │  ├─ 📝 images-digest.yaml
14│  │  ├─ 📝 python-deps.yaml
15│  │  └─ 📝 release.yaml
16├─ 📁 charts/
17│  └─ 📁 helm_lib/
18├─ 📁 crds/
19│  ├─ 📝 crd1.yaml
20│  ├─ 📝 doc-ru-crd1.yaml
21│  ├─ 📝 crd2.yaml
22│  └─ 📝 doc-ru-crd2.yaml
23├─ 📁 docs/
24│  ├─ 📝 README.md
25│  ├─ 📝 README.ru.md
26│  ├─ 📝 EXAMPLES.md
27│  ├─ 📝 EXAMPLES.ru.md
28│  ├─ 📝 CONFIGURATION.md
29│  ├─ 📝 CONFIGURATION.ru.md
30│  ├─ 📝 CR.md
31│  ├─ 📝 CR.ru.md
32│  ├─ 📝 FAQ.md
33│  ├─ 📝 FAQ.ru.md
34│  ├─ 📝 ADVANCED_USAGE.md
35│  └─ 📝 ADVANCED_USAGE.ru.md
36├─ 📁 hooks/
37│  ├─ 📝 ensure_crds.py
38│  ├─ 📝 hook1.py
39│  └─ 📝 hook2.py
40├─ 📁 images/
41│  ├─ 📁 nginx
42│  │  └─ 📝 Dockerfile
43│  └─ 📁 backend
44│     └─ 📝 werf.inc.yaml
45├─ 📁 lib/
46│  └─ 📁 python/
47│     └─ 📝 requirements.txt
48├─ 📁 openapi/
49│  ├─ 📁 conversions
50│  │  ├─ 📁 testdata
51│  │  │  ├─ 📝 v1-1.yaml
52│  │  │  └─ 📝 v2-1.yaml
53│  │  ├─ 📝 conversions_test.go
54│  │  └─ 📝 v2.yaml
55│  ├─ 📝 config-values.yaml
56│  ├─ 📝 doc-ru-config-values.yaml
57│  └─ 📝 values.yaml
58├─ 📁 templates/
59│  ├─ 📝 a.yaml
60│  └─ 📝 b.yaml
61├─ 📝 .helmignore
62├─ 📝 Chart.yaml
63├─ 📝 module.yaml
64├─ 📝 werf.yaml
65└─ 📝 werf-giterminism.yaml

charts

В папке /charts находятся вспомогательные чарты Helm, которые используются при рендере шаблонов.

У Deckhouse Kubernetes Platform (DKP) существует собственная библиотека для работы с шаблонами – lib-helm. О возможностях библиотеки можно почитать в репозитории lib-helm. Чтобы положить библиотеку в модуль, загрузите tgz-архив с нужным релизом и переместите его в директорию /charts модуля.

crds

В этой директории лежат CustomResourceDefinition (CRD), которые используются компонентами модуля. CRD обновляются каждый раз, когда запускается модуль, если есть обновления.

Для того чтобы CRD из директории /crds модуля начали применяться в кластере, нужно добавить хук hello.py из шаблона модуля. Подробнее о хуках в разделе hooks.

Чтобы отобразить CRD из директории /crds в документации на сайте или модуле documentation в кластере, выполните следующие шаги:

  • создайте файл перевода со структурой аналогичной исходному файлу ресурса:
    • оставьте только параметры description, в которых укажите текст перевода;
    • используйте префикс doc-ru- в названии: например /crds/doc-ru-crd.yaml для /crds/crd.yaml.
  • создайте файлы /docs/CR.md и /docs/CR.ru.md.

docs

В папке /docs находится документация к модулю:

  • README.md — описание, для чего нужен модуль, какую проблему он решает и общие архитектурные принципы.

    Метаданные файла (front matter) в виде YAML-структуры должны быть во всех языковых версиях файла. Параметры, доступные для использования в метаданных:

    • title(рекомендуется) Заголовок страницы описания модуля. Пример — “Веб-консоль администратора Deckhouse”. Он же используется в навигации, если не указан параметр linkTitle.
    • menuTitle(желательно) Название модуля в меню слева на странице (sidebar). Пример — “Deckhouse Admin”. Если отсутствует, то используется название директории или репозитория, например deckhouse-admin.
    • linkTitle(опционально) Отдельный заголовок для навигации, если, например, title очень длинный. Если отсутствует, то используется параметр title.
    • description(желательно) Краткое уникальное описание содержимого страницы (до 150 символов). Не повторяет title. Служит продолжением названия и раскрывает его детальнее. Используется при генерации превью-ссылок и индексации поисковыми системами. Пример — «Модуль позволяет полностью управлять кластером Kubernetes через веб-интерфейс, имея только навыки работы мышью.»
    • d8Edition(опционально) ce/be/se/ee. Минимальная редакция в которой доступен модуль. По умолчанию — ce.
    • moduleStatus(опционально) experimental. Статус модуля. Если модуль помечен как experimental, то на его страницах отображается предупреждение о том, что код нестабилен, а также отображается специальная плашка в меню.
    Пример метаданных
    1---
    2title: "Веб-консоль администратора Deckhouse"
    3menuTitle: "Deckhouse Admin"
    4description: "Модуль позволяет полностью управлять кластером Kubernetes через веб-интерфейс, имея только навыки работы мышью."
    5---
    
    
  • EXAMPLES.md – примеры конфигурации модуля с описанием.

    Метаданные файла (front matter) в виде YAML-структуры должны быть во всех языковых версиях файла. Параметры, доступные для использования в метаданных:

    • title(рекомендуется) Заголовок страницы. Пример: “Примеры”. Он же используется в навигации, если нет linkTitle.
    • description(желательно) Краткое уникальное описание содержимого страницы (до 150 символов). Не повторяет title. Служит продолжением названия и раскрывает его детальнее. Используется при генерации превью-ссылок, индексации поисковиками. Пример: “Примеры хранения секретов в нейронной сети с автоматической подстановкой в мысли при общении.”
    • linkTitle(опционально) Отдельный заголовок для навигации, если, например, title очень длинный. Если отсутствует, то используется title.
    Пример метаданных
    1---
    2title: "Примеры"
    3description: "Примеры хранения секретов в нейронной сети с автоматической подстановкой в мысли при общении."
    4---
    
    
  • FAQ.md – часто задаваемые вопросы, касающиеся эксплуатации модуля (“Какой сценарий выбрать: А или Б?”).

    Метаданные файла (front matter) в виде YAML-структуры должны быть во всех языковых версиях файла. Параметры, доступные для использования в метаданных:

    • title(рекомендуется) Заголовок страницы.
    • description(желательно) Краткое уникальное описание содержимого страницы (до 150 символов).
    • linkTitle(опционально) Отдельный заголовок для навигации, если, например, title очень длинный. Если отсутствует, то используется title.
    Пример метаданных
    1---
    2title: "Часто задаваемые вопросы"
    3description: "Часто задаваемые вопросы и ответы на них."
    4---
    
    
  • ADVANCED_USAGE.md – инструкция по отладке модуля.

    Метаданные файла (front matter) в виде YAML-структуры должны быть во всех языковых версиях файла. Параметры, доступные для использования в метаданных:

    • title(рекомендуется) Заголовок страницы.
    • description(желательно) Краткое уникальное описание содержимого страницы (до 150 символов).
    • linkTitle(опционально) Отдельный заголовок для навигации, если, например, title очень длинный. Если отсутствует, то используется title.
    Пример метаданных
    1---
    2title: "Отладка модуля"
    3description: "В разделе разбираются все шаги по отладке модуля."
    4---
    
    
  • CR.md и CR.ru.md – файл для генерации ресурсов из папки /crds/ добавьте вручную.

    Пример метаданных
    1---
    2title: "Кастомные ресурсы"
    3---
    
    
  • CONFIGURATION.md – файл для создания ресурсов из /openapi/config-values.yaml и /openapi/doc-<LANG>-config-values.yaml добавьте вручную.

    Пример метаданных
    1---
    2title: "Настройки модуля"
    3---
    
    

Все изображения, PDF-файлы и другие медиафайлы нужно хранить в директории /docs или ее подкаталогах (например, /docs/images/). Все ссылки на файлы должны быть относительными.

Для каждого языка нужен файл с соответствующим суффиксом. Например, image1.jpg и image1.ru.jpg. Используйте ссылки:

  • [image1](image1.jpg) в англоязычном документе;
  • [image1](image1.ru.jpg) в русскоязычном документе.

hooks

В директории /hooks находятся хуки модуля. Хук — это исполняемый файл, выполняемый при реакции на событие. Хуки используются модулем также для динамического взаимодействия с API Kubernetes. Например, они могут быть использованы для обработки событий, связанных с созданием или удалением объектов в кластере. Познакомьтесь с концепцией хуков, прежде чем начать разрабатывать свой собственный хук. Для ускорения разработки хуков можно воспользоваться Python-библиотекой от команды Deckhouse.

Требования к работе хука:

  • Хук должен быть написан на языке Python.
  • При запуске с параметром --config, хук должен выводить свою конфигурацию в формате YAML.
  • При запуске без параметров, хук должен выполнять свое основное действие.

Файлы хуков должны иметь права на выполнение. Добавьте их командой chmod +x <путь до файла с хуком>.

В репозитории шаблона модуля можно найти примеры хуков.

Пример хука, включающего в работу CRD (из директории /crds модуля):

1import os
2import yaml
3from deckhouse import hook
4# Ожидается структура с возможными поддиректориями, подобная следующей:
5#
6#   my-module/
7#       crds/
8#           crd1.yaml
9#           crd2.yaml
10#           subdir/
11#               crd3.yaml
12#       hooks/
13#           ensure_crds.py # this file
14config = """
15configVersion: v1
16onStartup: 5
17"""
18def main(ctx: hook.Context):
19    for crd in iter_manifests(find_crds_root(__file__)):
20        ctx.kubernetes.create_or_update(crd)
21def iter_manifests(root_path: str):
22    if not os.path.exists(root_path):
23        return
24    for dirpath, dirnames, filenames in os.walk(top=root_path):
25        for filename in filenames:
26            if not filename.endswith(".yaml"):
27                # Ищем только манифесты.
28                continue
29            if filename.startswith("doc-"):
30                # Пропускаем YAML-файлы с документацией модуля.
31                continue
32        crd_path = os.path.join(dirpath, filename)
33        with open(crd_path, "r", encoding="utf-8") as f:
34            for manifest in yaml.safe_load_all(f):
35                if manifest is None:
36                    continue
37                yield manifest
38    for dirname in dirnames:
39        subroot = os.path.join(dirpath, dirname)
40        for manifest in iter_manifests(subroot):
41            yield manifest
42def find_crds_root(hookpath):
43    hooks_root = os.path.dirname(hookpath)
44    module_root = os.path.dirname(hooks_root)
45    crds_root = os.path.join(module_root, "crds")
46    return crds_root
47if __name__ == "__main__":
48    hook.run(main, config=config)

images

В директории /images находятся инструкции по сборке образов контейнеров модуля. На первом уровне находятся директории для файлов, используемых при создании образа контейнера, на втором — контекст для сборки.

Существует два способа описания образа контейнера:

  1. Dockerfile — файл, который содержит команды для быстрой сборки образов. Если необходимо собрать приложение из исходного кода, поместите его рядом с Dockerfile и включите его в образ с помощью команды COPY.
  2. Файл werf.inc.yaml, который является аналогом секции описания образа из werf.yaml.

Имя образа совпадает с именем директории для этого модуля, записанным в нотации camelCase с маленькой буквы. Например, директории /images/echo-server соответствует имя образа echoServer.

Собранные образы имеют content-based теги, которые можно использовать в сборке других образов. Чтобы использовать content-based теги образов, подключите библиотеку lib-helm. Вы также можете воспользоваться другими функциями библиотеки helm_lib Deckhouse Kubernetes Platform.

Пример использования content-based тега образа в Helm-чарте:

1image: {{ include "helm_lib_module_image" (list . "<имя образа>") }}

openapi

conversions

В директории /openapi/conversions находятся файлы конверсий параметров модуля и их тесты.

Конверсии параметров модуля позволяют конвертировать OpenAPI-спецификацию параметров модуля одной версии в другую. Конверсии могут быть необходимы в случаях, когда в новой версии OpenAPI-спецификации параметр переименовывается или переносится в другое место.

Каждая конверсия возможна только между двумя смежными версиями (например с первой версии на вторую). Конверсий может быть несколько, и цепочка конверсий должна покрывать все версии спецификации параметров, без “пропусков”.

Файл конверсии, это YAML-файл произвольного имени следующего формата:

1version: N # Номер версии, в которую нужно выполнить конверсию. 
2conversions: []  # Набор выражений jq, для преобразования данных из предыдущей версии.

Пример файла конверсии параметров модуля, когда в версии 2 удаляется параметр .auth.password:

1version: 2
2conversions:
3  - del(.auth.password) | if .auth == {} then del(.auth) end

Тесты конверсий

Для написания тестов конверсий можно использовать функцию conversion.TestConvert, которой нужно передать:

  • путь до исходного файла конфигурации (версия до конвертации);
  • путь до ожидаемого файла конфигурации (версия после конвертации).

Пример теста конверсии.

templates

В директории /templates находятся шаблоны Helm.

  • Для доступа к настройкам модуля в шаблонах используйте путь .Values.<имяМодуля>, а для глобальных настроек .Values.global. Имя модуля конвертируется в нотации camelCase.

  • Для упрощения работы с шаблонами используйте lib-helm – это набор дополнительных функций, которые облегчают работу с глобальными и модульными значениями.

  • Доступы в registry из ресурса ModuleSource доступны по пути .Values.<имяМодуля>.registry.dockercfg.

  • Чтобы использовать эти функции для пула образов в контроллерах, создайте секрет и добавьте его в соответствующий параметр: "imagePullSecrets": [{"name":"registry-creds"}].

    1apiVersion: v1
    2kind: Secret
    3metadata:
    4  name: registry-creds
    5type: kubernetes.io/dockerconfigjson
    6data:
    7  .dockerconfigjson: {{ .Values.<имяМодуля>.registry.dockercfg }}
    

Модуль может иметь параметры, с помощью которых может менять свое поведение. Параметры модуля и схема их валидации описываются в OpenAPI-схемах в директории /openapi.

Настройки лежат в двух файлах: config-values.yaml и values.yaml.

Пример OpenAPI-схемы можно найти в шаблоне модуля.

config-values.yaml

Необходим для проверки параметров модуля, которые пользователь может настроить через ModuleConfig.

Чтобы схема была представлена в документации на сайте или в модуле documentation в кластере, создайте:

  • файл doc-ru-config-values.yaml со структурой, аналогичной структуре файла config-values.yaml. В файле doc-ru-config-values.yaml оставьте только переведенные параметры description;
  • файлы /docs/CONFIGURATION.md и /docs/CONFIGURATION.ru.md — это включит показ данных из файлов /openapi/config-values.yaml и /openapi/doc-ru-config-values.yaml.

Пример схемы /openapi/config-values.yaml с одним настраиваемым параметром nodeSelector:

1type: object
2properties:
3  nodeSelector:
4    type: object
5    additionalProperties:
6      type: string
7    description: |
8      The same as the Pods' `spec.nodeSelector` parameter in Kubernetes.
9      If the parameter is omitted or `false`, `nodeSelector` will be determined
10      [automatically](https://deckhouse.io/products/kubernetes-platform/documentation/v1/#advanced-scheduling).</code>

Пример файла /openapi/doc-ru-config-values.yaml для русскоязычного перевода схемы:

1properties:
2  nodeSelector:
3    description: |
4      Описание на русском языке. Разметка Markdown.</code>

values.yaml

Необходим для проверки исходных данных при рендере шаблонов без использования дополнительных функций Helm chart. Ближайший аналог — schema-файлы из Helm.

В values.yaml можно автоматически добавить валидацию параметров из config-values.yaml. В этом случае, минимальный values.yaml выглядит следующим образом:

1x-extend:
2  schema: config-values.yaml
3type: object
4properties:
5  internal:
6    type: object
7    default: {}

.helmignore

Исключите файлы из Helm-релиза с помощью .helmignore. В случае модулей DKP директории /crds, /images, /hooks, /openapi обязательно добавляйте в .helmignore, чтобы избежать превышения лимита размера Helm-релиза в 1 Мб.

Chart.yaml

Обязательный файл для чарта, аналогичный Chart.yaml из Helm. Должен содержать, как минимум, параметр name с именем модуля и параметр version с версией.

Пример:

1name: echoserver
2version: 0.0.1
3dependencies:
4- name: deckhouse_lib_helm
5  version: 1.5.0
6  repository: https://deckhouse.github.io/lib-helm

module.yaml

В данном файле настройте следующие опции модуля:

  • tags: string — дополнительные теги для модуля, которые преобразуются в лейблы модуля: module.deckhouse.io/$tag="".
  • weight: integer — вес модуля. Вес по-умолчанию: 900, можно задать собственный вес в диапазоне 900 – 999.
  • stage: stringcтадия жизненного цикла модуля. Может быть Sandbox, Incubating, Graduated или Deprecated.
  • description: string — описание модуля.

Например:

1tags: ["test", "myTag"]
2weight: 960
3stage: "Sandbox"
4description: "my awesome module"

Будет создан модуль (deckhouse.io/v1alpha/Module) с лейблами: module.deckhouse.io/test="" и module.deckhouse.io/myTag="", весом 960 и описанием my awesome module.

Таким образом можно управлять очередностью модулей, а также задавать дополнительную метаинформацию для них.