В кластере Kubernetes
объекты типа секрет (secret
) предназначены для хранения конфиденциальной информации, такой как пароли, OAuth-токены или ssh-ключи.
Представление конфиденциальной информации в виде секрета является более безопасным и гибким, чем добавление такой информации в открытом виде при описании контейнера или сборке docker-образа.
Объекты типа секрет могут быть созданы как пользователем, так и системой. Для использования секрета, под (pod
) должен на него ссылаться - чаще всего как на файл, находящийся на примонтированном томе. Кроме того, kubelet
может использовать секреты при скачивании docker-образов из реджистри.
Kubernetes
автоматически создает необходимые ему секреты, которые содержат учетные данные для доступа к API, и автоматически модифицирует созданные поды для использования этого секрета.
Объекты типа секрет могут быть созданы с помощью команды kubectl create secret
. Рассмотрим пример - допустим, для подключения к БД из пода необходимы логин и пароль, которые находятся в отдельных файлах:
echo -n 'admin' > ./username.txt
echo -n 'B7wItYlHeRR1' > ./password.txt
C помощью данной команды можно преобразовать эти два файла в объект типа секрет:
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
secret "db-user-pass" created
Убедиться, что секрет успешно создан можно так:
1 2 3 4 |
kubectl get secrets NAME TYPE DATA AGE db-user-pass Opaque 2 51s |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
kubectl describe secrets/db-user-pass Name: db-user-pass Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== password.txt: 12 bytes username.txt: 5 bytes |
Стоит отметить, что ни get
, ни describe
не отобразят содержимое данного секрета на экране пользователя - это сделано из соображений безопасности.
Еще один вариант создания секрета - сначала описать его в формате yaml (или json), и только после этого создать секрет. Для этого, каждое используемое значение должно быть закодировано в base64:
echo -n 'admin' | base64 YWRtaW4=
echo -n 'B7wItYlHeRR1' | base64 Qjd3SXRZbEhlUlIx
Создаем yaml-файл со следующим содержимым:
1 2 3 4 5 6 7 8 9 |
apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: YWRtaW4= password: Qjd3SXRZbEhlUlIx |
Здесь поле data
это map, ключи которого могут содержать буквенно-цифровые последовательности и символы -
, _
и .
, а значения - необходимые данные, закодированные в base64.
Теперь можно создать секрет с использованием команды kubectl create
:
kubectl create -f ./secret.yaml
secret "mysecret" created
Получим информацию о только что созданном секрете с помощью kubectl get secret
(вывод сокращен):
1 2 3 4 5 6 7 8 9 |
kubectl get secret mysecret -o yaml apiVersion: v1 data: username: YWRtaW4= password: Qjd3SXRZbEhlUlIx kind: Secret metadata: ... |
Раскодировать значение из секрета можно, например, так:
echo 'Qjd3SXRZbEhlUlIx' | base64 --decode
B7wItYlHeRR1
Секреты могут быть смонтированы как тома данных или определены в качестве переменных окружения для использования в подах. Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: redis volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo secret: secretName: mysecret |
Если в поде существует несколько контейнеров, которые должны использовать данный секрет, то секцию volumeMounts:
следует добавить в описание каждого из них. Есть возможность указания конкретного пути монтирования внутрь контейнера значения отдельного ключа из секрета:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: redis volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo secret: secretName: mysecret items: - key: username path: my-group/my-username |
В этом примере значение username
будет доступно по пути /etc/foo/my-group/my-username
вместо /etc/foo/username
, а password
доступен не будет.
Примечание. Можно задавать права доступа к объектам типа секрет (и даже к отдельным ключам).
Использование секретов как переменных окружения в описании подов выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
apiVersion: v1 kind: Pod metadata: name: secret-env-pod spec: containers: - name: mycontainer image: redis env: - name: SECRET_USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name: SECRET_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password restartPolicy: Never |
После запуска пода в контейнере с именем mycontainer
проверим переменные окружения:
echo $SECRET_USERNAME
admin
echo $SECRET_PASSWORD
B7wItYlHeRR1
Еще один частный случай использования секретов - параметр imagePullSecrets
, который содержит пароль для доступа к docker-реджистри. Подробнее о нем можно почитать здесь