How to K8s: Kubernetes Secrets Made Simple
Whether in production or a testing environment, sensitive information – such as SSH keys or database credentials – needs to be kept private and secure. In Kubernetes, this need is satisfied by an object called a Secret.
What is a Secret, exactly?
Secrets are Kubernetes objects that store small amounts of private information. They are created in much the same way as Pods. Although Secrets live out a very different life than that of a Pod, they are similar in the sense that they are also fundamental Kubernetes objects that can be created and torn down much like a Pod can be.
Secrets live out their lives in etcd, the central datastore for the entire Kubernetes system. This is the same central location where declarative definitions for Kubernetes Deployments live.
This centralized storage approach allows users to create one Secret that can then be consumed by any number of Pods, whether those Pods are identical copies of one another (as would be the case with a Deployment or ReplicaSet) or not. It is worth noting that you can create any number of Secrets you like, but none can exceed 1MB in size.
How do you make a Secret?
Secrets can either be defined via the kubectl CLI or manually via a YAML file.
If going the manual route, you’ll first need to encode the values that will be passed to the Secret:
$ echo -n <value_to_be_encoded> | base64</value_to_be_encoded>
For example, we can encode the word “password” like so:
$ echo -n password | base64
Then create a YAML file that defines a Secret. For example:
Notice that both our username and password values have been encoded.
And, finally, apply the Secret’s definition:
kubectl apply -f example_secret.yml
How are Secrets used?
The information Secrets house can be accessed by the code that needs it in two ways. It can either be mounted onto a Pod in the form of a Volume or set as an environment variable within the Pod.
When mounted as a Volume, the key-value pairs are expressed as files in a directory. So, if your secret information was something like:
db_creds : "some really long complex string"
Once mounted onto the Pod as a Volume at “/etc/db-creds” for example, a file named “db_creds” would be in the db-creds directory, and within that file you would find:
some really long complex string
To mount the Secret onto the Pod as a Volume, we need to define a Volume with a secretName that corresponds to our above Secret definition. We also need to define the volumeMount where the Volume will live in the Pod.
- name: db-creds
- name: chef-server
- name: db-creds
The mountPath in the Pod template is the path to the directory that will house your decoded information as one or more files named for a given key and containing the associated value. If we exec into the running Pod we would see the following:
# cd /etc/db-creds
# cat password
Something to note: The key-value pairs can also be introduced into the Pods as environment variables with only a slight change to the definition statement.
Kubernetes Secrets are a fundamental API object that stores small amounts of encrypted data, such as would be used for DB passkeys or SSH keys. This information is stored in etcd, the central datastore for Kubernetes. As such, a single Secret can be consumed by any number of Pods and, by extension, containers running therein.