# Свои аддоны для k3s-ansible Этот документ описывает, как **добавить собственный аддон** в проект: структуру каталога, плейбуки, переменные, интеграцию в `make`, и тесты Molecule. Предполагается, что вы уже читали [Аддоны](addons.md) и понимаете, как включать готовые компоненты через `group_vars/all/addons.yml`. --- ## 1. Что считается «аддоном» Аддон — это **отдельная Ansible-роль** с **тонким плейбуком** в каталоге `addons/<имя>/`. Установка с хоста делается так: ```bash make addon-<имя> # прямой запуск make install-addons # все аддоны с `addon_<имя>: true` в addons.yml ``` Внутри Docker runner вызывается `addon <имя>` (см. `docker/entrypoint.sh`): исполняется файл `addons/<имя>/playbook.yml`. Имя каталога **должно** совпадать с аргументом `addon` (например `addons/my-app/playbook.yml` → `make addon-my-app`). --- ## 2. Минимальная структура каталога ``` addons// ├── README.md # обязательно: назначение, переменные, примеры ├── playbook.yml # точка входа для make addon- └── role/ ├── tasks/main.yml ├── defaults/main.yml # все пользовательские переменные с разумными default ├── meta/main.yml # опционально: dependencies, role_name ├── templates/ # Jinja2 (.j2) — манифесты, values для Helm ├── files/ # статические файлы └── molecule/ └── default/ ├── molecule.yml # драйвер docker, платформа master01 ├── converge.yml # «собрать» артефакты для проверки └── verify.yml # assert ``` - **Роль** лежит **внутри** `addons//role/`, путь в плейбуке — относительно `playbook.yml` (см. ниже). - Для **Helm-чарта** часто добавляют `role/chart/` или скачивание chart в `tasks` — ориентируйтесь на существующие аддоны (`gitea`, `loki`, `technitium-dns`). --- ## 3. Плейбук `playbook.yml` ### 3.1. Вариант «только аддон» (как у большинства поставляемых аддонов) ```yaml --- - name: Install My Application hosts: k3s_master[0] gather_facts: false become: true roles: - role: "{{ playbook_dir }}/role" ``` - `playbook_dir` — каталог, где лежит этот `playbook.yml` (т.е. `addons//`). - `hosts` выбирайте по смыслу (см. [раздел 5](#5-выбор-группы-hosts-и-порядок-в-addonsyml) ниже). ### 3.2. Плейбук в общем списке `playbooks/addons.yml` Для участия в `make install-addons` / `make install-full` добавьте **отдельный play** в `playbooks/addons.yml` **в правильном месте по зависимостям** (сначала NFS/CSI, ingress, cert-manager, затем остальные): ```yaml - name: Install My Application hosts: k3s_master[0] gather_facts: false become: true when: addon_my_app | default(false) | bool roles: - role: "{{ playbook_dir }}/../addons/my-app/role" ``` Имя флага в `when` и в `group_vars` должно быть согласовано: `addon_my_app` → `addon_my_app: true/false`. --- ## 4. Переменные: `group_vars/all/addons.yml` 1. **Флаг включения** (в начале файла, рядом с остальными `addon_*`): ```yaml addon_my_app: false ``` 2. **Переменные по умолчанию** для аддона (префикс лучше делать уникальным, например `my_app_*`): ```yaml # ─── My Application ───────────────────────────────────── my_app_namespace: "my-app" my_app_ingress_host: "myapp.example.com" ``` 3. **Секреты** — только через Ansible Vault, в `group_vars/all/vault.yml` (и пример в `vault.yml.example`): ```yaml vault_my_app_password: "..." ``` См. существующие комментарии в `addons.yml`: там же лежат примеры для похожих сервисов. --- ## 5. Выбор группы hosts и порядок в addons.yml | Группа / паттерн | Когда использовать | |------------------|------------------| | `k3s_master[0]` | Почти все компоненты, которые ставятся через `kubectl`/`helm` с одной control-plane ноды | | `k3s_cluster` | DaemonSet / агенты на всех нодах (пример: ingress-nginx, часть CSI) | | `nfs_server` | NFS-сервер не на K8s (отдельная группа в inventory) | | `hysteria2_server` | Удалённый VPS (см. `hysteria2-server`) | | `splitgw` | Хосты split-gateway вне K8s или вместе с k8s в зависимости от роли | **Порядок play в `playbooks/addons.yml` важен:** не ставьте приложение, требующее Ingress, раньше play с `ingress-nginx`, не ставьте TLS-зависимое раньше `cert-manager`, если оно ожидает готовые `ClusterIssuer`. Новый аддон обычно добавляют **в конец** или сразу после логического предка. --- ## 6. Цель `Makefile` Чтобы `make addon-` существовал, в `Makefile` в секции аддонов должен быть таргет вида: ```makefile addon-my-app: _check_env _check_image @printf "$(CYAN)Устанавливаю My Application...$(NC)\n" $(DOCKER_RUN) addon my-app $(ARGS) ``` Имя после `addon` — **каталог** `addons/my-app/`. См. комментарий в Makefile: *«Добавить новый аддон: создай addons//playbook.yml + addons//role/»*. `ARGS` передаётся в `ansible-playbook` как extra vars (кастомизация без правки `addons.yml`). --- ## 7. Тесты Molecule Без Molecule легко сломать шаблоны при рефакторинге. Рекомендуемый минимум — сценарий `role/molecule/default/`. ### 7.1. Как запускается ```bash make build make molecule-addon-my-app ``` Runner (`docker/entrypoint.sh`, команда `molecule-addon`) заходит в каталог **`addons//role`** и выполняет `molecule test` (см. `JUNIT_OUTPUT_DIR` для отчётов в составе `make molecule-all`). ### 7.2. `molecule.yml` Обычно одна тестовая нода `master01` (образ `geerlingguy/docker-ubuntu2204-ansible`), без privileged, если не нужен K3S в контейнере. Шаблон — любой существующий аддон рядом с вашим по сложности. ### 7.3. `converge.yml` Типовые варианты: 1. **Рендер Jinja2 + проверка файла** (простой аддон). 2. **Helm: `template` + `dest` в `/tmp/...` + `helm lint` / `helm template`** - Команды `helm` выполняйте с **`delegate_to: localhost` и `run_once: true`**, иначе бинарник не найдётся в ноде Molecule. - То же для `ansible.builtin.copy` / `template`, если пишете файлы, которые читает `helm` с localhost: пишите **на localhost** (иначе «файл не найден» при `delegate_to: localhost` у helm). 3. **Переменные** — задайте в `vars:` все, что **обязаны** знать шаблоны роли (в т.ч. пустые строки для optional полей), иначе `AnsibleUndefinedVariable` в тесте. ### 7.4. `verify.yml` - Assert по содержимому сгенерированных YAML/манифестов. - Булевы из `slurp`+`from_yaml` часто приходят **строками** — сравнивайте так: `(v.flag | string | lower) == 'true'`. - Если проверяете **multi-doc YAML** (`---`), используйте `from_yaml_all` / разбор по документам. - `hosts: localhost` удобен, если артефакты гарантированно на runner (файлы в `/tmp` после `delegate_to: localhost`). Подробности и типовые ошибки: [Тестирование через Molecule](molecule-testing.md#частые-причины-падений-addon-molecule). ### 7.5. Включение в общий прогон После готового сценария добавьте в `Makefile` цель **`molecule-addon-`** (по аналогии с соседними аддонами) и вызов из **`molecule-addon-all`**, иначе CI/ручной `make molecule-addon-all` **не** увидит аддон. --- ## 8. Документация в репозитории - **`addons//README.md`**: назначение, требования (ingress, БД, storage), переменные, пример `make`, ссылки на апстрим. - **Корневой** [Аддоны](addons.md): добавьте строку в таблицу «Каталог аддонов» (флаг, краткое описание, ссылка на README), если аддон попал в **основной** репозиторий. - **Секреты** — перечислить в `group_vars/all/vault.yml.example`, если введены новые `vault_*` ключи. --- ## 9. Чеклист нового аддона - [ ] `addons//playbook.yml` + `role/` с осмысленными `defaults` и идемпотентными `tasks` - [ ] `addons//README.md` - [ ] `addon_: false` и переменные в `group_vars/all/addons.yml` (и секреты в `vault` при необходимости) - [ ] Play в `playbooks/addons.yml` с `when: addon_ | default(false) | bool` и корректным `hosts` - [ ] Таргет `addon-` в `Makefile` - [ ] Molecule: `role/molecule/default/*`, `make molecule-addon-` зелёный - [ ] Добавить `molecule-addon-` в `molecule-addon-all` в `Makefile` (если аддон в основной ветке репо) - [ ] Строка в таблице [docs/addons.md](addons.md) --- ## 10. Кастомизация без форка (альтернатива «своему» аддону) Если нужно **один раз** переопределить поведение существующей роли: - `make addon- ARGS="-e var=value"` - `host_vars/<хост>.yml` / `group_vars` для тонкой настройки - Для постоянного форка лучше **скопировать** роль в `addons//` и следовать чеклисту выше, явно называя сущности, чтобы не пересекаться с апстримом. --- ## См. также - [Аддоны: установка, каталог, зависимости](addons.md) - [Molecule: сценарии, отладка, шаблоны тестов](molecule-testing.md) - [Справочник make](make-reference.md) - [Конфигурация](configuration.md)