4th gen AMD EPYC coming soon Pre-order now

How to Create and Use Kubernetes Secrets | A Complete Guide

July 7th, 2023
How to Create and Use Kubernetes Secrets | A Complete Guide

Are you trying to deploy an application into a Kubernetes cluster and need to pass it some sensitive information such as a username and password, an API token, or an SSL certificate? Most applications have some sensitive data required to configure them, and thankfully, Kubernetes has a primitive made for managing such information named a Secret. These secrets consist of key-value pairs.

In this guide, we'll look at what Kubernetes secrets are and how they can be created and used in your Kubernetes cluster.

Prerequisites

This guide will demonstrate various examples. If you’d like to follow along, be sure to have the following:

  • A Kubernetes cluster (Minikube is used for this demonstration)
  • The Kubernetes Kubectl command-line tool
  • Basic knowledge of Kubernetes

What are Secrets in Kubernetes?

A Secret is an object that contains a small amount of sensitive data, such as a password or token, to be used within a Kubernetes environment. Secrets are used for storing sensitive information like authentication tokens, passwords, ssh keys, and certificates. Secrets are stored in etcd (the datastore for Kubernetes). Secrets are similar to ConfigMaps but are specifically intended to hold confidential data. The data stored using secrets are independent of pods, but pods can reference the secrets as container environment variables or the secrets can be mounted as volumes to the container.

Importance of Kubernetes Secrets

Secrets can be quite secure when effectively managed. They provide a secure means of managing sensitive data that your applications running in Kubernetes may need. They prevent you from having to hardcode sensitive data directly into configuration files or application codes, as doing that would be insecure, and the data could be accessed or intercepted by just anyone.

Types of Kubernetes Secret

There are a few different types of secrets, and when creating a secret, you can specify its type.

  • Opaque: This is the default type, which is the type that is assumed when a secret type is not specified, and it can store arbitrary user-defined data in key-value pairs. Data is stored as base64-encoded within this secret type.
  • Docker-registry: Used to store credentials for authenticating with a private Docker registry.
  • TLS: This secret type is designed for storing TLS certificates and their private keys.
  • Service Account Token: The service account token secret type is used to store a token that identifies a service account. When using this Secret type, the kubernetes.io/service-account.name annotation needs to be set to an existing service account name.
  • Basic authentication: This is used for storing basic authentication credentials. If you want to use this type, note that it requires that its data field contains the username and password keys.
  • SSH authentication: This secret type is for storing data used for SSH authentication. It requires you to add an ssh-privatekey key-value pair in the data as the SSH credential to use.
  • Bootstrap token: This type of Secret is designed for tokens used during the node bootstrap process or when adding new nodes to an existing cluster. It stores tokens used to sign well-known ConfigMaps.

These secret types serve a specific purpose, so you can use any of these types depending on the information you want to store.

How to create Kubernetes Secrets?

There are three main ways of creating a Kubernetes secret. You can either create a Kubernetes secret in the command line using the kubectl create secret command, you can use a configuration file, or use a generator like Kustomize. Below we will demonstrate how to create secrets in each of these three ways in detail.

1. Create a secret using Kubectl

Using Kubectl is the easiest way to create a Kubernetes secret. You do this using the kubectl create secret command. There are two different options when using this method.

Firstly, you can do from-literal, where you pass the key and value as literal strings in the command. This method doesn't require you to create a file, which is convenient because you likely wouldn't want to store your secrets in a plaintext source file anyway.

The second option is the from-file option, in which you pass a key and then a path to the file containing the key value on your local system. Both of these options handle the base64 encoding for you, so you can pass in your secret without having to encode it first.

Using from-file

Step 1 - Create the secret data file

To create a secret from a file, you can use the from-file option. First, create a file to store the secret data. Here you'd be creating two files; a username.txt file and a password.txt file. These files will contain a value for username and password, respectively. Run the following code to create the files and write the string values in them:

# Store the string 'superuser' in the file 'username.txt'
echo -n 'superuser' > username.txt

# Store the string 'secretpasscode' in the file 'password.txt'
echo -n 'secretpasscode' > password.txt

The -n flag ensures that no newline character is added to the string before writing it to the file. create secret data files

Step 2 - Using the files

Now run the following command to create a secret using the files:

kubectl create secret generic demo-credentials \
--from-file=username=./username.txt \
--from-file=password=./password.txt

create secret using the from-file option

This will create an Opaque Kubernetes secret named demo-credentials using the content of the username.txt and password.txt files as the values for the username key and the password key, respectively, in the demo-credentials secret.

Using from-literal

This option of using kubectl directly in the CLI doesn't require you to create any file. To create a generic secret by passing the key values directly as literal values, execute the following:

kubectl create secret generic demo-credentials2 \
--from-literal=username=rootuser \
--from-literal=password=rootpassword

create secret using the from-literal option

This command creates a generic Secret Kubernetes secret named demo-credentials2 with the username key set to 'rootuser' and the password key set to 'rootpassword'.

2. Creating a Secret using a configuration file

You can define a YAML file to create a Kubernetes secret like any other Kubernetes resource. This file will specify that it is of kind Secret, defines the name of the secret within the metadata, and then contain the key and value of the secret within the data portion. Using the data field requires you to encode the secret data, but if you want to use the data as it is, you can use the stringData field instead. To encode your secret data, you can use the base64 command line utility. For this demonstration, you'd be converting the username and password data to base64.

Step 1 - Encode the secret data

To encode the data, run the following commands:

# Encode the string 'adminuser' in base64 format
echo -n 'adminuser' | base64

# Encode the string 'secretpassword' in base64 format
echo -n 'secretpassword' | base64

You should see the converted data in the terminal when you run the commands - you'll use these in the configuration file.

encode secret data

Step 2 - Create the configuration/YAML file

Create a YAML file and add the following configuration to it:

apiVersion: v1
kind: Secret
metadata:
  name: new-secret
type: Opaque
data:
  username: YWRtaW51c2Vy
  password: c2VjcmV0cGFzc3dvcmQ=

Notice that the base64 encoded values are added as the values for username and password in the data field.

Step 3 - Create a Kubernetes secret using the configuration file

To create the secret, you'd then run the command:

# Apply the configuration defined in the 'secrets-config.yaml' file
kubectl apply -f secrets-config.yaml

where secrets-config.yaml is the name of the file. After running the command, you should get an output indicating that the secret has been created.

create new secret using a configuration file

3. Create Kubernetes Secrets using a generator (Kustomize)

You can create Kubernetes secrets using a resource generator like Kustomize. It provides more flexibility and automation for secret creation.

Step 1 - Create a kustomization.yaml file

To create a secret with Kustomize, first, create kustomization.yaml file and add the following configuration to it:

secretGenerator:
- name: demo-credentials
  files:
  - username.txt
  - password.txt

The files containing the secret data are referenced in the definition above. With the secretGenerator, you can reference files containing the secret data, the literal values of the secret data, or environment variable files.

Step 2 - Generate the secret

Run the following command to generate the secret:

# Apply the Kubernetes configuration using Kustomize in the current directory
kubectl apply -k .

After running the command, you should see an output saying the secret has been created, like in the image below:

secret created using Kustomize

4. Verifying the secret

You can check if the secrets were successfully created by using the kubectl get secrets command.

kubectl get secrets

You should see the secrets you've created displayed in the terminal:

list secrets

You can display more details about a secret using the kubectl describe secret command, run the following command to display more information about the demo-credentials secret:

kubectl describe secret demo-credentials

describe demo-credentials

If you'd like to display just the data field of a secret, you can do that using the following command:

kubectl get secret demo-credentials -o jsonpath='{.data}'

This will display the base64 encoded format of the demo-credentials secret data.

display encode format of demo-credentials secret data

To display the secret data and decode them so they are shown in a plaintext format, you can use the following:

# Retrieve and decode the value of the 'password' data entry in the 'demo-credentials' Secret
kubectl get secret demo-credentials -o jsonpath='{.data.password}' | base64 --decode

# Retrieve and decode the value of the 'username' data entry in the 'demo-credentials' Secret
kubectl get secret demo-credentials -o jsonpath='{.data.username}' | base64 --decode

decode secret data

Editing Secrets

Now you know how to display secrets and their data, what if you discovered you made a mistake in the secret you had previously created? You can do that using the kubectl edit secrets command or by editing the YAML file. Note that you cannot edit a secret that was set to be immutable.

kubectl edit secrets demo-credentials

The command above will open the specified secret in your terminal's default editor allowing you to modify its contents as shown in the image below:

edit secret

How to use Kubernetes Secrets?

After creating the secret within Kubernetes, how do you access it within an application? There are three main ways of consuming secrets. The first is to inject it as an environment variable inside the container, the second way to consume a secret is to mount it into a container using a volume and the third is for pulling private images from docker registries. Let's look at how these work.

1. Kubernetes Secrets as environment variables

When defining the pod spec, you can use the env key and indicate that the value should be pulled from a reference to the secret you created earlier and then it references the key-value pair to extract.

Step 1 - Create the pod definition file

Create a YAML file and include the following configuration in it:

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod # Name of the Pod
spec:
  containers:
  - name: redis # Name of the container
    image: redis # Docker image to use for the container
    imagePullPolicy: IfNotPresent # Pull the image if it is not already present on the node
    env:
      - name: SECRET_USERNAME # Name of the environment variable
        valueFrom:
          secretKeyRef:
            name: demo-credentials # Name of the Secret containing the value for the environment variable
            key: username # Key within the Secret that contains the value to assign to the environment variable
      - name: SECRET_PASSWORD # Name of the Secret containing the value for the environment variable
        valueFrom:
          secretKeyRef:
            name: demo-credentials
            key: password # Key within the Secret that contains the value to assign to the environment variable
  restartPolicy: Never # Restart policy for the Pod

This code will create a Pod named secret-env-pod with a Redis container. The container's environment variables, SECRET_USERNAME and SECRET_PASSWORD, will be gotten from a Kubernetes Secret named demo-credentials using the keys "username" and "password" respectively.

Step 2 - Create the pod

Run the following command to create a pod based on the definition in the configuration file:

kubectl create -f secret-env-pod.yaml

Where secret-env-pod.yaml is the configuration file. After running the command, you should get an output confirming the pod creation.

decode secret data

You can confirm that the pod is running using the kubectl get pods command.

get pods

To confirm that the environment variables have been injected into the pod, run the following command:

# Execute the 'env' command inside the 'secret-env-pod' Pod
kubectl exec secret-env-pod -- env

Running this command will list the environment variables present within the Pod's container.

list environment variables

You can see that the secrets have been added as environment variables inside the pod which can be used or accessed by the code or the application which is running.

2. Kubernetes Secret as a volume

This method works great for applications that are designed to consume sensitive information from configuration files such as Nginx reading an SSL certificate. To do this, you need to configure two things; first, you declare a volume within the pod's specification referencing the secret. Next, you create a volumeMounts within the container specification. The name of the volume in the volume mount must match the name of the volume where it was defined. and the path is where within the container file system the secret will be located. Each key in the secret will become a file containing its corresponding value.

Step 1 - Create a configuration file

Create a YAML file to include the following configuration:

apiVersion: v1
kind: Pod
metadata: 
  name: secret-volume-pod # Name of the Pod
spec:
  containers:
  - name: nginx # Name of the container
    image: nginx # Docker image to use for the container
    imagePullPolicy: IfNotPresent # Pull the image if it is not already present on the node
    volumeMounts:
    - name: secret-volume # Name of the volume to mount
      mountPath: /etc/secret # Mount path within the container
  volumes:
  - name: secret-volume # Name of the volume
    secret:
      secretName: demo-credentials # Name of the Secret to be mounted as a volume

This will create a Pod named secret-volume-pod with an nginx container. The container mounts a volume named secret-volume at the path /etc/secret.

Step 2 - Create the pod

Run the command below to create a pod based on the configuration defined.

kubectl apply -f secret-volume-pod.yaml

You should see an output indicating that the pod has been created.

secret volume pod created

Confirm if the pod is running using kubectl get pods:

get pods

To confirm that the pod now has access to the secret data, run the following commands:

# Execute an interactive shell inside the 'secret-volume-pod' Pod
kubectl exec -it secret-volume-pod -- sh

# Change directory to '/etc/secret-volume', the mountPath
cd /etc/secret-volume

# List the files and directories in the current directory
ls

The first command will open an interactive shell session within the running Pod, and the subsequent commands navigate to the /etc/secret-volume directory and list its contents. You should be able to see the secret data files.

confirm the mounted volume

With the secret inside the pod, you can have a code that can make use of the secret.

3. Using Kubernetes Secret to pull images from private Docker registries

Another way you can use Kubernetes secrets is for pulling images from private Docker repositories. In this method, the imagePullSecrets field is used to reference the secret to be used in authenticating the docker registry in the configuration file. The following steps will show you how this can be done.

Step 1 - Create a Docker-registry Secret

In your terminal, run the following code to create a docker-registry secret:

kubectl create secret docker-registry docker-secret \
--docker-server=REGISTRY_SERVER_ADDRESS \
--docker-username=USERNAME \
--docker-password=PASSWORD \
--docker-email=EMAIL

Replace REGISTRY_SERVER_ADDRESS, USERNAME, PASSWORD and EMAIL with the appropriate values specific to your docker registry configuration. This command will create a secret named docker-secret of the type docker-registry. It contains the credentials necessary to authenticate with the specified Docker registry server.

confirm the mounted volume

With the docker-registry secret created, it can be used by Kubernetes to pull private Docker images from the registry when deploying pods or other resources using the imagePullSecrets field.

Step 2 - Create a Pod Definition File

Create a YAML file and add the following configuration to it:

apiVersion: v1
kind: Pod
metadata:
  name: private-pod # Name of the pod
spec: 
  containers:
  - name: private-registry-container # Name of the container within the pod
    image: goodiec/nodeapp:v1 # Docker image to be pulled and run in the container
    ports:
      - containerPort: 3000
  imagePullSecrets:  
  - name: docker-secret # Name of the image pull secret to be used for authentication

Step 3 - Create a Pod

Execute the following command to create the pod using the configuration specified in the YAML file:

kubectl apply -f private-pod.yaml

private-pod created

You can confirm if Kubernetes was able to authenticate and pull the image from the registry using the kubectl get pods command. From the image below, you can see that the pod is running indicating that the action was successful.

check if the pod is running

You can also use the following command to get detailed information about the pod:

kubectl describe pod private-pod

The "Events" section in the output of the command will provide valuable insights into the history and status of the Pod as seen in the image below:

pod events

Good Practice when Using Kubernetes Secrets

  1. Make sure to encrypt etcd and set up RBAC (Role Based Access Control). In the Kubernetes API server, the secret is stored within etcd, the distributed key-value store containing most Kubernetes configurations. When managing your cluster, you want to ensure the data is encrypted and set up role-based access permissions to limit access to that data.

  2. Treat YAML or JSON secret configuration files as sensitive. Secrets within a YAML definition file are base64 encoded - this is not encryption and those files should be treated as sensitive, and should not be checked into a version control system.

  3. Protect the secret where it is being consumed. You also need to protect the secrets within the applications using them. For example, don't log them out or send them to an untrusted third party.

Conclusion

Throughout this guide, you've learned about Kubernetes secrets and its various types. You've also seen how to use secrets as environment variables and volumes, as well as fetch private container images from docker registries using Kubernetes secrets.

Secrets in Kubernetes are vital in securing sensitive information within applications running in your Kubernetes clusters. With this newfound knowledge, you can take advantage of what this feature offers while ensuring you follow its good practices.

Goodness is an expert in technical support, JavaScript programming, and cloud/DevOps engineering. She acquired her skills from studies in computer science and hands-on working experience. Over the years, Goodness has also honed the skills of creating, updating, and improving software documentation, writing instruction guides/manuals and technical articles for the knowledge base, and developing website content. Goodness is an expert in technical writing, DevOps engineering, Linux, Docker, containers, open-source, frontend development, and JavaScript. She also contributes to the documentation of open-source projects like Ansible and ODK-X. Goodness received her B.Sc. in Computer Science from the University of Port Harcourt and resides in Port Harcourt, Nigeria.

Cloud VPS - Cheaper Each Month

Start with $9.99 and pay $0.5 less until your price reaches $6 / month.

We use cookies to ensure seamless user experience for our website. Required cookies - technical, functional and analytical - are set automatically. Please accept the use of targeted cookies to ensure the best marketing experience for your user journey. You may revoke your consent at any time through our Cookie Policy.
build: e4941077.621