- 7 и 9 правил соответственно, у каждого модальность и обоснование - условие выбора первичного ключа стало правилом с таблицей веток, на которые можно ссылаться из отступлений и механизации
8.1 KiB
extends
| extends |
|---|
| arch/app-directories.md |
Категории директорий: реализация в Ansible
Как категории из arch/app-directories.md раскладываются на сервере
плейбуком. Форма записи — common/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, и если директория принадлежит другому, отказ произойдёт не при деплое, а при первой записи — то есть после того, как плейбук отчитался об успехе. Выбор же модели — свойство репозитория: сервер с одним пользователем и сервер с изоляцией по приложениям решают разные задачи, и навязывать одну модель обоим значит гарантировать вечное отступление.
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 при ближайшем касании.