- 31 регион `<!-- local:имя -->` в двенадцати файлах удалён, а не перенесён: локальное принадлежит копии и живёт ниже маркера `<!-- conv:local -->` (META-22), так что наполнять регионы в каноне нечем - вместе с ними ушли два опустевших раздела «Связано» — в arch и ansible слоях app-directories канонических ссылок нет, а пустой заголовок ничего не адресует; CLAUDE.md уточнён: раздел заводят, когда ссылки есть - форма проверена скриптом: у всех правил модальность и «Почему», префиксы сходятся с реестром, дыр в нумерации нет
8.3 KiB
prefix, extends
| prefix | extends |
|---|---|
| ANSD | arch/app-directories.md |
Категории директорий: реализация в Ansible
Как категории из базового слоя раскладываются на сервере плейбуком.
Ключевые слова ДОЛЖЕН, НЕ ДОЛЖЕН, СЛЕДУЕТ, НЕ СЛЕДУЕТ, ДОПУСКАЕТСЯ и отметка МЕХАНИЗИРОВАНО толкуются как описано в языке конвенций версии 1 — тогда и только тогда, когда написаны заглавными.
Область действия
Раскладка меняется вместе с миграцией данных, поэтому правила распространяются на новые приложения; существующие переезжают по мере касания, отдельной кампанией не переписываются.
Правила
ANSD-1. Каждая директория объявлена переменной *_dir
ДОЛЖЕН. Директория приложения объявляется переменной плейбука внутри
base_dir, имя оканчивается на _dir. Для случая «одна директория на
категорию» это config_dir, data_dir, cache_dir; когда категория
состоит из нескольких директорий, имя даётся по содержимому (media_dir,
uploads_dir, dumps_dir).
Почему. Переменная — единственная ссылка, которую разделяют задача создания директории и список бэкапа (ANSD-4). Литерал пути в одном из этих мест означает, что переименование директории молча разойдётся с бэкапом, и обнаружится это при восстановлении.
ANSD-2. Директории создаются одной задачей циклом по списку
СЛЕДУЕТ. Список директорий в единственной задаче создания.
Почему. Этот список — единственное место, где декларировано всё, что приложение пишет на диск. Разнесённое по нескольким задачам создание отвечает на вопрос «какие директории есть у приложения» только чтением всего плейбука, а именно этот вопрос задают при заведении бэкапа и при разборе места на диске.
ANSD-3. Владелец директорий — пользователь, от имени которого работает приложение
ДОЛЖЕН. Конкретная модель — выделенный пользователь на приложение
(app_owner_uid == app_owner_gid) или общий primary_user — выбирается на
репозиторий и фиксируется ниже.
Почему. Правило про соответствие владельца рантайму, а не про конкретную модель: приложение в контейнере пишет от определённого uid, и если директория принадлежит другому, отказ произойдёт не при деплое, а при первой записи — то есть после того, как плейбук отчитался об успехе. Выбор же модели — свойство репозитория: сервер с одним пользователем и сервер с изоляцией по приложениям решают разные задачи, и навязывать одну модель обоим значит гарантировать вечное отступление.
ANSD-4. Список бэкапа собирается из тех же переменных
ДОЛЖЕН. Плейбук кладёт в base_dir файл backup-targets, строки
которого ссылаются на переменные *_dir из ANSD-1, а не на литеральные пути.
Почему. Правило вывода списка механическое (ANSD-5), но применяет его человек или шаблон — то есть ошибиться можно. Общая переменная делает целый класс ошибок невозможным: переименовал директорию — переименовалось в обоих местах. Независимо набранный список расходится тихо и проявляется в единственный момент, когда это уже неисправимо.
ANSD-5. В список бэкапа идут только данные
ДОЛЖЕН. Директории категории «данные», включая директорию дампов, — в списке; конфигурация и кеш — нет.
Почему. Реализация правила базовой конвенции. Кеш раздувает снапшот без пользы, а конфигурация содержит отрендеренные секреты — бэкап уезжает в облако, и источником истины для секретов остаётся vault, а не снапшот.
ANSD-6. Конфигурация монтируется только на чтение
СЛЕДУЕТ. В compose конфигурация подключается с :ro.
Почему. Плейбук — источник истины для конфигурации, и :ro превращает
это из договорённости в свойство системы: приложение, которое втихую
переписывает свой конфиг, падает сразу, а не расходится с репозиторием
незаметно. Приложение, которому запись в конфиг нужна по устройству,
монтируется на запись — это отступление, и оно записывается.
ANSD-7. docker-compose.yml лежит в корне base_dir
ДОЛЖЕН. Файл не переносится во вложенную директорию.
Почему. Туда смотрит project_src модуля docker_compose_v2. Правило
внешнее по происхождению, но нарушается легко — при попытке «навести
порядок» и убрать compose в config/, где ему по смыслу категорий было бы
место.
ANSD-8. Секреты рендерятся в файл конфигурации
СЛЕДУЕТ. Значения приходят из vault-переменных и попадают в файл, принадлежащий пользователю приложения.
Почему. Файл под 0600 не наследуется дочерними процессами, не виден в
docker inspect и не оседает в compose-файле на диске. Это те же три
довода, по которым базовая конвенция конфигурации выбирает файл вместо
окружения.
ANSD-9. Когда приложение не умеет файловые секреты — environment под no_log
ДОПУСКАЕТСЯ. Задача рендера идёт с no_log: true.
Почему. Явное разрешение нужно, чтобы ANSD-8 не читался как запрет на деплой такого приложения. Способ вынужденный: секрет попадает в метаданные контейнера и в compose-файл на диске. Приложение, научившееся читать секреты из файла, переводится на ANSD-8 при ближайшем касании.