Введение
Приложениям часто требуются данные, которые не следует размещать непосредственно в образе контейнера или в обычном манифесте, например, пароли, токены или учетные данные для доступа к базам данных. Kubernetes Secrets хранят такие конфиденциальные параметры конфигурации как отдельные объекты и позволяют подам использовать их при запуске.
В этой лабораторной работе вы создадите секрет, внимательно изучите его закодированные данные, подключите его к поду приложения, обновите секрет и пересоздадите под, чтобы приложение считало новые значения. Эта работа сфокусирована на базовом рабочем процессе работы с секретами. В последующих лабораторных работах будут рассмотрены более детальные способы передачи данных через переменные окружения и монтирование конфигурационных файлов.
Подготовка пространства имен для работы с секретами
На этом этапе вы подготовите чистое пространство имен (namespace) для практики работы с секретами.
Начните работу в директории /home/labex/project. В этой директории вы создадите манифест пода.
mkdir -p /home/labex/project
cd /home/labex/project
Убедитесь, что API-сервер Kubernetes доступен. Если виртуальная машина только что запустилась и узел еще не готов, подождите несколько секунд и повторите команду.
kubectl get nodes --request-timeout=5s
Ожидаемый вывод:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Дождитесь готовности пода сетевого плагина кластера перед созданием объектов приложения.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Ожидаемый вывод:
pod/calico-node-... condition met
Создайте пространство имен с именем ckad-prep-secrets:
kubectl create namespace ckad-prep-secrets
Установите это пространство имен в качестве текущего контекста:
kubectl config set-context --current --namespace=ckad-prep-secrets
Проверьте текущее пространство имен:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Ожидаемый вывод:
ckad-prep-secrets
Создание и проверка секрета
На этом этапе вы создадите секрет, в котором будут храниться настройки подключения к базе данных для небольшого приложения.
Команда kubectl create secret generic создает непрозрачный (opaque) секрет. generic означает, что Kubernetes не присваивает ключам какое-либо специальное встроенное значение. Каждый флаг --from-literal добавляет одну пару «ключ-значение» в секрет.
kubectl create secret generic db-credentials \
--from-literal=DB_USER=orders-app \
--from-literal=DB_PASSWORD=dev-password-123 \
--from-literal=DB_NAME=orders
Ожидаемый вывод:
secret/db-credentials created
Проверьте сводную информацию о секрете:
kubectl get secret db-credentials
Ожидаемый вывод:
NAME TYPE DATA AGE
db-credentials Opaque 3 ...
Просмотрите секрет в формате YAML. Kubernetes хранит значения в поле data в виде строк, закодированных в base64, поэтому не стоит ожидать, что вы увидите исходный пароль в этом выводе.
kubectl get secret db-credentials -o yaml
Ожидаемый вывод включает:
data:
DB_NAME: b3JkZXJz
DB_PASSWORD: ...
DB_USER: b3JkZXJzLWFwcA==
type: Opaque
Кодировка Base64 — это не шифрование. Любой, кто может прочитать объект Secret, может декодировать его значения. Декодируйте здесь только имя пользователя, чтобы увидеть, как работает представление данных, не выводя при этом пароль.
kubectl get secret db-credentials -o 'jsonpath={.data.DB_USER}' | base64 --decode; echo
Ожидаемый вывод:
orders-app
Настройка пода с использованием секрета
На этом этапе вы запустите под, который считывает секрет в виде переменных окружения.
Поле envFrom.secretRef импортирует все ключи из секрета в окружение контейнера. Это похоже на шаблон с ConfigMap из предыдущей лабораторной работы, но значения берутся из объекта Secret. Команда в этом поде выводит имя пользователя и имя базы данных, а затем просто подтверждает, что пароль был загружен. Сам пароль при этом не выводится.
Создайте файл secret-reader-pod.yaml:
cat > secret-reader-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: secret-reader
labels:
app: secret-reader
spec:
terminationGracePeriodSeconds: 0
containers:
- name: reader
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo user=${DB_USER}; echo database=${DB_NAME}; if [ -n "${DB_PASSWORD}" ]; then echo password-loaded; fi; sleep 3600'
envFrom:
- secretRef:
name: db-credentials
EOF
Примените манифест пода:
kubectl apply -f secret-reader-pod.yaml
Ожидаемый вывод:
pod/secret-reader created
Дождитесь готовности пода:
kubectl wait --for=condition=Ready pod/secret-reader --timeout=120s
Ожидаемый вывод:
pod/secret-reader condition met
Прочитайте логи пода. Приложение подтверждает, что значения из секрета были доступны, но значение пароля не отображается.
kubectl logs secret-reader -c reader
Ожидаемый вывод:
user=orders-app
database=orders
password-loaded
Обновление секрета и пересоздание пода
На этом этапе вы обновите секрет и пересоздадите под, чтобы контейнер получил новые значения.
Окружение контейнера фиксируется в момент его запуска. Если секрет используется в качестве переменных окружения, обновление объекта Secret не приведет к перезаписи окружения внутри уже запущенного контейнера. Запустите новый под, когда приложению необходимо считать обновленные значения секрета.
Обновите секрет с помощью нового пользователя приложения и пароля:
kubectl patch secret db-credentials --type merge --patch '{"stringData":{"DB_USER":"orders-worker","DB_PASSWORD":"rotated-password-456","DB_NAME":"orders"}}'
Ожидаемый вывод:
secret/db-credentials patched
Подтвердите обновление имени пользователя, декодировав только DB_USER:
kubectl get secret db-credentials -o 'jsonpath={.data.DB_USER}' | base64 --decode; echo
Ожидаемый вывод:
orders-worker
Удалите старый под:
kubectl delete pod secret-reader
Ожидаемый вывод включает:
pod "secret-reader" deleted
Пересоздайте под из того же манифеста и дождитесь его готовности:
kubectl apply -f secret-reader-pod.yaml
kubectl wait --for=condition=Ready pod/secret-reader --timeout=120s
Ожидаемый вывод:
pod/secret-reader created
pod/secret-reader condition met
Снова прочитайте логи. Новый под теперь видит обновленного пользователя из секрета и по-прежнему не выводит пароль в открытом виде.
kubectl logs secret-reader -c reader
Ожидаемый вывод:
user=orders-worker
database=orders
password-loaded
Резюме
Вы создали секрет Kubernetes, изучили его закодированные данные, декодировали неконфиденциальный ключ, чтобы понять принцип представления данных, подключили секрет к поду приложения и пересоздали под после обновления секрета. Вы также закрепили важную привычку при работе с конфиденциальными данными: проверять, что приложение получило пароль, не выводя само значение пароля в логи.


