Введение

В программном обеспечении не следует встраивать такие настройки, как URL базы данных или пароли, непосредственно в код приложения. Это усложняет внесение изменений и повышает риски безопасности.

Kubernetes решает эту проблему с помощью двух объектов:

  1. ConfigMap: представьте его как общедоступную доску объявлений. Вы размещаете здесь информацию, например «цвет фона — синий» или «адрес базы данных — 10.0.0.1». Любой сотрудник офиса (Pod) может её прочитать.
  2. Secret: используется для конфиденциальных значений, таких как пароли или токены.

Разделение кода приложения и конфигурации времени выполнения — это важный принцип проектирования платформ, а не просто возможность Kubernetes.

В этой лабораторной работе вы:

  • разместите заметку на доске объявлений (ConfigMap);
  • положите пароль в сейф (Secret);
  • научите Pod читать оба значения.

Создание ConfigMap

Создадим файл конфигурации для веб-сервера. Вместо того чтобы встраивать его в образ, мы сохраним его в ConfigMap.

Этот подход является частью более общего принципа проектирования контейнеров: создайте один повторно используемый образ, а конфигурацию для конкретной среды передавайте во время выполнения. Благодаря этому образ становится более переносимым: в средах разработки, тестирования и эксплуатации можно использовать один и тот же контейнер с разными настройками.

Сначала создайте простой файл конфигурации Nginx с именем nginx.conf:

echo 'events {} http { server { listen 80; location / { return 200 "Hello from ConfigMap!"; } } }' > nginx.conf

Теперь создайте из этого файла ConfigMap с именем nginx-config. Фактически вы размещаете файл на доске объявлений кластера Kubernetes.

kubectl create configmap nginx-config --from-file=nginx.conf

Убедитесь, что объект создан:

kubectl describe configmap nginx-config

В разделе «Data» должно отображаться содержимое файла nginx.conf.

Создание Secret

Теперь сохраним конфиденциальное значение. Secret работает примерно так же, как ConfigMap, но Kubernetes обрабатывает его более осторожно: данные маскируются при хранении.

Важно понимать ограничение этого механизма: Secret безопаснее, чем хранение паролей непосредственно в манифестах или образах, однако кодировка base64 не является настоящим шифрованием. В рабочей среде работу с Secret часто дополняют шифрованием данных в состоянии покоя, более строгими правилами RBAC и внешними системами управления секретами.

Создайте Secret с именем app-secret и сохраните в нём учебный пароль:

kubectl create secret generic app-secret --from-literal=password=SuperSecretPass123

Убедитесь, что объект создан:

kubectl get secret app-secret

Если просмотреть подробности, пароль не будет отображаться напрямую. Он будет скрыт и закодирован.

kubectl get secret app-secret -o yaml

Обратите внимание: поле password содержит набор непонятных символов. Это кодировка base64, которая помогает предотвратить случайный просмотр пароля посторонними и его случайное отображение в журналах.

Подключение ConfigMap как файла

Теперь научим Pod читать данные с доски объявлений.

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

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

Создайте файл с именем pod-config.yaml:

nano pod-config.yaml

Вставьте следующий текст. Этот Pod подключает ConfigMap nginx-config по пути /etc/nginx/nginx.conf.

apiVersion: v1
kind: Pod
metadata:
  name: config-pod
spec:
  containers:
    - name: nginx
      image: nginx:alpine
      volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
  volumes:
    - name: config-volume
      configMap:
        name: nginx-config

Сохраните файл и выйдите из редактора (Ctrl+X, Y, Enter).

Примените конфигурацию:

kubectl apply -f pod-config.yaml

Подождите несколько секунд, пока Pod запустится. Затем загляните внутрь контейнера и проверьте, появился ли файл:

kubectl exec config-pod -- cat /etc/nginx/nginx.conf

Вы должны увидеть созданную вами конфигурацию. Это означает, что Pod «прочитал доску объявлений» и использовал этот файл.

Передача Secret в переменную окружения

Теперь перейдём к Secret. Один из распространённых способов передавать пароли — использовать переменные окружения.

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

Создайте файл с именем pod-secret.yaml:

nano pod-secret.yaml

Вставьте следующий текст. Этот Pod получает значение password из app-secret и записывает его в переменную окружения с именем APP_PASSWORD.

apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
    - name: busybox
      image: busybox
      command: ["sleep", "3600"]
      env:
        - name: APP_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: password

Сохраните файл и выйдите из редактора (Ctrl+X, Y, Enter).

Примените конфигурацию:

kubectl apply -f pod-secret.yaml

После запуска Pod проверьте переменные окружения внутри контейнера:

kubectl exec secret-pod -- env | grep APP_PASSWORD

Вы должны увидеть APP_PASSWORD=SuperSecretPass123.

В этом и заключается основной принцип: определение Pod не содержит сам пароль. Пароль хранится в «сейфе» (Secret), а Pod получает только ключ, с помощью которого обращается к нему во время выполнения.

Итоги

В этой лабораторной работе вы попрактиковались в отделении кода от конфигурации.

Вы успешно:

  1. использовали ConfigMap (доску объявлений), чтобы передать файл конфигурации серверу;
  2. использовали Secret (сейф), чтобы передать приложению скрытый пароль.

Теперь вы можете обновлять конфигурацию или менять пароли, не пересобирая образы Docker!