K8s Q A Secrets

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску


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

imagePullSecrets

https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod Specifying imagePullSecrets on a Pod

Note: This is the recommended approach to run containers based on images in private registries. Kubernetes supports specifying container image registry keys on a Pod. imagePullSecrets must all be in the same namespace as the Pod. The referenced Secrets must be of type kubernetes.io/dockercfg or kubernetes.io/dockerconfigjson.

Creating a Secret with a Docker config

You need to know the username, registry password and client email address for authenticating to the registry, as well as its hostname. Run the following command, substituting the appropriate uppercase values:

kubectl create secret docker-registry <name> \

 --docker-server=DOCKER_REGISTRY_SERVER \
 --docker-username=DOCKER_USER \
 --docker-password=DOCKER_PASSWORD \
 --docker-email=DOCKER_EMAIL

If you already have a Docker credentials file then, rather than using the above command, you can import the credentials file as a Kubernetes Secrets. Create a Secret based on existing Docker credentials explains how to set this up.

This is particularly useful if you are using multiple private container registries, as kubectl create secret docker-registry creates a Secret that only works with a single private registry.

Note: Pods can only reference image pull secrets in their own namespace, so this process needs to be done one time per namespace. Referring to an imagePullSecrets on a Pod

Now, you can create pods which reference that secret by adding an imagePullSecrets section to a Pod definition. Each item in the imagePullSecrets array can only reference a Secret in the same namespace.

For example:

cat <<EOF > pod.yaml apiVersion: v1 kind: Pod metadata:

 name: foo
 namespace: awesomeapps

spec:

 containers:
   - name: foo
     image: janedoe/awesomeapp:v1
 imagePullSecrets:
   - name: myregistrykey

EOF

cat <<EOF >> ./kustomization.yaml resources: - pod.yaml EOF This needs to be done for each pod that is using a private registry.

However, setting of this field can be automated by setting the imagePullSecrets in a ServiceAccount resource.

Check Add ImagePullSecrets to a Service Account for detailed instructions.

You can use this in conjunction with a per-node .docker/config.json. The credentials will be merged.