Задача 13. Когда под увидит новый ConfigMap

ConfigMap обновили, но приложение работает по-старому. Разбираем, почему переменные окружения не обновляются никогда, тома обновляются с задержкой, а subPath не обновляется вовсе.
Опубликовано:

Задача

Приложение читает настройки из ConfigMap. Конфигурацию обновили:

BASH
kubectl edit configmap app-config
Нажмите, чтобы развернуть и увидеть больше

В манифесте пода конфигурация подключена двумя способами:

YAML
spec:
  containers:
    - name: app
      env:
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: log_level
      volumeMounts:
        - name: config
          mountPath: /etc/app
  volumes:
    - name: config
      configMap:
        name: app-config
Нажмите, чтобы развернуть и увидеть больше

Вопрос: что произойдёт с LOG_LEVEL и с файлами в /etc/app после обновления ConfigMap?

Что кажется очевидным

«Kubernetes обновит и то, и другое — может быть, с небольшой задержкой».

Верно только наполовину, и разница принципиальная.

Как это работает на самом деле

Три способа подключить ConfigMap ведут себя по-разному:

СпособОбновляется?Когда
Переменная окружения (env, envFrom)НикогдаТолько при пересоздании пода
Том (volumeMounts)✅ ДаС задержкой до ~1–2 минут
Том с subPathНикогдаТолько при пересоздании пода

Переменные окружения передаются процессу при его запуске — это свойство самого Linux, а не Kubernetes. Изменить окружение работающего процесса извне нельзя. Значение LOG_LEVEL останется прежним до пересоздания пода.

Тома работают иначе: kubelet периодически синхронизирует содержимое смонтированного ConfigMap. Обновление доходит с задержкой, складывающейся из периода синхронизации kubelet и времени жизни кэша. На практике — обычно до минуты-двух.

subPath — коварная ловушка. Он монтирует конкретный файл, а не каталог, и такой монтаж не обновляется никогда. Это регулярный источник недоумения: «у коллеги обновляется, у меня нет» — разница именно в subPath.

Даже когда файл обновился

Есть второй уровень проблемы: обновление файла не означает, что приложение перечитало конфигурацию. Большинство приложений читают конфиг один раз при старте. Чтобы изменения вступили в силу, приложение должно либо следить за файлом (inotify), либо перечитывать по сигналу (например, SIGHUP).

Атомарность

Полезная деталь реализации: Kubernetes монтирует ConfigMap через симлинки на скрытый каталог с версией. При обновлении создаётся новый каталог и симлинк атомарно переключается — приложение никогда не увидит наполовину обновлённый набор файлов.

Ответ

LOG_LEVEL не изменится никогда — переменные окружения фиксируются при старте процесса. Файлы в /etc/app обновятся в течение примерно минуты (если не использован subPath), но приложение продолжит работать по старой конфигурации, пока не перечитает файлы.

Что с этим делать

Способ 1: перезапуск при изменении (рекомендуемый)

Самый предсказуемый подход — считать конфигурацию частью версии приложения и перевыкатывать под при её изменении. Классический приём — хеш конфигурации в аннотациях пода:

YAML
spec:
  template:
    metadata:
      annotations:
        checksum/config: '{{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}'
Нажмите, чтобы развернуть и увидеть больше

Изменился ConfigMap → изменился хеш → изменился шаблон пода → Deployment сам запускает rolling update. Работает в Helm; в Kustomize аналогичный эффект даёт configMapGenerator с суффиксом хеша в имени.

Ручной вариант того же:

BASH
kubectl rollout restart deployment/api
Нажмите, чтобы развернуть и увидеть больше

Плюс подхода: изменение конфигурации проходит через ту же процедуру, что и выкатка кода, — с rolling update, readiness-проверками и возможностью отката.

Способ 2: горячая перезагрузка

Если перезапуск нежелателен (долгий прогрев, stateful-нагрузка), приложение должно уметь перечитывать конфиг:

Для сервисов, которые этого не умеют, существуют вспомогательные инструменты вроде reloader, которые перезапускают Deployment при изменении связанного ConfigMap/Secret.

Практические правила


Дальше: Задача 14. Куда на самом деле идёт запрос к Service.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша