Инфраструктура сервиса: конфиг и 12-factor
12-factor - свод правил, по которым приложение живёт в облаке, и его любимая на собесе часть - конфигурация: что различается между средами, должно быть снаружи кода. Проверяют, понимаешь ли ты, почему один образ едет во все среды и почему секретам не место в git.
Типовые формулировки: «где хранить конфиг для разных сред?», «почему один образ на все среды?», «куда девать секреты».
Конфиг среды - в переменных окружения
Принцип 12-factor: всё, что РАЗЛИЧАЕТСЯ между средами - адреса БД, ключи, флаги - живёт в переменных окружения, а не в коде и не в VCS (version control system). Это отделяет код от среды: сам код одинаков, различия задаются снаружи.
Отсюда единый артефакт: один протестированный образ едет во все среды, а различия подставляются переменными при запуске. Прод гоняет РОВНО то, что проверено в CI, не пересобранное под прод, а тот же самый образ. Хардкодить конфиг в коде или заводить git-ветку под каждую среду - прямое нарушение: код начинает различаться там, где различаться должна только конфигурация.
// Собирать отдельный образ под прод - подрывать доверие к тому, что тестировалось: в прод уезжает не проверенный артефакт, а его двойник.
- 12-factor
- конфиг среды в переменных окружения, отдельно от кода
- единый артефакт
- один образ на все среды, различие - конфиг
Секреты - вне кода и образа
Секреты - пароли, ключи, токены - не хранят в git и не зашивают в образ. Причина та же, что у конфига, но острее: образ один на все среды и легко утекает, а git хранит историю навечно - закоммиченный однажды секрет остаётся в истории, даже если удалить его следующим коммитом.
Правильно - переменные окружения при запуске или секрет-менеджер (Vault, облачные secrets). Тогда секрет не является частью артефакта и его можно ротировать, не пересобирая образ.
// Практическое следствие: .env с реальными секретами в .gitignore, а в репозитории - только .env.example с именами переменных без значений.
- секреты
- пароли/ключи вне кода и образа
Как отвечать: «Почему один и тот же образ должен ехать во все среды?»
Чтобы в прод попадало ровно то, что проверено. По 12-factor различаться между средами должна только конфигурация - адреса БД, ключи, флаги, и она задаётся переменными окружения при запуске, а не пересборкой. Тогда артефакт неизменен: образ, прошедший тесты в CI, тот же самый едет в stage и prod, отличаясь лишь подставленным окружением. Если же собирать отдельный образ под прод, я в прод выкатываю не тот бинарник, что тестировал, а его двойника, и доверие к тестам падает, потому что различия сборки могут принести баг, которого в CI не было. Секреты по той же логике держу снаружи - в переменных или секрет-менеджере, не в образе и не в git.
Названа суть (в прод едет проверенный артефакт), объяснено почему отдельная сборка под прод опасна и связано с конфигом и секретами - системное понимание, а не пересказ правила.
На чём валят
- −Хардкодить конфиг среды в коде или заводить ветку git на каждую среду.
- −Собирать отдельный образ под прод - подрывает доверие к тому, что тестировалось.
- −Хранить секреты в git или зашивать их в образ - утекут и останутся в истории навсегда.
- −Класть реальный .env в репозиторий вместо .env.example с одними именами переменных.
Проверьте себя
Пять вопросов из банка по этой подтеме. Всего их 12, остальные разбираются в тренажёре.
- Один и тот же образ едет на dev и prod. Как получить разное поведение сред?A)Держать if-ветки в коде, проверяющие имя хоста текущей машиныB)Пересобирать образ на каждый деплой с новыми значениями внутриC)Прокинуть разные переменные окружения при запуске образаD)Собрать два отдельных образа с зашитыми внутрь настройками каждой среды
показать ответ и разбор
+C)Прокинуть разные переменные окружения при запуске образа// разбор: Ключевой смысл вынесенного конфига: один протестированный образ — во все среды, а различия (адрес БД, уровень логов, флаги) задаются переменными окружения при запуске. Тогда prod гоняет ровно то, что проверено в CI, а не пересобранный заново артефакт. Разные образы под среды сводят на нет гарантии тестирования.
- Где по 12-factor держат конфиг, различающийся между средами (адреса БД, ключи)?A)В отдельной ветке git на каждую среду, где значения прописаны прямо в файлахB)В самом коде приложения, чтобы он деплоился вместе с нужными значениямиC)В переменных окружения, отдельно от кода и вне системы контроля версийD)В образе Docker, зашитым на этапе сборки под каждую конкретную среду отдельно
показать ответ и разбор
+C)В переменных окружения, отдельно от кода и вне системы контроля версий// разбор: 12-factor предписывает хранить конфиг, различающийся между средами (адреса сервисов, учётные данные, флаги), в переменных окружения — отдельно от кода и вне VCS. Это отделяет код от среды: один и тот же образ/кодовая база работает всюду, а различия задаются переменными при запуске. Хардкод в коде или ветка git на каждую среду ломают этот принцип.
- Один протестированный образ едет во все среды, различия — переменными. Что это даёт?A)Ускоряет сборку за счёт того, что образ собирается заново под каждую среду отдельноB)Позволяет для прода собирать отдельный, специально оптимизированный под него образC)Даёт возможность менять код приложения прямо в проде без пересборки образаD)Прод гоняет ровно то, что проверено в CI — исчезает «в тесте работало»
показать ответ и разбор
+D)Прод гоняет ровно то, что проверено в CI — исчезает «в тесте работало»// разбор: Единый артефакт — тот же образ проходит CI и едет в staging и прод без пересборки, а среды различаются лишь переменными окружения. Так на проде исполняется ровно то, что протестировано, — исчезает класс проблем «в тесте работало, на проде нет» из-за разных сборок. Собирать отдельный образ под прод — значит запускать непроверенное и подрывать доверие к тестам.
- Почему 12-factor требует, чтобы процессы приложения были stateless?A)Любой инстанс обслужит любой запрос, легко масштабировать и перезапускатьB)Чтобы каждый процесс намертво привязать к конкретному пользователю на всё время сессииC)Чтобы ускорить обработку запросов за счёт полного отказа от обращений к базе данныхD)Чтобы приложение вообще не хранило никаких данных, включая базу данных и файлы
показать ответ и разбор
+A)Любой инстанс обслужит любой запрос, легко масштабировать и перезапускать// разбор: Stateless-процессы не хранят состояние между запросами в своей памяти/на своём диске: сессии, кеши, данные выносят во внешние backing-сервисы (БД, Redis). Тогда любой инстанс обслужит любой запрос, их можно свободно добавлять, убирать и перезапускать (в том числе при деплое и падениях) без потери состояния. Липкое состояние в процессе ломает горизонтальное масштабирование и устойчивость.
- 12-factor трактует БД, кеш, брокер как «attached resources». Что это меняет?A)Их подключают по конфигу-URL и меняют без правки кода — как сменные ресурсыB)Запрещает использовать управляемые облачные базы данных и кеши в приложенииC)Требует, чтобы все они физически работали на той же машине, что и приложениеD)Означает, что менять адрес или экземпляр ресурса можно только пересборкой кода
показать ответ и разбор
+A)Их подключают по конфигу-URL и меняют без правки кода — как сменные ресурсы// разбор: Backing-сервисы (БД, кеш, очередь, SMTP) 12-factor рассматривает как подключаемые ресурсы, адресуемые через конфиг (обычно URL в переменной окружения). Локальный Postgres и managed-облачный — для кода одно и то же: сменить один на другой можно правкой конфига, без изменения кода. Это развязывает приложение и конкретные экземпляры ресурсов, упрощая переезды, замену и работу в разных средах.
дальше
Теорию прочитали. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.