Files
K3S/docs/custom-addons.md
Sergey Antropoff 4eaf91e2d2 docs: руководство по своим аддонам и ссылки в README/Molecule/справочнике
- Добавлен docs/custom-addons.md: структура addons/<name>, playbook, group_vars,
  playbooks/addons.yml, Makefile, Molecule, чеклист и см. также.
- docs/addons.md, getting-started.md: отсылки на custom-addons.md.
- README.md: строка в таблице документации.
- docs/molecule-testing.md: уточнены molecule-prometheus/istio (тесты аддонов),
  разделы prometheus-stack/istio, ссылка на руководство в блоке про новые тесты.
- docs/make-reference.md: примечание к make addon-<name>.
2026-04-28 01:43:13 +03:00

214 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Свои аддоны для 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/<name>/
├── README.md # обязательно: назначение, переменные, примеры
├── playbook.yml # точка входа для make addon-<name>
└── 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/<name>/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/<name>/`).
- `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-<name>` существовал, в `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/<name>/playbook.yml + addons/<name>/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/<name>/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-<name>`** (по аналогии с соседними аддонами) и вызов из **`molecule-addon-all`**, иначе CI/ручной `make molecule-addon-all` **не** увидит аддон.
---
## 8. Документация в репозитории
- **`addons/<name>/README.md`**: назначение, требования (ingress, БД, storage), переменные, пример `make`, ссылки на апстрим.
- **Корневой** [Аддоны](addons.md): добавьте строку в таблицу «Каталог аддонов» (флаг, краткое описание, ссылка на README), если аддон попал в **основной** репозиторий.
- **Секреты** — перечислить в `group_vars/all/vault.yml.example`, если введены новые `vault_*` ключи.
---
## 9. Чеклист нового аддона
- [ ] `addons/<name>/playbook.yml` + `role/` с осмысленными `defaults` и идемпотентными `tasks`
- [ ] `addons/<name>/README.md`
- [ ] `addon_<name>: false` и переменные в `group_vars/all/addons.yml` (и секреты в `vault` при необходимости)
- [ ] Play в `playbooks/addons.yml` с `when: addon_<name> | default(false) | bool` и корректным `hosts`
- [ ] Таргет `addon-<name>` в `Makefile`
- [ ] Molecule: `role/molecule/default/*`, `make molecule-addon-<name>` зелёный
- [ ] Добавить `molecule-addon-<name>` в `molecule-addon-all` в `Makefile` (если аддон в основной ветке репо)
- [ ] Строка в таблице [docs/addons.md](addons.md)
---
## 10. Кастомизация без форка (альтернатива «своему» аддону)
Если нужно **один раз** переопределить поведение существующей роли:
- `make addon-<name> ARGS="-e var=value"`
- `host_vars/<хост>.yml` / `group_vars` для тонкой настройки
- Для постоянного форка лучше **скопировать** роль в `addons/<your-name>/` и следовать чеклисту выше, явно называя сущности, чтобы не пересекаться с апстримом.
---
## См. также
- [Аддоны: установка, каталог, зависимости](addons.md)
- [Molecule: сценарии, отладка, шаблоны тестов](molecule-testing.md)
- [Справочник make](make-reference.md)
- [Конфигурация](configuration.md)