ConfigMap, Secret и обновление окружения процесса
API «Площадки» уже содержит параметры GREETING, APP_VERSION и DEMO_ADMIN_TOKEN. До этого сервер брал значения по умолчанию. Теперь зададим их через ConfigMap и Secret, не меняя исходники и образ. Основной результат урока — отделить хранение настройки от момента её чтения программой. Существующий объект конфигурации ещё не означает, что работающий процесс уже получил новое значение.
Полные файлы находятся в каталоге примера: 05-config.yaml создаёт данные, 06-api-health.yaml связывает их с API Deployment. Второй файл также содержит будущие probes; их поведение подробно разберём в следующем уроке. Все значения учебные, команды не выполнялись, реальных секретов в наборе нет.
Общая конфигурация образа
ConfigMap хранит обычные настройки. Для нашего API это приветствие, показываемое в интерфейсе, номер версии для демонстрации и длительность начальной задержки. В 05-config.yaml соответствующая декларация выглядит так:
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
namespace: ploshchadka
data:
GREETING: Площадка — локальная лаборатория
APP_VERSION: "1"
BOOT_DELAY_MS: "3000"
Значения data являются строками. Числа окружения тоже приходят в Node как строки, поэтому код преобразует BOOT_DELAY_MS через Number. Для учебного константного значения этого достаточно. В реальном API параметры проверяют при запуске: отрицательная задержка, неизвестная схема URL или пустой обязательный параметр должны давать понятную ошибку конфигурации.
Перенос настроек не делает образ универсальным для любой версии данных. Код должен знать имена и смысл параметров. Если новый образ ожидает CATALOG_TITLE, а ConfigMap содержит только GREETING, совместимость нарушится. Поэтому версия конфигурационного контракта входит в описание выпуска вместе с версией приложения.
Не путайте APP_VERSION с фактическим содержимым образа. В нашей демонстрации значение помогает увидеть изменённое окружение. Если передать APP_VERSION=2 старому образу, его программа не станет новым кодом. Для точного расследования нужны идентификатор образа и декларация Deployment, а не только строка, которую приложение показывает пользователю.
Secret и учебный административный маршрут
Вторая часть файла создаёт Secret:
apiVersion: v1
kind: Secret
metadata:
name: api-demo-secret
namespace: ploshchadka
type: Opaque
stringData:
DEMO_ADMIN_TOKEN: classroom-only-not-a-real-credential
Это заведомо несекретная учебная строка. Она позволяет увидеть отличие обычной конфигурации от значения, к которому доступ обычно ограничивают отдельно. stringData принимает читаемый текст для передачи API. Внутреннее представление data использует base64, но base64 не является шифрованием. Доступность Secret определяется правами и конфигурацией хранения.
Маршрут GET /api/admin/config сравнивает Authorization с переданным токеном и при успехе отдаёт приветствие и версию. Он не раскрывает сам токен. Это демонстрационный механизм, а не полноценная аутентификация людей: здесь нет пользователей, сроков действия, обновления токенов и журналов входа. Его задача — показать, зачем части приложения нужен конфиденциальный параметр.
Официальная документация Secrets объясняет модель хранения и доступа. Из неё следует важное практическое правило: не считать Secret безопасным только из-за типа объекта. В производственной системе нужны ограниченные права, управление выдачей значения и подходящая защита управляющего хранилища. Эти механизмы нельзя заменить переименованием файла из config в secret.
Как значения попадают в контейнер
Полный API Deployment из 06-api-health.yaml использует:
envFrom:
- configMapRef:
name: api-config
- secretRef:
name: api-demo-secret
Две ссылки находятся внутри описания контейнера API. При создании процесса Kubernetes формирует окружение из указанных объектов. Сам Node-сервер читает параметры при запуске и сохраняет их в переменных. Поэтому изменения ConfigMap позднее не переписывают переменную greeting в уже работающей программе.
Будущий порядок действий имеет значение:
kubectl --context kind-ploshchadka apply -f manifests/05-config.yaml
kubectl --context kind-ploshchadka apply -f manifests/06-api-health.yaml
kubectl --context kind-ploshchadka -n ploshchadka rollout status deployment/api
Сначала создаются данные, затем Pod, который на них ссылается. Если обязательный объект отсутствует, контейнер может не получить нужное окружение и не начнёт нормальную работу. Это ошибка подготовки Pod, а не HTTP-маршрута. Посмотрите состояние и Events вместо бесконечного нажатия кнопки frontend.
Ожидаемый ответ каталога теперь содержит «Площадка — локальная лаборатория». Исходный образ при этом остаётся ploshchadka-api:1. Такое изменение показывает полезную границу: одинаковый артефакт кода можно настраивать для различных окружений, если сохраняется совместимый контракт параметров.
Смена настройки и воспроизводимость выпуска
При объединении нескольких источников окружения полезно избегать одинаковых ключей. Если ConfigMap и Secret оба определяют GREETING, результат зависит от порядка источников и явных переменных контейнера. Читателю трудно понять, какой объект действительно управляет ответом. В нашей схеме Secret содержит только токен, ConfigMap — обычные параметры, поэтому смысл каждого имени однозначен.
В большом проекте явные ссылки отдельных переменных часто удобнее envFrom: видно, какой ключ из какого объекта нужен контейнеру. Здесь небольшой набор целиком относится к API, поэтому envFrom сохраняет читаемость. Выбор формы не меняет основного правила: приложение получает определённый снимок окружения при создании процесса.
Предположим, вы изменили GREETING в ConfigMap и применили только 05-config.yaml. Старые API-процессы продолжают использовать прежнее окружение. Чтобы получить новые значения, читатель может выполнить rollout restart deployment/api с явным context и namespace. Команда изменит шаблон метаданными перезапуска, и Deployment создаст новые Pod.
При rolling update некоторое время могут существовать экземпляры с разными приветствиями. Для нашей учебной надписи это допустимо. Для важных бизнес-параметров такое смешанное состояние требует отдельного решения: совместимость двух конфигураций, версионированный ConfigMap или согласованный переход. Инфраструктура не угадывает, можно ли одновременно применять старые и новые правила расчёта.
Существуют и настройки через смонтированные файлы. Их обновление имеет другие свойства, а приложение должно уметь перечитать файл. Нельзя обещать горячее обновление только потому, что объекты Kubernetes способны менять проекцию. В нашей серии используется окружение процесса; механизм чтения однозначен и не требует скрытого watcher в Node.
Откат Deployment не возвращает автоматически прежнее содержимое ConfigMap с тем же именем. Поэтому при выпуске нужно сохранять набор совместимых данных или пользоваться версионированными именами. В уроке про rollback это ограничение станет особенно важным: старая программа может получить новую настройку и продолжить ошибаться после успешной замены образа.
На этом этапе код, конфигурация и экземпляр разделены. Новый процесс получает новое окружение; старый не меняется самопроизвольно. Следующий урок связывает готовность процесса, probes и завершение по SIGTERM, чтобы Service не направлял обычный трафик к экземпляру во время инициализации.