Kubernetes
Теория: Конфигурация приложений
При работе с приложениями в Kubernetes возникает важная задача: как правильно передавать конфигурацию? Хардкодить значения в код неправильно, пересобирать образы для каждой среды (development, staging, production) неудобно. ConfigMap и Secret решают эту задачу, позволяя отделить конфигурацию от кода.
Проблема конфигурации
Представьте веб-приложение, которому нужны параметры подключения к базе данных, URL внешних API, настройки кеширования и feature flags. Эти параметры различаются между окружениями: в development используется локальная база данных, в production — отказоустойчивый кластер.
Традиционный подход — создавать разные Docker-образы для каждой среды. Но это приводит к проблемам: нельзя быть уверенным, что код в production идентичен протестированному в staging; изменение одного параметра требует полной пересборки образа; секретные данные попадают в слои образа и могут утечь.
Kubernetes предлагает лучшее решение: хранить конфигурацию отдельно от образа и монтировать её в контейнеры во время запуска. ConfigMap для обычных настроек, Secret для чувствительных данных.
Что такое ConfigMap
ConfigMap — это объект Kubernetes, который хранит конфигурационные данные в виде пар ключ-значение. Вы создаёте ConfigMap с нужными параметрами и подключаете его к Pod через переменные окружения или файлы.
Создадим простой ConfigMap с настройками приложения:
ConfigMap содержит четыре параметра. Все значения хранятся как строки, даже если это числа или булевы значения. Приложение должно преобразовывать их в нужный тип при чтении.
Создайте ConfigMap несколькими способами:
Посмотрите на созданный ConfigMap:
Использование ConfigMap в Pod
Существует два основных способа использования ConfigMap в Pod: как переменные окружения или как файлы в томе.
Переменные окружения (отдельные ключи)
Самый простой способ — монтировать значения из ConfigMap как переменные окружения:
Здесь переменная DATABASE_HOST получает значение из ключа DATABASE_HOST в ConfigMap app-config.
Переменные окружения (все ключи сразу)
Если нужно импортировать все ключи сразу, используйте envFrom:
Все ключи из ConfigMap станут переменными окружения.
Важные нюансы envFrom:
- Ключи импортируются как есть:
database_hostстанет переменнойdatabase_host, неDATABASE_HOST - Ключи с недопустимыми символами (например, дефисами) будут пропущены — дефис недопустим в именах переменных окружения
- Возможны конфликты с системными переменными окружения
Файлы в томе
Для сложной конфигурации удобнее монтировать ConfigMap как файлы. Каждый ключ становится файлом, значение — содержимым файла:
В контейнере появится директория /etc/config с файлами: DATABASE_HOST, DATABASE_PORT, CACHE_ENABLED, LOG_LEVEL. Каждый файл содержит соответствующее значение.
Можно выбрать конкретные ключи и задать имена файлов:
Теперь в директории /etc/config будут файлы db-host.txt и db-port.txt.
ConfigMap для конфигурационных файлов
ConfigMap отлично подходит для хранения полных конфигурационных файлов. Например, конфигурация Nginx:
Символ | позволяет хранить многострочный текст. Смонтируйте этот ConfigMap в Pod с Nginx:
Nginx прочитает конфигурацию из /etc/nginx/conf.d/default.conf при запуске.
Что такое Secret
Secret предназначен для хранения чувствительных данных: паролей, ключей API, сертификатов.
Важно понимать: Secret — это механизм доставки чувствительных данных в Pod, а не система безопасного хранения. По умолчанию значения хранятся в etcd в кодировке base64 — это не шифрование. Любой с доступом к API-серверу может их прочитать.
Чем Secret отличается от ConfigMap:
- Значения кодируются в base64 (но это не защита!)
- Kubernetes может шифровать Secret в etcd (требует отдельной настройки)
- Secret не выводится в
kubectl describe pod - Secret монтируется в tmpfs (память), не пишется на диск ноды
- Можно ограничить доступ через RBAC (система прав доступа в Kubernetes, рассмотрим в отдельном уроке)
Создадим Secret с параметрами подключения к базе данных. Используйте stringData — не нужно вручную кодировать в base64:
Если видите чужой манифест с data вместо stringData — там значения уже в base64:
Кодирование и декодирование:
Создавайте Secret из командной строки:
Посмотрите на Secret:
Использование Secret в Pod
Secret используется так же, как ConfigMap: через переменные окружения или файлы.
Переменные окружения:
Приложение получит переменные DATABASE_USERNAME и DATABASE_PASSWORD с расшифрованными значениями.
Файлы в томе:
В директории /etc/secrets появятся файлы username и password с расшифрованными значениями. Используйте readOnly: true для дополнительной безопасности.
Основные типы Secret
Kubernetes поддерживает несколько типов Secret для разных сценариев. Вот основные:
-
Opaque — базовый тип для произвольных данных. Используется по умолчанию.
-
kubernetes.io/tls — для хранения TLS-сертификатов и ключей. Требует ключи
tls.crtиtls.key. -
kubernetes.io/dockerconfigjson — для аутентификации в приватных Docker-реестрах:
Используйте этот Secret в Pod для загрузки приватных образов:
-
kubernetes.io/basic-auth — для хранения имени пользователя и пароля.
Полный список типов — в документации Kubernetes.
Обновление конфигурации
Когда вы обновляете ConfigMap или Secret, возникает вопрос: как обновить работающие Pod? Kubernetes не перезапускает Pod автоматически при изменении ConfigMap/Secret.
Если конфигурация смонтирована как том, изменения появятся в контейнере через некоторое время (обычно 1-2 минуты). Но приложение должно само отслеживать изменения файлов и перечитывать конфигурацию. Большинство приложений этого не делают.
Если конфигурация передана через переменные окружения, изменения не применятся до перезапуска Pod. Переменные окружения устанавливаются при создании контейнера и не меняются во время его работы.
Чтобы принудительно обновить Pod, можно инициировать rolling update у Deployment, даже если образ не менялся. Для этого достаточно изменить любую часть шаблона Pod. Kubernetes воспринимает это как новую версию приложения и пересоздаёт Pod.
Один из простых способов — изменить аннотацию:
Что происходит после этой команды:
- API Server принимает обновлённый манифест Deployment. Шаблон Pod внутри Deployment теперь отличается от предыдущего.
- Deployment Controller замечает изменение и создаёт новый ReplicaSet.
- Scheduler размещает новые Pod, kubelet запускает контейнеры уже с обновлённой конфигурацией.
- После успешного старта новых Pod старые постепенно останавливаются.
Снаружи это выглядит как «перезапуск», но внутри — полноценное безопасное rolling-обновление без простоя сервиса.


