Переменные окружения в Pod
Поле env в spec контейнера: литералы, valueFrom, подстановка $(VAR) и почему env не обновляется на лету.
Зачем env-переменные
12-factor app говорит простое: всё, что зависит от окружения, передавай через environment. URL базы, режим запуска, путь к ключу, секрет API. Образ остаётся одним и тем же, поведение меняется через env.
В Kubernetes за это отвечает поле spec.containers[].env у Pod. Дальше
любой процесс внутри контейнера видит переменную через $DB_HOST в
shell, os.environ["DB_HOST"] в python, os.Getenv("DB_HOST") в go.
Минимальная форма
spec:
containers:
- name: app
image: busybox:1.36
env:
- name: DB_HOST
value: postgres-internal
- name: LOG_LEVEL
value: debug
env это массив объектов. У каждого объекта обязательное name,
дальше либо value (литерал-строка), либо valueFrom (ссылка на
ConfigMap, Secret, downward API).
Имя env с дефисом apiserver не примет: MY-VAR отвалится на apply.
Разрешён только шаблон [A-Za-z_][A-Za-z0-9_]*.
value всегда строка. Если нужно число или булеан, значение пишут в
кавычках:
- name: REPLICAS
value: "3"
- name: DEBUG
value: "true"
Без кавычек YAML распарсит 3 как int, и kubectl ругнётся:
v1.EnvVar.Value: ReadString: expects " or n.
valueFrom: четыре источника
value это просто строка. valueFrom достаёт значение из другого
объекта кластера. Четыре варианта:
env:
# из ConfigMap
- name: APP_MODE
valueFrom:
configMapKeyRef:
name: app-config
key: APP_MODE
# из Secret
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: password
# из downward API: имя Pod, namespace, labels
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
# из downward API: requests/limits контейнера
- name: CPU_LIMIT
valueFrom:
resourceFieldRef:
containerName: app
resource: limits.cpu
Самая простая форма - литерал через value. ConfigMap и Secret как
источники разбираются в следующих уроках трека.
Когда env читается
Один раз на старте контейнера. Если поменять Pod через kubectl edit,
изменения сами не подхватятся: kubectl скажет Pod updates may not change fields other than .... У нативного Pod env-блок вообще
иммутабельный после создания. Нужно удалить и пересоздать.
У Deployment пересоздание делается автоматически: меняется spec, ReplicaSet поднимает новые Pod со свежим env, старые удаляет.
Для valueFrom из ConfigMap правило то же. Если ConfigMap поменяли, env
в работающем контейнере остаётся старым. Нужен rollout. Для динамики
используют volume mount (там kubelet синхронит файлы периодически).
Подстановка переменных в env
Можно ссылаться на переменные, уже объявленные выше в том же массиве:
env:
- name: HOST
value: postgres-internal
- name: PORT
value: "5432"
- name: DB_URL
value: "postgres://$(HOST):$(PORT)/app"
Синтаксис $(VAR), не ${VAR}. Работает только для переменных, уже
объявленных до текущей. Если перепутать порядок, $(HOST) останется
литералом.
env, порядок элементов в массиве:
1 HOST = postgres-internal
2 PORT = 5432
3 DB_URL = $(HOST):$(PORT) раскрыт
4 BAD = $(LATER) литерал
5 LATER = x
То же работает в command и args:
command: ["sh", "-c"]
args: ["echo DB=$(DB_URL); sleep 3600"]
Дополнительно shell умеет раскрывать $VAR сам, поэтому sh -c "echo $DB_HOST" тоже работает: тут уже не kubelet подставляет, а shell
читает env-переменную из своего окружения.
Связанные команды
# Показать env конкретного контейнера в spec
kubectl get pod app -o jsonpath='{.spec.containers[0].env}' | jq
# Выполнить env внутри Pod и увидеть реальные значения
kubectl exec app -- env | sort
# Увидеть, что контейнер вывел при старте
kubectl logs app
# Разобрать схему полей
kubectl explain pod.spec.containers.env
kubectl explain pod.spec.containers.env.valueFrom --recursive
Что часто ломается
- Число без кавычек:
value: 3→expects " or n. Значения кавычат. - Env поменяли, Pod не подхватил. Env не реактивны, нужно пересоздать Pod.
- Ссылка на
$(VAR), а VAR объявлена ниже в списке. Подстановка не сработает.
Домашка
Теорию закрепляет задание на своём кластере: 3 шага с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.
./run.sh start k8s-env-vars # развернуть стартовое состояние
./run.sh verify k8s-env-vars # проверить текущий шаг
Коротко
- Env задаются в
spec.containers[].env, каждый элемент этоnameплюсvalueилиvalueFrom. valueвсегда строка, числа и булеаны пишут в кавычках.valueFromтянет значение из ConfigMap, Secret или downward API.- Env читаются один раз на старте контейнера, обновление требует пересоздания Pod.
- Подстановка
$(VAR)работает только для переменных, объявленных выше по списку.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс