← Back to notes

ConfigMap и
Secret


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

[source: kubernetes.io/docs/concepts/configuration/configmap/]

ConfigMap

ConfigMap хранит неконфиденциальные конфигурационные данные в виде пар ключ-значение. Размер — до 1 MiB.

Создание ConfigMap

Из литералов:

kubectl create configmap app-config \
  --from-literal=DB_HOST=postgres \
  --from-literal=DB_PORT=5432 \
  --from-literal=LOG_LEVEL=info

Из файла:

# Файл целиком как одно значение (ключ = имя файла)
kubectl create configmap nginx-config --from-file=nginx.conf

# С явным ключом
kubectl create configmap nginx-config --from-file=my-nginx=nginx.conf

# Из .env файла (каждая строка KEY=VALUE становится отдельным ключом)
kubectl create configmap app-config --from-env-file=.env

Через YAML-манифест (рекомендуется для GitOps):

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: production
data:
  DB_HOST: postgres
  DB_PORT: "5432"
  LOG_LEVEL: info
  app.properties: |
    server.port=8080
    server.context-path=/api
    feature.cache.enabled=true

Использование ConfigMap

Все ключи как переменные окружения (envFrom):

spec:
  containers:
    - name: app
      image: myapp:1.0
      envFrom:
        - configMapRef:
            name: app-config

Все ключи ConfigMap становятся переменными окружения контейнера.

Отдельные ключи (valueFrom):

spec:
  containers:
    - name: app
      image: myapp:1.0
      env:
        - name: DATABASE_HOST
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: DB_HOST
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: LOG_LEVEL

Как файлы через Volume (рекомендуется для конфигов с автообновлением):

spec:
  containers:
    - name: app
      image: myapp:1.0
      volumeMounts:
        - name: config-volume
          mountPath: /etc/config
          readOnly: true
  volumes:
    - name: config-volume
      configMap:
        name: app-config

Каждый ключ ConfigMap становится файлом в /etc/config/. При обновлении ConfigMap файлы в Volume обновляются автоматически (с задержкой до kubelet sync period — обычно ~1 минута). Переменные окружения (env/envFrom) не обновляются — требуется перезапуск Pod.

Secret

Secret хранит конфиденциальные данные: пароли, токены, ключи. По структуре аналогичен ConfigMap, но значения хранятся в base64. Размер — до 1 MiB.

[source: kubernetes.io/docs/concepts/configuration/secret/]

Создание Secret

Императивно:

kubectl create secret generic db-credentials \
  --from-literal=username=admin \
  --from-literal=password=s3cret123

Через YAML с data (значения в base64):

# Кодирование
echo -n 'admin' | base64        # YWRtaW4=
echo -n 's3cret123' | base64    # czNjcmV0MTIz
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  username: YWRtaW4=
  password: czNjcmV0MTIz

Через YAML с stringData (без ручного кодирования):

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
stringData:
  username: admin
  password: s3cret123

stringData автоматически кодируется в base64 при сохранении. Удобнее для манифестов, но не коммить такие файлы в git без шифрования (Sealed Secrets, SOPS).

Типы Secret

# TLS Secret
kubectl create secret tls my-tls \
  --cert=server.crt \
  --key=server.key

# Docker registry Secret
kubectl create secret docker-registry regcred \
  --docker-server=registry.example.com \
  --docker-username=user \
  --docker-password=pass

Использование Secret

Как переменные окружения:

spec:
  containers:
    - name: app
      image: myapp:1.0
      env:
        - name: DB_USERNAME
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: username
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: password

Как файлы через Volume (предпочтительно):

spec:
  containers:
    - name: app
      image: myapp:1.0
      volumeMounts:
        - name: secret-volume
          mountPath: /etc/secrets
          readOnly: true
  volumes:
    - name: secret-volume
      secret:
        secretName: db-credentials

Volume mount предпочтительнее env для Secret: файлы обновляются автоматически при ротации, не попадают в kubectl describe pod вывод так легко, не логируются средами выполнения.

Docker registry credentials (imagePullSecrets):

spec:
  imagePullSecrets:
    - name: regcred
  containers:
    - name: app
      image: registry.example.com/myapp:1.0

Безопасность Secret

Secret хранятся в etcd в base64 — это кодирование, не шифрование. Декодируется тривиально:

echo 'czNjcmV0MTIz' | base64 -d    # s3cret123

Encryption at rest

Для шифрования Secret в etcd настраивается EncryptionConfiguration на API Server:

[source: kubernetes.io/docs/tasks/administer-cluster/encrypt-data/]

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded-32-byte-key>
      - identity: {}

Рекомендации

  • Не коммить Secret-манифесты в git в открытом виде
  • Использовать Sealed Secrets (Bitnami) или SOPS для шифрования манифестов в репозитории
  • Использовать внешние менеджеры секретов: HashiCorp Vault, AWS Secrets Manager, Azure Key Vault — с CSI driver или оператором
  • Включить encryption at rest в etcd
  • Ограничить доступ к Secret через RBAC
  • Монтировать как Volume вместо env

Сравнение ConfigMap и Secret

Типичные ошибки

Секрет в ConfigMap. Пароль или токен в ConfigMap — ошибка. ConfigMap не имеет дополнительных защитных механизмов.

Коммит Secret манифеста в git. stringData в YAML читается как plain text. Стандартное решение — Sealed Secrets или внешний secret manager.

Обновление ConfigMap не приводит к обновлению env в Pod. После обновления ConfigMap Pod с envFrom продолжает видеть старые значения до перезапуска. Для автоматического перезапуска при изменении ConfigMap используй Reloader (stakater/Reloader) или пересоздавай Pod через kubectl rollout restart.

Забыть readOnly: true при монтировании Secret. Хорошая практика — монтировать Secret как read-only.

Secret слишком большой. Лимит 1 MiB. Большие артефакты (TLS chain, binary keys) — в отдельные Secret или внешнее хранилище.

Альтернативы

HashiCorp Vault с Vault Agent Injector или CSI Secrets Store Driver — динамические секреты, аудит доступа, автоматическая ротация. Стандарт для security-требовательных окружений.

AWS Secrets Manager / Azure Key Vault / GCP Secret Manager — облачные менеджеры секретов с интеграцией через CSI Secrets Store Driver или нативные операторы.

Sealed Secrets (Bitnami) — шифрует Secret в SealedSecret ресурс, который безопасно хранить в git. Расшифровывается только контроллером в кластере.

SOPS — шифрует YAML/JSON файлы (включая Secret манифесты) с использованием KMS, PGP или age. Хорошо интегрируется с GitOps.


07: Ingress

09: Volumes

ConfigMap и Secret | Aleksandr Suprun