This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Managing Secrets

Managing confidential settings data using Secrets.

1 - Managing Secrets using kubectl

Creating Secret objects using kubectl command line.

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. It is recommended to run this tutorial on a cluster with at least two nodes that are not acting as control plane hosts. If you do not already have a cluster, you can create one by using minikube or you can use one of these Kubernetes playgrounds:

Create a Secret

A Secret can contain user credentials required by pods to access a database. For example, a database connection string consists of a username and password. You can store the username in a file ./username.txt and the password in a file ./password.txt on your local machine.

echo -n 'admin' > ./username.txt
echo -n '1f2d1e2e67df' > ./password.txt

In these commands, the -n flag ensures that the generated files do not have an extra newline character at the end of the text. This is important because when kubectl reads a file and encodes the content into a base64 string, the extra newline character gets encoded too.

The kubectl create secret command packages these files into a Secret and creates the object on the API server.

kubectl create secret generic db-user-pass \
  --from-file=./username.txt \
  --from-file=./password.txt

The output is similar to:

secret/db-user-pass created

The default key name is the filename. You can optionally set the key name using --from-file=[key=]source. For example:

kubectl create secret generic db-user-pass \
  --from-file=username=./username.txt \
  --from-file=password=./password.txt

You do not need to escape special characters in password strings that you include in a file.

You can also provide Secret data using the --from-literal=<key>=<value> tag. This tag can be specified more than once to provide multiple key-value pairs. Note that special characters such as $, \, *, =, and ! will be interpreted by your shell and require escaping.

In most shells, the easiest way to escape the password is to surround it with single quotes ('). For example, if your password is S!B\*d$zDsb=, run the following command:

kubectl create secret generic db-user-pass \
  --from-literal=username=devuser \
  --from-literal=password='S!B\*d$zDsb='

Verify the Secret

Check that the Secret was created:

kubectl get secrets

The output is similar to:

NAME                  TYPE                                  DATA      AGE
db-user-pass          Opaque                                2         51s

You can view a description of the Secret:

kubectl describe secrets/db-user-pass

The output is similar to:

Name:            db-user-pass
Namespace:       default
Labels:          <none>
Annotations:     <none>

Type:            Opaque

Data
====
password:    12 bytes
username:    5 bytes

The commands kubectl get and kubectl describe avoid showing the contents of a Secret by default. This is to protect the Secret from being exposed accidentally, or from being stored in a terminal log.

To check the actual content of the encoded data, refer to Decoding the Secret.

Decoding the Secret

To view the contents of the Secret you created, run the following command:

kubectl get secret db-user-pass -o jsonpath='{.data}'

The output is similar to:

{"password":"MWYyZDFlMmU2N2Rm","username":"YWRtaW4="}

Now you can decode the password data:

# This is an example for documentation purposes.
# If you did things this way, the data 'MWYyZDFlMmU2N2Rm' could be stored in
# your shell history.
# Someone with access to you computer could find that remembered command
# and base-64 decode the secret, perhaps without your knowledge.
# It's usually better to combine the steps, as shown later in the page.
echo 'MWYyZDFlMmU2N2Rm' | base64 --decode

The output is similar to:

1f2d1e2e67df

In order to avoid storing a secret encoded value in your shell history, you can run the following command:

kubectl get secret db-user-pass -o jsonpath='{.data.password}' | base64 --decode

The output shall be similar as above.

Clean Up

Delete the Secret you created:

kubectl delete secret db-user-pass

What's next

2 - Managing Secrets using Configuration File

Creating Secret objects using resource configuration file.

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. It is recommended to run this tutorial on a cluster with at least two nodes that are not acting as control plane hosts. If you do not already have a cluster, you can create one by using minikube or you can use one of these Kubernetes playgrounds:

Create the Secret

You can define the Secret object in a manifest first, in JSON or YAML format, and then create that object. The Secret resource contains two maps: data and stringData. The data field is used to store arbitrary data, encoded using base64. The stringData field is provided for convenience, and it allows you to provide the same data as unencoded strings. The keys of data and stringData must consist of alphanumeric characters, -, _ or ..

The following example stores two strings in a Secret using the data field.

  1. Convert the strings to base64:

    echo -n 'admin' | base64
    echo -n '1f2d1e2e67df' | base64
    

    The output is similar to:

    YWRtaW4=
    MWYyZDFlMmU2N2Rm
    
  2. Create the manifest:

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    type: Opaque
    data:
      username: YWRtaW4=
      password: MWYyZDFlMmU2N2Rm
    

    Note that the name of a Secret object must be a valid DNS subdomain name.

  3. Create the Secret using kubectl apply:

    kubectl apply -f ./secret.yaml
    

    The output is similar to:

    secret/mysecret created
    

To verify that the Secret was created and to decode the Secret data, refer to Managing Secrets using kubectl.

Specify unencoded data when creating a Secret

For certain scenarios, you may wish to use the stringData field instead. This field allows you to put a non-base64 encoded string directly into the Secret, and the string will be encoded for you when the Secret is created or updated.

A practical example of this might be where you are deploying an application that uses a Secret to store a configuration file, and you want to populate parts of that configuration file during your deployment process.

For example, if your application uses the following configuration file:

apiUrl: "https://my.api.com/api/v1"
username: "<user>"
password: "<password>"

You could store this in a Secret using the following definition:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
stringData:
  config.yaml: |
    apiUrl: "https://my.api.com/api/v1"
    username: <user>
    password: <password>    

When you retrieve the Secret data, the command returns the encoded values, and not the plaintext values you provided in stringData.

For example, if you run the following command:

kubectl get secret mysecret -o yaml

The output is similar to:

apiVersion: v1
data:
  config.yaml: YXBpVXJsOiAiaHR0cHM6Ly9teS5hcGkuY29tL2FwaS92MSIKdXNlcm5hbWU6IHt7dXNlcm5hbWV9fQpwYXNzd29yZDoge3twYXNzd29yZH19
kind: Secret
metadata:
  creationTimestamp: 2018-11-15T20:40:59Z
  name: mysecret
  namespace: default
  resourceVersion: "7225"
  uid: c280ad2e-e916-11e8-98f2-025000000001
type: Opaque

Specify both data and stringData

If you specify a field in both data and stringData, the value from stringData is used.

For example, if you define the following Secret:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
stringData:
  username: administrator

The Secret object is created as follows:

apiVersion: v1
data:
  username: YWRtaW5pc3RyYXRvcg==
kind: Secret
metadata:
  creationTimestamp: 2018-11-15T20:46:46Z
  name: mysecret
  namespace: default
  resourceVersion: "7579"
  uid: 91460ecb-e917-11e8-98f2-025000000001
type: Opaque

YWRtaW5pc3RyYXRvcg== decodes to administrator.

Clean up

To delete the Secret you have created:

kubectl delete secret mysecret

What's next

3 - Managing Secrets using Kustomize

Creating Secret objects using kustomization.yaml file.

Since Kubernetes v1.14, kubectl supports managing objects using Kustomize. Kustomize provides resource Generators to create Secrets and ConfigMaps. The Kustomize generators should be specified in a kustomization.yaml file inside a directory. After generating the Secret, you can create the Secret on the API server with kubectl apply.

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. It is recommended to run this tutorial on a cluster with at least two nodes that are not acting as control plane hosts. If you do not already have a cluster, you can create one by using minikube or you can use one of these Kubernetes playgrounds:

Create the Kustomization file

You can generate a Secret by defining a secretGenerator in a kustomization.yaml file that references other existing files. For example, the following kustomization file references the ./username.txt and the ./password.txt files:

secretGenerator:
- name: db-user-pass
  files:
  - username.txt
  - password.txt

You can also define the secretGenerator in the kustomization.yaml file by providing some literals. For example, the following kustomization.yaml file contains two literals for username and password respectively:

secretGenerator:
- name: db-user-pass
  literals:
  - username=admin
  - password=1f2d1e2e67df

You can also define the secretGenerator in the kustomization.yaml file by providing .env files. For example, the following kustomization.yaml file pulls in data from .env.secret file:

secretGenerator:
- name: db-user-pass
  envs:
  - .env.secret

Note that in all cases, you don't need to base64 encode the values.

Create the Secret

Apply the directory containing the kustomization.yaml to create the Secret.

kubectl apply -k .

The output is similar to:

secret/db-user-pass-96mffmfh4k created

Note that when a Secret is generated, the Secret name is created by hashing the Secret data and appending the hash value to the name. This ensures that a new Secret is generated each time the data is modified.

Check the Secret created

You can check that the secret was created:

kubectl get secrets

The output is similar to:

NAME                             TYPE                                  DATA      AGE
db-user-pass-96mffmfh4k          Opaque                                2         51s

You can view a description of the secret:

kubectl describe secrets/db-user-pass-96mffmfh4k

The output is similar to:

Name:            db-user-pass-96mffmfh4k
Namespace:       default
Labels:          <none>
Annotations:     <none>

Type:            Opaque

Data
====
password.txt:    12 bytes
username.txt:    5 bytes

The commands kubectl get and kubectl describe avoid showing the contents of a Secret by default. This is to protect the Secret from being exposed accidentally to an onlooker, or from being stored in a terminal log. To check the actual content of the encoded data, please refer to decoding secret.

Clean Up

To delete the Secret you have created:

kubectl delete secret db-user-pass-96mffmfh4k

What's next