Kubernetes - 02 - the 3 practical ways to use k8s secret

kubernetes

This is the second post about kubernetes secret, in the previous, I have list the 3 ways to create secrets. We can create as many secrets as we want. In this post, I will give the 3 practical ways to use the secrets in k8s deployment.

Let’s assume we have created a secret named my secret as following

1
2
3
4
5
6
7
8
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
stringData:
username: admin
password: 1f2d1e2e67df

3 ways to use k8s secrets

  • As environments
  • As volume files
  • As Kubelet auth credentials to pull image

1 Used as environments

A secret is a dictionary, we can put it in a environment as key-values.
We can put the whole dictionary into the environment or we refer one of the keys and use its value

1.1 Use as a value of a user defined env var

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
- containers
- name: container-name
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username

The environment variable POSTGRES_USER shall be the value admin

1.2 Use keys from secret directly as env, key word envFrom

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
- containers
- name: container-name
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
envFrom:
- secretRef:
name: test-secret

The environment variable username and password shall be available in the container.

2 Used as volume files

We can use the secret keys to generate files in a volume, and mount it into a container. We have 2 keys in our secret, which means we will have two files (/username and /password) created in the volume.

2.1 Mount all keys

Two steps to mount a secret into a container.

2.2.1 Create a volume from a secret

1
2
3
4
volumes:
- name: volume-from-secret
secret:
secretName: mysecret

2.2.2 Mount the volume to a directory

1
2
3
4
volumeMounts:
- name: volume-from-secret
mountPath: "/etc/foo"
readOnly: true

Put them together in a pod yaml file

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

Since we mount the secret volume (I call a volume created from a secret) to /etc/foo, we can use the values from the files created from the secret keys.

1
2
3
4
$cat /etc/foo/username 
admin
$cat /etc/foo/password
1f2d1e2e67df

2.2 Mount subset of the secret keys to user defind subfolder

To select a specific key instead of mount all keys into the folder, we can add items when creating the secret volume

2.2.1 Create a volume from a secret

1
2
3
4
5
6
7
8
volumes:
- name: volume-from-secret
secret:
secretName: mysecret

items:
- key: username
path: my-group/my-username

2.2.2 Mount the volume to a directory(which is the same as above)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

Now you will find only username is projected.

1
2
$cat /etc/foo/my-group/my-username
admin

2.3 File mode

0644 is used by default, which can be changed as following

1
2
3
4
5
volumes:
- name: foo
secret:
secretName: mysecret
defaultMode: 0400

3 Kubelet auth to pull image

3.1 Use image pull secret in pod spec

When k8s is trying to pull image from image registry, it will check list of docker-registry secrets in the same namespace in the field imagePullSecrets from your pod yaml specification.

  • To create a secret for docker authentication

    1
    kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
  • Refer the secret in the pod spec

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    apiVersion: v1
    kind: Pod
    metadata:
    name: foo
    namespace: awesomeapps
    spec:
    containers:
    - name: foo
    image: YOUR_PRIVATE_DOCKER_IMAGE
    imagePullSecrets:
    - name: myregistrykey

3.2 Use image pull secret in pod service account

Since each pod will be associated with an service account, we can also add the imagePullSecrets to the service account
Usually if we don’t specify a service account when defining pod or deployment, the default service account is used in that case.

3.2.1 Associate a secret to service account

To add a secret to a service account, add a field ‘imagePullSecrets’ to the sa spec.

  • Patch an existing service account
    We can patch the service account as following

    1
    kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
  • Create a new one service account with imagePullSecrets

    1
    2
    3
    4
    5
    6
    7
    8
    apiVersion: v1
    kind: ServiceAccount
    metadata:
    name: my-pod-used-service-account
    namespace: default

    imagePullSecrets:
    - name: myregistrykey

3.2.2 Config a pod to use the service account, field ‘serviceAccountName’ in Pod spec

1
2
3
4
5
6
7
8
9
10
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: YOUR_PRIVATE_DOCKER_IMAGE
serviceAccountName: my-pod-used-service-account

When pod is created with service account my-pod-used-service-account, the imagePullSecrets will be added automatically in the spec, we can verify

1
kubectl get pod THE_POD_NAME -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'

Related:
https://kaichu.se/Kubernetes/2020/09/19/kubernetes-01-the-3-practical-ways-to-create-k8s-secret.html

References:
https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod

https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/