Understanding Basic Kubernetes Concepts IV - Secrets and ConfigMaps
This post is the fourth in a series of blog posts about basic Kubernetes concepts. In the first one I explained the concepts of Pods, Labels, and Replica Sets. In the second post we talked about Deployments. The third post explained the Services concept and now we will look at Secrets and ConfigMaps. In the fifth and final post we talk about Daemon Sets and Jobs.
The third factor of the 12 factor app methodology is called Config and describes why you should store configuration in the environment. This is based on the fact that an application's configuration can change between environments (e.g. development, staging, production, etc.) and that you want your applications to be portable. Thus, you should store the config outside of the application itself.
Now with Docker and containers this means we should try to keep configuration out of the container image. This is even more needed when working with sensitive information, such as passwords, keys, auth tokens, because we might not want them to be available in a registry, even if that registry might be private.
In Docker we would use
--env-file for this no matter if we are working with sensitive information or just plain configuration.
In Kubernetes we have two separate primitives for these use cases. The first is Secrets, which as the name suggest is for storing sensitive information. The second one is ConfigMaps, which you can use for storing general configuration. The two are quite similar in usage and support a variety of use cases.
Secrets can (and should) be used for storing small amounts (less than 1MB each) of sensitive information like passwords, keys, tokens, etc. Kubernetes creates and uses some secrets automatically (e.g. for accessing the API from a pod), but you can also create your own easily.
Using secrets is quite straightforward. You reference them in a pod and can then use them either as files from volumes or as environment variables in your pod. Keep in mind that each container in your pod that needs to access the secret needs to request it explicitly. There's no implicit sharing of secrets inside the pod.
There's also a special type of secret called
imagePullSecrets. Using these you can pass a Docker (or other) container image registry login to the Kubelet, so it can pull a private image for your pod.
When updating secrets that are used by already running pods you need to be careful, as running pods won't automatically pull the updated secret. You need to explicitly update your pods (for example using the rolling update functionality of deployments explained in the second blog post in this series).
Further keep in mind that you create a secret in a specific namespace and only pods in the same namespace can access the secret.
Secrets are kept in a tmpfs and only on nodes that run pods that use those secrets. The tmpfs keeps secrets from coming to rest on the node. However, they are transmitted to and from the API server in plain text, thus, be sure to have SSL/TLS protected connections between user and API server, but also between API server and Kubelets (Giant Swarm clusters do come with both enabled by default).
ConfigMaps are similar to Secrets, only that they are designed to more conveniently support working with strings that do not contain sensitive information. They can be used to store individual properties in form of key-value pairs. However, the values can also be entire config files or JSON blobs to store more information.
This configuration data can then be used as:
- Environment variables
- Command-line arguments for a container
- Config files in a volume
Good use cases for ConfigMaps are for example storing config files for tools like redis or prometheus. This way you can change the configuration of these without having to rebuild the container.
A difference to the secrets concept is that ConfigMaps actually get updated without the need to restart the pods that use them. However, depending on how you use the configs provided you might need to reload the configs, e.g. with an API call to prometheus to reload.
Towards more portable containers
Once, you're using Secrets and ConfigMaps, it's easy to differentiate between environments like dev, test, and prod. You can just use different secrets and configs to configure your containers for the respective environment.
These two concepts also make your containers more versatile in that they keep out some of the specifics and let different users deploy them in different ways. Thus, you can foster better re-use between teams or even outside of your organization.
Secrets (and in some use cases also ConfigMaps) are especially helpful when sharing with other teams and organizations or even more when sharing publicly. You can freely share your images (and manifests), maybe even keep them in a public repository, without having to worry about any company-specific or sensitive data being published.