Resources

Kubernetes Secrets | How To Create, Use, and Access

November 30, 2021

Secrets allow you to store small pieces of sensitive data, so managing them is clearly important. Learn how to create, use, and access secrets with Kubernetes.

Lukonde Mwila
DevOps Engineer

With the continued growth of the cloud-native landscape, more companies are opting to run their workloads in Kubernetes, which necessitates testing and validating application environment behavior. In the context of Kubernetes, this can be achieved by using distinct resources:

  • ConfigMaps
  • Secrets

ConfigMaps are suitable for most configuration data scenarios. However, there is certain data that can be regarded as extra-sensitive, like passwords, security tokens, and other types of private keys. This type of data would be categorized as a Secret. Secrets are Kubernetes resources used to configure your applications with sensitive data that can be made accessible to your container workloads at runtime.

Kubernetes has native support for storing and handling this type of sensitive data with care. Depending on your use case, these Secrets can act as keys or methods of authentication in your computing environments. Let’s take a closer look at what Secrets are, the different types of Secrets that exist, and how to make use of them in your Kubernetes development lifecycle.

What Are Kubernetes Secrets?

The software development life cycle typically consists of working with multiple environments. As a result, you may want to pass dynamic values to your application at runtime to control its behavior. This kind of application configuration in Kubernetes can be carried out using either ConfigMaps or Secrets.

ConfigMaps and Secrets are distinct Kubernetes objects that have a similar function but serve different purposes.

Secrets handle small amounts of sensitive data to reduce the risk of accidental exposure of confidential information. Secret data should be stored and handled in a way that can be easily hidden and possibly encrypted at rest if the environment is configured as such. Kubernetes is insecure by default. This extends to Secrets because they are not encrypted. As soon as the Secret is injected into the Pod, the Pod itself can see the Secret data in plain text.

Secrets are stored inside the Kubernetes data store (i.e., an etcd database) and are created before they can be used inside a Pods manifest file. Furthermore, Secrets have a size limit of 1 MB. When it comes to implementation, you can either mount Secrets as volumes or expose them as environment variables inside the Pod manifest files.

There are a few different types of Secrets in Kubernetes:

  • Opaque: The default Secret type if one isn’t specified in the manifest configuration file. It allows you to provide arbitrary configuration data in key-value pairs.
  • Service account token: These store a token that identifies a specific service account. Of course, don’t forget to set the <terminal inline>kubernetes.io/service-account.name<terminal inline> annotation to an existing service account.
  • Docker config: This stores the credentials for a specific Docker registry for container images.
  • Basic authentication: These store basic authentication credentials. Note that their <terminal inline>data<terminal inline> fields need to include the <terminal inline>username<terminal inline> and <terminal inline>password<terminal inline> keys.
  • SSH authentication: These store SSH credentials. You’ll have to specify an <terminal inline>ssh-privatekey<terminal inline> key-value pair in the <terminal inline>data<terminal inline> or <terminal inline>stringData<terminal inline> field.
  • TLS: These Secrets store certificates and the associated keys used for TLS. You need to make sure the <terminal inline>tls.key<terminal inline> and the <terminal inline>tls.crt<terminal inline> keys are included in the <terminal inline>data<terminal inline> field of the Secret’s configuration.
  • Bootstrap token: These are tokens used during the node bootstrap process, used to sign ConfigMaps.

Implementing Secrets

In this section, you will create a Secret and mount it using the two approaches mentioned above.

Connect to a Kubernetes Cluster

The first step is to ensure that you are connected to a Kubernetes cluster, either local or remote. The cluster setup and configuration used in this post can be found in this public repository.

You can verify the context of your cluster connection with the following command:


kubectl config current-context

Create a Secret Manifest File

Once your connection is established, proceed to create a manifest file for a Secret. The Secret will contain key-value pairs for a username and password.

You can base64-encode the values for your secret as follows:


echo -n 'jsmith' | base64
echo -n 'mysecretpassword' | base64
Note that the outputs from the previous commands need to be pasted into the YAML file in the next section.

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: anNtaXRo
  password: bXlzZWNyZXRwYXNzd29yZA==

Create a Secret in a Kubernetes Cluster

To create the Secret, use the <terminal inline>kubectl<terminal inline> command to reference the manifest file you just created. The request will be sent to the API Server in the Kubernetes Control Plane for the request to be actioned. Afterward, the data will be stored in the etcd data store of your cluster.


kubectl create -f secret.yaml
Create Secret
Create Secret
Get Secret
Get Secret

Mount Secret Values with Environment Variables

In this step, you will create a Pod that will expose the Secret values as environment variables in a container at runtime. Once the Pod has been created, check the logs to verify that the values are accessible to the container based on an executed shell command.


apiVersion: v1
kind: Pod
metadata:
  name: env-pod
spec:
  containers:
    - name: express-test
      image: lukondefmwila/express-test:latest
      command: ['sh', '-c', 'echo "Username: $USER" "Password: $PASSWORD"']
      env:
        - name: USER
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: username
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: password

Create the above Pod manifest file and execute the following command to create it in your cluster:


kubectl create -f env-pod.yaml

Once the Pod has been created, you can check the logs by running <terminal inline>kubectl logs <name-of-pod><terminal inline>.

Pod Logs
Pod Logs

Mount Secret Values with Volumes

Secrets can also be passed to containers in the form of mounted volumes. This will cause the configuration data to appear in files available to the container file system. Each top-level key in the configuration data will appear as a file containing all keys below that top-level key.


apiVersion: v1
kind: Pod
metadata: 
  name: volume-pod
spec:
  containers:
  - name: express-test
    image: lukondefmwila/express-test:latest
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/config/secret
  volumes:
  - name: secret-volume
    secret:
      secretName: my-secret

To test the Pod’s accessibility of the volume mounted secret, you can connect to the container and run read commands in the volume directory.


kubectl exec volume-pod -- ls /etc/config/secret
kubectl exec volume-pod -- cat /etc/config/secret/username
Volume Mounted Secrets
Volume Mounted Secrets

Conclusion

As we’ve discussed in this article, software teams typically configure computing environments to drive certain behavior in the development process. When developing in a Kubernetes environment, there are two ways of accomplishing this: ConfigFile and Secrets. If you have truly sensitive data, you should now be well equipped to create, use, and access Secrets in your container workloads.

Looking for an out-of-the-box monitoring solution?

With a simple one-line install, ContainIQ allows you to monitor the health of your cluster with pre-built dashboards and easy-to-set alerts.

Article by

Lukonde Mwila

DevOps Engineer

Lukonde Mwila specializes in cloud and DevOps engineering, cloud architecture designs, and cloud security at an enterprise level in the AWS landscape. He currently is a Principal Technical Evangelist at SUSE. He has a passion for sharing knowledge through speaking engagements such as meetups and tech conferences, as well as writing technical articles. His talk at DockerCon 2020 on deploying multi-container applications to AWS was one of the top-rated and most viewed sessions of the event. He is 5x AWS certified and is an advocate for containerization and serverless technologies.

Read More