12 factor app: конфиг



Где хранить конфиги? На каком этапе передать их приложению?



Эти вопросы обсуждаются в третьем пункте 12 factor app, который звучит как



Store config in the environment



Разберём, что это значит:)



Конфигурация — это всё, чем отличаются запущенные приложения на разных средах. Например,

Адреса, логины, пароли, токены внешних сервисов

Специфичные значения для конкретного сервиса: имя хоста, порт

Управляющие параметры: имя профайла, флажки и прочие свойства



Не являются конфигом:



Классы спринга с аннотацией @Configuration. Это описание компонентов и связей, часть исходного кода



Описания и состав профайлов. В спринге это аннотация @Profile. Причина та же: профайлы описаны в кодовой базе, которая не меняется. Но вот параметр, который задаёт, какой именно профайл нужен — это конфиг



Не конфиг:

@Configuration

@Profile(”dev”)

public class DBConfiguration {…}



А вот это конфиг:

-Dspring.profiles.active=dev



Задача разработчика простая: отделить конфигурацию от основного кода. Тогда приложение легко запустить и настроить на работу в разных средах.



Где хранить конфиги?



Оригинальный документ категоричен: конфиг должен передаваться через environment переменные, а конфиг-файлы не должны существовать. Потому что:



🔸 Рано или поздно сервис с продакшн конфигами попадёт в лапки разработчиков, и они сделают delete table users

🔸 Файлы с конфигами расползаются по всей системе, это небезопасно и сложно в управлении

🔸 Environment переменные не зависят от ОС, фреймворка и языка разработки



Мотивация понятна, но на практике всё работает не так:) Конфиги группируются в файлы, а в гите часто хранится дефолтный файлик для разработки.



Конфиги могут лежать в другом сервисе, например, в Kubernetes, Zookeeper или даже в HashiCorp Vault. Последний поддерживает версионирование и следит, кто и когда запрашивал данные.



Для ежедневной разработки есть следующие best practices:



В параметрах конфига нет префикса среды выполнения, а в коде — логики по их разделению:

 @Value("dev.datasource")

✔️ @Value("datasource")



В коде нет констант вроде "8080", "admin", имён хостов, логинов и паролей



Кажется, что это само собой разумеется, но нет:) В 2020 году утекли личные данные 243 миллионов бразильцев, потому что пароль БД был записан константой в исходном коде сервиса минздрава. А согласно этому исследованию более 100к GitHub репозиториев содержат токены и криптографические ключи прямо в исходном коде. Будем надеяться, что это всё pet проекты, которые нигде не используются🤞