- сами конвенции переехали в conventions/, описательное — в корень: LANGUAGE.md (язык записи) и GUIDE.md (как ведут конвенции) - conv синхронизирует только conventions/, пути в origin даются относительно неё — раскладка копий в репозиториях не меняется
123 lines
8.1 KiB
Markdown
123 lines
8.1 KiB
Markdown
---
|
|
extends: arch/app-directories.md
|
|
---
|
|
|
|
# Категории директорий: реализация в Ansible
|
|
|
|
Как категории из `arch/app-directories.md` раскладываются на сервере
|
|
плейбуком. Форма записи — `LANGUAGE.md`.
|
|
|
|
## Область действия
|
|
|
|
Раскладка меняется вместе с миграцией данных, поэтому правила
|
|
распространяются на **новые приложения**; существующие переезжают по мере
|
|
касания, отдельной кампанией не переписываются.
|
|
|
|
## Правила
|
|
|
|
### R1. Каждая директория объявлена переменной `*_dir`
|
|
|
|
**ДОЛЖЕН.** Директория приложения объявляется переменной плейбука внутри
|
|
`base_dir`, имя оканчивается на `_dir`. Для случая «одна директория на
|
|
категорию» это `config_dir`, `data_dir`, `cache_dir`; когда категория
|
|
состоит из нескольких директорий, имя даётся по содержимому (`media_dir`,
|
|
`uploads_dir`, `dumps_dir`).
|
|
|
|
**Почему.** Переменная — единственная ссылка, которую разделяют задача
|
|
создания директории и список бэкапа (R4). Литерал пути в одном из этих мест
|
|
означает, что переименование директории молча разойдётся с бэкапом, и
|
|
обнаружится это при восстановлении.
|
|
|
|
### R2. Директории создаются одной задачей циклом по списку
|
|
|
|
**СЛЕДУЕТ.** Список директорий в единственной задаче создания.
|
|
|
|
**Почему.** Этот список — единственное место, где декларировано всё, что
|
|
приложение пишет на диск. Разнесённое по нескольким задачам создание
|
|
отвечает на вопрос «какие директории есть у приложения» только чтением
|
|
всего плейбука, а именно этот вопрос задают при заведении бэкапа и при
|
|
разборе места на диске.
|
|
|
|
### R3. Владелец директорий — пользователь, от имени которого работает приложение
|
|
|
|
**ДОЛЖЕН.** Конкретная модель — выделенный пользователь на приложение
|
|
(`app_owner_uid == app_owner_gid`) или общий `primary_user` — выбирается на
|
|
репозиторий и фиксируется ниже.
|
|
|
|
**Почему.** Правило про соответствие владельца рантайму, а не про
|
|
конкретную модель: приложение в контейнере пишет от определённого uid, и
|
|
если директория принадлежит другому, отказ произойдёт не при деплое, а при
|
|
первой записи — то есть после того, как плейбук отчитался об успехе. Выбор
|
|
же модели — свойство репозитория: сервер с одним пользователем и сервер с
|
|
изоляцией по приложениям решают разные задачи, и навязывать одну модель
|
|
обоим значит гарантировать вечное отступление.
|
|
|
|
<!-- local:модель-владельца -->
|
|
<!-- /local -->
|
|
|
|
### R4. Список бэкапа собирается из тех же переменных
|
|
|
|
**ДОЛЖЕН.** Плейбук кладёт в `base_dir` файл `backup-targets`, строки
|
|
которого ссылаются на переменные `*_dir` из R1, а не на литеральные пути.
|
|
|
|
**Почему.** Правило вывода списка механическое (R5), но применяет его
|
|
человек или шаблон — то есть ошибиться можно. Общая переменная делает целый
|
|
класс ошибок невозможным: переименовал директорию — переименовалось в
|
|
обоих местах. Независимо набранный список расходится тихо и проявляется в
|
|
единственный момент, когда это уже неисправимо.
|
|
|
|
### R5. В список бэкапа идут только данные
|
|
|
|
**ДОЛЖЕН.** Директории категории «данные», включая директорию дампов, — в
|
|
списке; конфигурация и кеш — нет.
|
|
|
|
**Почему.** Реализация правила базовой конвенции. Кеш раздувает снапшот без
|
|
пользы, а конфигурация содержит отрендеренные секреты — бэкап уезжает в
|
|
облако, и источником истины для секретов остаётся vault, а не снапшот.
|
|
|
|
### R6. Конфигурация монтируется только на чтение
|
|
|
|
**СЛЕДУЕТ.** В compose конфигурация подключается с `:ro`.
|
|
|
|
**Почему.** Плейбук — источник истины для конфигурации, и `:ro` превращает
|
|
это из договорённости в свойство системы: приложение, которое втихую
|
|
переписывает свой конфиг, падает сразу, а не расходится с репозиторием
|
|
незаметно. Приложение, которому запись в конфиг нужна по устройству,
|
|
монтируется на запись — это отступление, и оно записывается.
|
|
|
|
### R7. `docker-compose.yml` лежит в корне `base_dir`
|
|
|
|
**ДОЛЖЕН.** Файл не переносится во вложенную директорию.
|
|
|
|
**Почему.** Туда смотрит `project_src` модуля `docker_compose_v2`. Правило
|
|
внешнее по происхождению, но нарушается легко — при попытке «навести
|
|
порядок» и убрать compose в `config/`, где ему по смыслу категорий было бы
|
|
место.
|
|
|
|
### R8. Секреты рендерятся в файл конфигурации
|
|
|
|
**СЛЕДУЕТ.** Значения приходят из vault-переменных и попадают в файл,
|
|
принадлежащий пользователю приложения.
|
|
|
|
**Почему.** Файл под `0600` не наследуется дочерними процессами, не виден в
|
|
`docker inspect` и не оседает в compose-файле на диске. Это те же три
|
|
довода, по которым базовая конвенция конфигурации выбирает файл вместо
|
|
окружения.
|
|
|
|
### R9. Когда приложение не умеет файловые секреты — `environment` под `no_log`
|
|
|
|
**ДОПУСКАЕТСЯ.** Задача рендера идёт с `no_log: true`.
|
|
|
|
**Почему.** Явное разрешение нужно, чтобы R8 не читался как запрет на
|
|
деплой такого приложения. Способ вынужденный: секрет попадает в метаданные
|
|
контейнера и в compose-файл на диске. Приложение, научившееся читать
|
|
секреты из файла, переводится на R8 при ближайшем касании.
|
|
|
|
<!-- local:отступления -->
|
|
<!-- /local -->
|
|
|
|
## Связано
|
|
|
|
<!-- local:связано -->
|
|
<!-- /local -->
|