Олег Марков
Работа с secrets в Kubernetes
Введение
Практически в любом приложении приходит момент, когда возникают чувствительные данные — пароли, ключи API, токены аутентификации. Основная задача — хранить и использовать их так, чтобы не терять контроль над безопасностью. В Kubernetes для этого предусмотрен особый объект — Secret.
Secrets в Kubernetes позволяют обрабатывать конфиденциальную информацию в кластере, помогая обеспечить изоляцию и ограничить видимость данных. Давайте детально разберемся, как создавать, использовать и защищать secrets, чего стоит избегать и на что обратить внимание при их эксплуатации.
Что такое Secret в Kubernetes
Secret — это объект Kubernetes, предназначенный для хранения небольшой, но чувствительной информации, такой как пароли, токены OAuth, SSH-ключи и другие секретные данные. В отличие от ConfigMap, секреты автоматически кодируются в формате Base64 и требуют более строгого контроля доступа.
Для чего используются Secrets
- Хранение паролей и учетных данных для БД и сторонних сервисов.
- Предоставление токенов API приложениям.
- Управление приватными ключами и сертификатами.
- Использование в сценариях CI/CD для обеспечения безопасности пайплайнов.
Как работает Secret
Secret существует как отдельный API-объект внутри кластера Kubernetes. Он может быть:
- Создан вручную с помощью YAML-манифеста.
- Сгенерирован через командную строку kubectl.
- Создан программно через API Kubernetes.
Secrets можно предоставлять в контейнеры:
- Как файлы в файловой системе (через volume).
- Как переменные окружения (env).
Давайте теперь разберем весь рабочий процесс — от создания до безопасного использования.
Типы Secrets в Kubernetes
В Kubernetes существует несколько типов secrets:
- Opaque — самый распространённый, используется по умолчанию.
- docker-registry — хранение учетных данных для доступа к приватным реестрам изображений Docker.
- tls — хранение TLS-ключей и сертификатов.
- service-account-token — автоматические секреты, связанные с аккаунтами сервисов.
Вы чаще всего будете использовать тип Opaque, но давайте коротко разберёмся, когда использовать каждый тип.
Opaque
Это универсальный тип, куда можно сложить любые пары ключ:значение.
docker-registry
Используется для хранения логинов и паролей к приватным репозиториям Docker.
tls
Для хранения приватных ключей и публичных сертификатов TLS. Это удобно для автоматизации SSL, ingress, etc.
service-account-token
Kubernetes автоматически создает такие секреты и прикрепляет их к подам, позволяя им аутентифицироваться как сервис-аккаунт внутри кластера.
Создание Secret в Kubernetes
Теперь давайте рассмотрим, как можно создавать secrets на практике, используя различные подходы.
Создание Secret с помощью kubectl
Иногда проще всего создать secret прямо из командной строки. Вот пример, как это сделать для пароля к базе данных:
kubectl create secret generic db-password \
--from-literal=password=SuperSecretPass123
# Здесь мы создали secret с именем db-password и одной парой ключ:значение.
Если нужно добавить сразу несколько значений — используйте несколько опций:
kubectl create secret generic app-secret \
--from-literal=username=myappuser \
--from-literal=password=AnotherSecretPass456
Либо создать из файла: ```bash kubectl create secret generic ssh-key-secret \ --from-file=ssh-privatekey=/home/user/.ssh/id_rsa \ --from-file=ssh-publickey=/home/user/.ssh/id_rsa.pub
Ключ --from-file добавляет содержимое файла в secret.
### Создание Secret с помощью YAML-манифеста
Давайте теперь создадим secret через YAML.
yaml
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: bXl1c2Vy # "myuser" в base64
password: U3dwYXNzMTIz # "Swpass123" в base64
Поясню для новичков: значения в секции data всегда должны быть в кодировке Base64. Кодировать можно так:
bash
echo -n 'myuser' | base64
#### Как применить манифест
bash
kubectl apply -f secret.yaml
### Создание TLS Secret
Для хранения SSL-сертификата удобно использовать специальный тип tls:
bash
kubectl create secret tls my-tls-secret \
--cert=path/to/tls.crt \
--key=path/to/tls.key
Kubernetes автоматически сконвертирует содержимое файлов в base64 и добавит в Secret. Такой секрет крайне удобен для настройки ingress-контроллеров.
## Как использовать Secret в контейнерах
Вы можете использовать Secret двумя основными способами: передавая данные как переменные среды или монтируя их в контейнер как файлы.
### Монтирование Secret в качестве тома (volume)
Самый безопасный способ — примонтировать секрет в контейнер как read-only volume. Вот пример:
yaml
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: myapp
image: busybox
command: ["sleep", "3600"]
volumeMounts:
- name: secret-volume mountPath: "/etc/secret-data" readOnly: true volumes:
- name: secret-volume secret: secretName: db-credentials ``` Внутри контейнера файлы username и password появятся в /etc/secret-data/. Это безопаснее, потому что данные не попадают в переменные окружения и не отображаются в командных строках процессов.
Использование Secrets как переменных окружения
Если монтировать в виде файлов неудобно, вы можете подставить значения в env:
apiVersion: v1
kind: Pod
metadata:
name: env-pod
spec:
containers:
- name: myapp
image: busybox
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
command: ["printenv"]
Теперь при запуске контейнера переменные окружения DB_USERNAME и DB_PASSWORD будут содержать значения из секрета.
Управление минимальными разрешениями
Важно понимать, что доступ к секретам ограничен Namespace и RBAC. Каждый секрет принадлежит определенному namespace, и только подам (или сервисам), имеющим доступ к этому корневому пространству имен, можно работать с его содержимым.
Пример ограничения доступа через RBAC
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: my-namespace
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-secrets
namespace: my-namespace
subjects:
- kind: User
name: developer
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: secret-reader
apiGroup: rbac.authorization.k8s.io
С помощью таких политик можно ограничить, кто может читать или изменять секреты.
Безопасность работы с Secrets
Работа с секретами требует внимания — их уязвимость может привести к серьезным инцидентам.
Проблемы с безопасностью по умолчанию
- Секреты хранятся в etcd кластера Kubernetes в открытом виде (base64 не является шифрованием, а лишь кодированием).
- Пользователи с доступом к API Kubernetes Namespace могут просматривать секреты — об этом следует помнить при настройках RBAC.
- Вывод данных из секретов в логи или переменные окружения может привести к утечке информации.
Рекомендации по безопасной работе
Включить шифрование данных в etcd.
Для продакшн-кластеров включайте шифрование на уровне etcd (Encryption at rest
). Тогда секреты будут храниться на диске в зашифрованном виде.Минимизировать доступ через RBAC.
Ограничивайте права на получение (get), изменение (update), создание (create) и удаление (delete) секретов. Всегда придерживайтесь принципа наименьших привилегий.Использовать namespaces.
Не храните секреты разных сред (например, prod и dev) в одном namespace.Регулярно ревизируйте секреты.
Удаляйте неиспользуемые secret-объекты, не допускайте накопления «мертвых» секретов.Используйте внешние менеджеры секретов.
Для крупных проектов и повышенных требований к безопасности рассмотрите интеграцию с HashiCorp Vault, AWS Secrets Manager или аналогами.Монтируйте секреты только в нужные поды/контейнеры.
Не добавляйте их в каждый контейнер по умолчанию.
Пример настройки шифрования секретов в etcd
Этот процесс требует изменения конфигурации control-plane и обычно применяется администратором кластера.
Создайте манифест:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-encryption-key>
- identity: {}
После настройки, перезапустите kube-apiserver с этим конфигом. Детали различаются в зависимости от инструментов управления кластером (kubeadm, kops и т.д.).
Практические советы по эксплуатации Secrets
Как просмотреть содержимое Secret
Обычной командой вы увидите кодированные данные:
kubectl get secret db-credentials -o yaml
Чтобы посмотреть декодированные значения:
kubectl get secret db-credentials -o jsonpath="{.data.username}" | base64 --decode
# Выведет «myuser»
Обновление Secret
Если вы изменили значение секрета, например, пароль, то для перезапуска пода потребуется вручную удалить под или воспользоваться rollout deployment (если вы используете deployment).
kubectl create secret generic db-credentials --from-literal=username=newuser --from-literal=password=newpass --dry-run=client -o yaml | kubectl apply -f -
Для применения изменений контейнеру, запущенному в Deployment, сделайте rollout:
kubectl rollout restart deployment my-app
Хранение Secrets вне репозитория
— Никогда не добавляйте манифесты с реальными секретами в Git! Даже закодированные в base64 значения видны как на ладони. Используйте шаблоны, Helm Secrets или внешние Secret Manager’ы.
— Используйте инструменты для безопасного взаимодействия с секретами, например, SOPS, Sealed Secrets, External Secrets Operator. Так вы сможете безопасно работать с secrets даже при CI/CD.
Интеграция со сторонними сервисами
Для управления секретами в enterprise-окружениях часто используют сторонние службы (например, HashiCorp Vault). Такие решения позволяют хранить секреты вне кластера, выдавать их подам динамически и автоматически обновлять.
Пример работы с Kubernetes External Secrets Operator:
- Внешний секрет (например, в AWS Secrets Manager);
- External Secrets Operator синхронизирует содержимое внешнего секрета с Kubernetes Secret;
- Под запрашивает секрет привычным способом (через volume или env).
Это удобно в ситуациях, где требуется регулярная ротация паролей и централизованный аудит.
Лимитации и подводные камни
- Размер одного секрета ограничен 1 МБ.
- Большие бинарные объекты лучше хранить в других местах (не секретах).
- При обновлении секрета не все типы контроллеров или подов автоматически получают новые значения — иногда требуется перезапуск.
- Секреты, подключённые как переменные окружения, получают значения только при запуске (они не обновляются при изменении секрета).
Заключение
Secrets в Kubernetes — это мощный инструмент для безопасного хранения чувствительных данных. Их поддержка встроена в платформу, и вы можете легко инкапсулировать секретные значения, ограничивать к ним доступ и передавать данные контейнерам именно так, как нужно вашему приложению.
Помните: secrets не предназначены для масштабного хранения больших файлов или сложных хранилищ ключей. Важно постоянно обращать внимание не только на их использование, но и на их защиту, конечную настройку доступа, вариант хранения вне кластера для enterprise-решений, а также интеграцию с современными инструментами управления секретами и ротации ключей.
Конфигурируйте, работайте и автоматизируйте работу с секретами — но не забывайте про лучшие практики безопасности.
Частозадаваемые технические вопросы по теме
Как автоматически ротацировать секреты без ручного обновления подов?
Для этого используйте решения вроде Kubernetes External Secrets, Secrets Store CSI Driver или интеграцию с HashiCorp Vault. Они обновляют секреты в Kubernetes при изменениях на стороне внешнего хранилища, а для автоматической перезагрузки подов используйте аннотации и rollout-плагины или automation-сценарии.
Как безопасно передавать секреты в CI/CD пайплайне?
Старайтесь не добавлять base64 значения секретов в репозиторий. Используйте инструменты для криптографической защиты файлов (Vault Secret Injector, SOPS, Sealed Secrets). В CI/CD настройте переменные окружения для kubectl и применяйте секреты на этапе деплоя.
Можно ли восстановить удаленный secret?
Если у вас есть резервная копия etcd или экспорт yaml-секретов, можете восстановить с помощью kubectl apply -f. Без backup’а секрет невозможно восстановить.
Как узнать, используются ли секреты в кластере?
Проанализируйте, к каким подам подключён secret через volumes или env. Для этого можно использовать утилиты типа kubectl-who-can, kube-no-trouble, либо писать скрипты, анализирующие связку «secrets—pods».
Как синхронизировать секреты между namespace?
Лучше всего не дублировать secrets вручную, а использовать синхронизирующие операторы (например, K8s secret sync, cross-namespace mounts) или внешние Secret Manager’ы, которые экспортируют секреты в нужные namespace автоматизировано.
Постройте личный план изучения Kubernetes до уровня Middle — бесплатно!
Kubernetes — часть карты развития DevOps
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Kubernetes
Лучшие курсы по теме

Kubernetes и Helm
Антон Ларичев
Docker и Ansible
Антон Ларичев