Знакомство с Kubernetes. Часть 14: Секреты (Secrets)

Aug 27, 2018 06:06 · 624 words · 3 minute read kubernetes

В кластере 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

Убедиться, что секрет успешно создан можно так:

kubectl get secrets
NAME                  TYPE                                  DATA      AGE
db-user-pass          Opaque                                2         51s
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-файл со следующим содержимым:

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 (вывод сокращен):

kubectl get secret mysecret -o yaml
apiVersion: v1
data:
  username: YWRtaW4=
  password: Qjd3SXRZbEhlUlIx
kind: Secret
metadata:
...
type: Opaque

Раскодировать значение из секрета можно, например, так:

echo 'Qjd3SXRZbEhlUlIx' | base64 --decode
B7wItYlHeRR1

Секреты могут быть смонтированы как тома данных или определены в качестве переменных окружения для использования в подах. Пример:

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: следует добавить в описание каждого из них. Есть возможность указания конкретного пути монтирования внутрь контейнера значения отдельного ключа из секрета:

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 доступен не будет.

Примечание. Можно задавать права доступа к объектам типа секрет (и даже к отдельным ключам).

Использование секретов как переменных окружения в описании подов выглядит так:

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-реджистри. Подробнее о нем можно почитать здесь или здесь.

Больше информации о работе с секретами можно найти в официальной документации.

tweet Share