Distribute Credentials Securely Using Secrets

This page shows how to securely inject sensitive data, such as passwords and encryption keys, into Pods.

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using minikube or you can use one of these Kubernetes playgrounds:

Convert your secret data to a base-64 representation

Suppose you want to have two pieces of secret data: a username my-app and a password 39528$vdg7Jb. First, use a base64 encoding tool to convert your username and password to a base64 representation. Here’s an example using the commonly available base64 program:

  1. echo -n 'my-app' | base64
  2. echo -n '39528$vdg7Jb' | base64

The output shows that the base-64 representation of your username is bXktYXBw, and the base-64 representation of your password is Mzk1MjgkdmRnN0pi.

Caution: Use a local tool trusted by your OS to decrease the security risks of external tools.

Create a Secret

Here is a configuration file you can use to create a Secret that holds your username and password:

pods/inject/secret.yaml Distribute Credentials Securely Using Secrets - 图1

  1. apiVersion: v1
  2. kind: Secret
  3. metadata:
  4. name: test-secret
  5. data:
  6. username: bXktYXBw
  7. password: Mzk1MjgkdmRnN0pi
  1. Create the Secret

    1. kubectl apply -f https://k8s.io/examples/pods/inject/secret.yaml
  2. View information about the Secret:

    1. kubectl get secret test-secret

    Output:

    1. NAME TYPE DATA AGE
    2. test-secret Opaque 2 1m
  3. View more detailed information about the Secret:

    1. kubectl describe secret test-secret

    Output:

    1. Name: test-secret
    2. Namespace: default
    3. Labels: <none>
    4. Annotations: <none>
    5. Type: Opaque
    6. Data
    7. ====
    8. password: 13 bytes
    9. username: 7 bytes

Create a Secret directly with kubectl

If you want to skip the Base64 encoding step, you can create the same Secret using the kubectl create secret command. For example:

  1. kubectl create secret generic test-secret --from-literal='username=my-app' --from-literal='password=39528$vdg7Jb'

This is more convenient. The detailed approach shown earlier runs through each step explicitly to demonstrate what is happening.

Create a Pod that has access to the secret data through a Volume

Here is a configuration file you can use to create a Pod:

pods/inject/secret-pod.yaml Distribute Credentials Securely Using Secrets - 图2

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: secret-test-pod
  5. spec:
  6. containers:
  7. - name: test-container
  8. image: nginx
  9. volumeMounts:
  10. # name must match the volume name below
  11. - name: secret-volume
  12. mountPath: /etc/secret-volume
  13. # The secret data is exposed to Containers in the Pod through a Volume.
  14. volumes:
  15. - name: secret-volume
  16. secret:
  17. secretName: test-secret
  1. Create the Pod:

    1. kubectl apply -f https://k8s.io/examples/pods/inject/secret-pod.yaml
  2. Verify that your Pod is running:

    1. kubectl get pod secret-test-pod

    Output:

    1. NAME READY STATUS RESTARTS AGE
    2. secret-test-pod 1/1 Running 0 42m
  3. Get a shell into the Container that is running in your Pod:

    1. kubectl exec -i -t secret-test-pod -- /bin/bash
  4. The secret data is exposed to the Container through a Volume mounted under /etc/secret-volume.

    In your shell, list the files in the /etc/secret-volume directory:

    1. # Run this in the shell inside the container
    2. ls /etc/secret-volume

    The output shows two files, one for each piece of secret data:

    1. password username
  5. In your shell, display the contents of the username and password files:

    1. # Run this in the shell inside the container
    2. echo "$( cat /etc/secret-volume/username )"
    3. echo "$( cat /etc/secret-volume/password )"

    The output is your username and password:

    1. my-app
    2. 39528$vdg7Jb

Define container environment variables using Secret data

Define a container environment variable with data from a single Secret

  • Define an environment variable as a key-value pair in a Secret:

    1. kubectl create secret generic backend-user --from-literal=backend-username='backend-admin'
  • Assign the backend-username value defined in the Secret to the SECRET_USERNAME environment variable in the Pod specification.

    pods/inject/pod-single-secret-env-variable.yaml Distribute Credentials Securely Using Secrets - 图3

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: env-single-secret
    5. spec:
    6. containers:
    7. - name: envars-test-container
    8. image: nginx
    9. env:
    10. - name: SECRET_USERNAME
    11. valueFrom:
    12. secretKeyRef:
    13. name: backend-user
    14. key: backend-username
  • Create the Pod:

    1. kubectl create -f https://k8s.io/examples/pods/inject/pod-single-secret-env-variable.yaml
  • In your shell, display the content of SECRET_USERNAME container environment variable

    1. kubectl exec -i -t env-single-secret -- /bin/sh -c 'echo $SECRET_USERNAME'

    The output is

    1. backend-admin

Define container environment variables with data from multiple Secrets

  • As with the previous example, create the Secrets first.

    1. kubectl create secret generic backend-user --from-literal=backend-username='backend-admin'
    2. kubectl create secret generic db-user --from-literal=db-username='db-admin'
  • Define the environment variables in the Pod specification.

    pods/inject/pod-multiple-secret-env-variable.yaml Distribute Credentials Securely Using Secrets - 图4

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: envvars-multiple-secrets
    5. spec:
    6. containers:
    7. - name: envars-test-container
    8. image: nginx
    9. env:
    10. - name: BACKEND_USERNAME
    11. valueFrom:
    12. secretKeyRef:
    13. name: backend-user
    14. key: backend-username
    15. - name: DB_USERNAME
    16. valueFrom:
    17. secretKeyRef:
    18. name: db-user
    19. key: db-username
  • Create the Pod:

    1. kubectl create -f https://k8s.io/examples/pods/inject/pod-multiple-secret-env-variable.yaml
  • In your shell, display the container environment variables

    1. kubectl exec -i -t envvars-multiple-secrets -- /bin/sh -c 'env | grep _USERNAME'

    The output is

    1. DB_USERNAME=db-admin
    2. BACKEND_USERNAME=backend-admin

Configure all key-value pairs in a Secret as container environment variables

Note: This functionality is available in Kubernetes v1.6 and later.

  • Create a Secret containing multiple key-value pairs

    1. kubectl create secret generic test-secret --from-literal=username='my-app' --from-literal=password='39528$vdg7Jb'
  • Use envFrom to define all of the Secret’s data as container environment variables. The key from the Secret becomes the environment variable name in the Pod.

    pods/inject/pod-secret-envFrom.yaml Distribute Credentials Securely Using Secrets - 图5

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: envfrom-secret
    5. spec:
    6. containers:
    7. - name: envars-test-container
    8. image: nginx
    9. envFrom:
    10. - secretRef:
    11. name: test-secret
  • Create the Pod:

    1. kubectl create -f https://k8s.io/examples/pods/inject/pod-secret-envFrom.yaml
  • In your shell, display username and password container environment variables

    1. kubectl exec -i -t envfrom-secret -- /bin/sh -c 'echo "username: $username\npassword: $password\n"'

    The output is

    1. username: my-app
    2. password: 39528$vdg7Jb

References

What’s next