Kubernetes Secrets

A Secret is a Kubernetes object that encapsulates sensitive data such as a password or key. A Secret can be consumed by a container so that applications can access the sensitive data at runtime.

Defining a Secret

A sample Secret definition is shown below.

apiVersion: v1
kind: Secret
metadata:
  name: sample-secret
#stringData:
  #databasePassword: password11
data:
  databasePassword: cGFzc3dvcmQxMQ==

The Secret value can be set as either a plain string or a Base64 encoded string. The example above uses the data attribute with a Base64 encoded value for the key databasePassword. Base64 encoding is useful if you want to specify binary data such as a certificate. Note: base64 encoded values are not secure. Although Base64 encoding mildly obscures a value, in terms of security it’s essentially plain text. If you don’t want to use Base64 encoding you can specify the Secret value using stringData instead.

Consuming a Secret as an Environment Variable

A Secret can be consumed by a container as an environment variable or as a volume. The Pod example below shows the Secret created earlier being consumed as an environment variable.

apiVersion: v1
kind: Pod
metadata:
  name: sample-secret-env-var-pod
spec:
  containers:
    - name: sample-secret-env-var-pod
      image: busybox
      command: [ 'sh', '-c', 'echo Database Password: $DATABASE_PASSWORD & sleep 3600' ]
      env:
        - name: DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: sample-secret
              key: databasePassword

In env you specify the name that will be used by the container to reference the environment variable. valueFrom indicates where the env variable will be sourced from. In this example we use secretKeyRef to tell Kubernetes we want to reference a Secret object by the name of sample-secret. The key: databasePassword references the key we defined in the Secret earlier.

Consuming a Secret as Volume

The Pod definition below consumes the Secret using a volume.

apiVersion: v1
kind: Pod
metadata:
  name: sample-secret-volume-pod
spec:
  volumes:
    - name: secret-volume
      secret:
        secretName: sample-secret
  containers:
    - name: sample-secret-volume-pod
      image: busybox
      command: [ 'sh', '-c', 'echo Database Password from Volume: $(cat /var/my-secret/databasePassword) & sleep 3600' ]
      volumeMounts:
       - name: secret-volume
         mountPath: /var/my-secret

Inside the Pod spec a Volume is defined called secret-volume. Line 8 tells Kubernetes this Volume exposes a Secret and line 9 provides the Secret name.

Inside the container definition we specify a volume mount to reference the Secret volume created above. The name of the VolumeMount matches the Volume name used above. mountPath is the directory where the mounted Secret will be available to the container.

Kubernetes creates a file at the mountPath where the file name is the Secret key databasePassword we defined earlier. To access the Secret value we simply read this file. We do exactly this on line 13 where we echo out the contents of databasePassword.

We can exec into the running container and see the databasePasword file.

The sample code for these notes is available here.