Как обновить секрет без перезапуска pod?
Ключевая идея — можно обновить содержимое Secret в Kubernetes без перезапуска Pod, но это зависит от способа потребления секрета контейнером. Если секрет смонтирован в виде файла (volume), kubelet периодически обновляет файлы в контейнере; если секрет передан как переменная окружения (env), то обновить её без перезапуска нельзя — переменные окружения вычисляются при запуске процесса.
1) Поведение для секретов, смонтированных как volume
-
При изменении объекта Secret в API kubelet обнаруживает это и обновляет файлы в примонтированной директории в поде (асинхронно). Это реализовано через атомическую замену файлов/ссылок, поэтому новое содержимое появляется в файловой системе контейнера.
-
Приложение должно считывать файл заново или уметь обрабатывать изменение (например, переоткрывать файл, смотреть на изменение содержимого). Если приложение читает файл только при старте — оно не увидит новый секрет.
-
subPath ломает автоперезапись: если вы монтируете конкретный файл через subPath, kubelet копирует файл один раз и дальше не обновляет его. Поэтому не используйте subPath, если хотите live-обновления.
2) Поведение для переменных окружения
- Если секрет используется в env, его значение подставляется при старте контейнера и не меняется во время работы. Чтобы обновлённые значения в env появились — Pod нужно перезапустить (или заменить контейнер).
3) Как фактически обновить Secret (пример)
Обновить объект Secret в кластере можно командами:
# обновление/создание через apply
kubectl create secret generic my-secret \\
\--from-literal=password=newpass \\
\--dry-run=client -o yaml | kubectl apply -f -
# либо редактирование
kubectl edit secret my-secret
После изменения kubelet в скором времени (обычно в пределах минуты) обновит файлы в смонтированных volume внутри Pod'а.
4) Как приложение подхватывает изменения без перезапуска
-
Лучше всего — реализовать в приложении динамическую перезагрузку конфигурации при изменении файла (например, периодически перечитывать файл, реагировать на сигнал SIGHUP, или использовать файловые уведомления).
-
Учтите: kubelet делает атомическую замену файла (создаёт новую версию и меняет ссылку), поэтому простое inotify на файл может не сработать — лучше отслеживать событие в каталоге или реагировать на IN_MOVE/IN_CREATE. Эмпирически надёжнее реагировать на изменение родительской директории или периодически читать файл.
-
Альтернативный и удобный паттерн — sidecar-контейнер, который следит за файлом и при изменении шлёт сигнал в главный процесс (например, kill -HUP 1) или обновляет конфиг приложения.
5) Подводные камни
-
Если вы использовали subPath — обновлений не будет.
-
Если приложение кэширует значение в памяти и никогда не перечитывает файл — изменение не подействует.
-
Изменение Secret не меняет переменные окружения текущих контейнеров.
-
В некоторых CNI/платформах поведение обновления может отличаться по задержке, но в большинстве реализаций kubelet периодически синхронизирует.
6) Более надёжные/функциональные подходы (без рестарта Pod)
-
Secrets as files + приложение/sidecar, который умеет reload — стандартный и простой путь.
-
CSI Secrets Store (provider) — драйвер монтирует секреты из внешних хранилищ и поддерживает опции ротации/refresh; часто умеет обновлять контент по расписанию и уведомлять приложение.
-
Проекционные/short-lived токены (TokenRequest) для SA — kubelet автоматически обновляет токены сервис-аккаунта в поде (иногда используется для аутентификации без рестарта).
-
Если вы всё же хотите, чтобы изменение секрета автоматически перезапустило Deployment (чтобы env-переменные обновились), существуют паттерны/операторы, которые «подталкивают» rolling update при изменении Secret (это уже рестарт).
Пример простого манифеста Pod с монтированием секрета
volumes:
\- name: my-secret-vol
secret:
secretName: my-secret
containers:
\- name: app
image: myimage
volumeMounts:
\- name: my-secret-vol
mountPath: /etc/my-secret # приложение читает /etc/my-secret/password
Обновляете Secret через kubectl apply, kubelet обновит файлы; приложение должно уметь обнаружить и применить новые значения (рефреш/перечитывание или реакция на сигнал).