Secret и почему base64 это не шифрование
Чем Secret отличается от ConfigMap, какие бывают типы и что на самом деле защищает секреты в кластере.
Что такое Secret
Secret и ConfigMap на уровне Kubernetes почти близнецы. Оба хранят
пары «ключ/значение» в etcd. Отличий два: Secret хранит значения в
base64, и у него есть type. Всё.
Главная путаница новичков: base64 это не шифрование. Это просто
кодировка, чтобы бинарные данные можно было положить в YAML. Любой,
кто получит доступ к Secret в etcd или через kubectl get -o yaml,
расшифрует за секунду через base64 -d. Secret внутри кластера
защищён только RBAC.
Зачем тогда Secret, если он encoded, а не encrypted? Три причины.
Ключи не попадают в kubectl describe pod и логи (там показан факт env,
но не значение). Можно включить etcd encryption at rest на уровне
кластера и зашифровать все Secret оптом. Внешние инструменты (Vault,
Sealed Secrets) знают, куда складывать расшифрованное.
Минимальный YAML
apiVersion: v1
kind: Secret
metadata:
name: db-creds
type: Opaque
data:
username: YWRtaW4=
password: czNjcmV0
YWRtaW4= это admin в base64. Кодируют так:
echo -n admin | base64
-n обязателен, иначе echo добавит перевод строки и значение в
Secret будет с лишним \n на конце. Очень типичная ловушка.
Лишний \n в значении не видно ни в kubectl get, ни в describe.
Логин падает с «invalid credentials», а Secret при этом выглядит
нормальным.
Поле type
Opaque. Произвольные ключи, обычный кейс.kubernetes.io/dockerconfigjson. Для image pull secrets, нужны ключи.dockerconfigjsonопределённого формата.kubernetes.io/tls. Для TLS-сертификатов, нужныtls.crtиtls.key.kubernetes.io/service-account-token. Токен ServiceAccount, раньше создавался автоматически, с 1.24 уже нет.
У каждого специального типа свой набор обязательных ключей, apiserver их валидирует.
Подключение к Pod
Один в один как ConfigMap, только secretKeyRef вместо
configMapKeyRef:
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-creds
key: username
И volume:
volumes:
- name: creds
secret:
secretName: db-creds
defaultMode: 0400
defaultMode: 0400 ставит read-only для владельца, остальным ничего.
Хорошая привычка для секретов.
automountServiceAccountToken
По умолчанию Kubernetes монтирует в каждый Pod токен ServiceAccount - ключ доступа к API кластера. Если приложение к API не ходит, токен это лишний секрет внутри Pod. Его выключают в spec:
spec:
automountServiceAccountToken: false
Меньше доступов внутри Pod - меньше что украсть при компрометации.
Связанные команды
kubectl create secret generic db-creds \
--from-literal=username=admin \
--from-literal=password=s3cret
kubectl create secret tls my-tls --cert=cert.pem --key=key.pem
kubectl get secret db-creds -o yaml
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d
kubectl explain secret.type
Что часто ломается
- Secret коммитят в git как обычный YAML. Это утечка. В git кладут SealedSecrets, External Secrets ссылки, или SOPS-шифрованные файлы.
- Считают Secret шифрованным. Нет, он encoded. Если данные важны, включают etcd encryption at rest на кластере.
- Secret поменяли, env в Pod не обновился (как с ConfigMap). Нужен rollout либо mount через volume.
Домашка
Теорию закрепляет задание на своём кластере: 4 шага с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.
./run.sh start k8s-secret # развернуть стартовое состояние
./run.sh verify k8s-secret # проверить текущий шаг
Коротко
- Secret отличается от ConfigMap только base64-кодировкой значений и
полем
type. - base64 это кодировка, а не шифрование:
base64 -dвскрывает значение за секунду. - Реально секреты защищает RBAC, etcd encryption at rest и внешние хранилища вроде Vault.
echo -nпри ручном кодировании обязателен, иначе в значении окажется лишний перевод строки.automountServiceAccountToken: falseубирает из Pod лишний токен доступа к API.
Дрилл · вопросы как на собесе
Проверь себя без подсказок
Сформулируй ответ вслух или письменно, потом раскрой и честно отметь: знал или нет.
Что такое ConfigMap и чем он отличается от Secret?
K8S-004Что такое Secret и в чём его проблемы с безопасностью?
K8S-015Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс