Video Thumbnail for Lesson
4.11: Secret

Secret

Kubernetes Secrets provide a way to manage sensitive information, such as passwords, tokens, or API keys, that require more security than standard configurations. Secrets can be consumed in a similar way to ConfigMaps, either as environment variables or mounted into a pod's filesystem. One key difference is that the data in Secrets is base64 encoded, but it's important to note that this is not a security measure, just a method to support binary data. To protect secrets properly, cluster encryption policies should be considered, especially for sensitive environments, as base64 encoding alone doesn’t provide protection.

Secrets can be defined using plain text through the stringData field or directly as base64 encoded data. Kubernetes supports several types of secrets, including opaque (for arbitrary user-defined data), docker-config-json (for authenticating to private container registries), TLS (for storing certificates), and service account tokens (for granting access to cluster resources). These types allow fine-grained control over access and management, and Kubernetes provides tools like kubectl to generate and manage secrets efficiently, ensuring the right format and encoding are used for specific use cases.

Official docs: https://kubernetes.io/docs/concepts/configuration/secret/

Hands-On: Working with Secrets

Let's explore how to create and managing Secrets using practical commands.

1. Create a Namespace

First, create a namespace for these examples and set it as the default.

# task 01-create-namespace
# - Create a namespace for these examples and set as default.
kubectl apply -f Namespace.yaml
kubens 04--secret

2. Apply Secret using stringData field

Next, apply a secret using the stringData field. This method allows you to define values in plain text, which Kubernetes will automatically base64 encode.

# task 02-apply-secret-string-data
# - Apply Secret using stringData field.
kubectl apply -f Secret.string-data.yaml
apiVersion: v1
kind: Secret
metadata:
  name: string-data
type: Opaque
stringData:
  foo: bar

3. Apply Secret with Base64 Encoded Data

If you can't represent your data as a string, or you want to match the format that will be used in the cluster, you can provide the secret data already base64 encoded.

# task 06-apply-secret-base64-data
# - Apply secret using base64 encoded data.
kubectl apply -f Secret.base64-data.yaml
apiVersion: v1
kind: Secret
metadata:
  name: base64-data
type: Opaque
data:
  foo: YmFy # <- This is "bar" base64 encoded

4. Create a Docker Registry Secret

One common use case for kubernetes secrets is to store credentials to pull private container images.

It can be hard to get the syntax for this just right, so using the kubectl create command can be helpful.

# task 07-create-dockerconfigjson
# - Create a Docker registry secret.
kubectl create secret docker-registry dockerconfigjson \
  --docker-email=foo@bar.com \
  --docker-username=username \
  --docker-password=password \
  --docker-server=https://index.docker.io/v1/

This results in a secret like:

apiVersion: v1
kind: Secret
metadata:
  name: dockerconfigjson
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: |
    eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MSI6eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwicGFzc3dvcmQiOiJwYXNzd29yZCIsImVtYWlsIjoiZm9vQGJhci5jb20iLCJhdXRoIjoiZFhObGNtNWhiV1U2Y0dGemMzZHZjbVE9In19fQ==

5. Create a Pod that Consumes Secrets

With these secrets created, we can now create a pod that consumes the data from these secrets.

Like with ConfigMaps, Secrets can be consumed as environment variables as volumes.

# task 09-apply-pod
# - Apply a pod that consumes the secret.
kubectl apply -f Pod.secret-example.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-example
spec:
  containers:
    - name: nginx
      image: nginx:1.26.0
      volumeMounts:
        - name: secret-base64-data
          mountPath: /etc/config
      env:
        - name: ENV_VAR_FROM_SECRET
          valueFrom:
            secretKeyRef:
              name: base64-data
              key: foo
  imagePullSecrets:
    # Not necessary since example uses a public image, but including to show how
    # you would use a registry credential secret to access a private image
    - name: dockerconfigjson
  volumes:
    - name: secret-base64-data
      secret:
        secretName: base64-data

6. Confirm the secret data was injected at runtime

Once the pod is running we can inspect the environment variables and filesystem of the running container to confirm it worked.

# task 10-exec-printenv
# - Print the environment variables within the container.
kubectl exec secret-example -c nginx -- printenv
# task 11-exec-cat-config
# - Cat the secret file within the container.
kubectl exec secret-example -c nginx -- cat /etc/config/foo

7. Delete the Namespace to Clean Up

Finally, clean up by deleting the namespace, which will also delete all resources within it.

# task 12-delete-namespace
# - Delete the namespace to clean up.
kubectl delete -f Namespace.yaml