Use ConfigMaps and Secrets to configure applications
Both ConfigMaps and Secrets are used to decouple application configuration from the container image. By doing so, we have greater flexibility in changing the behaviour of our applications. They can be used in two ways:
- Mounted as a
Volume - Injected as a
Environment Variable
Which to choose is largely dependent on the application and its requirements.
graph LR
%% Define the external resources
CM["<b>ConfigMap</b><br/>Non-sensitive configuration<hr/>key:value<br/>key:value"]
SEC["<b>Secret</b><br/>Sensitive data<hr/>key:value<br/>key:value"]
%% Define the Pod and its internal structure
subgraph Pod [<b>Pod</b>]
subgraph Container [<b>Application Container</b>]
direction TB
VOL["<b>Mounted Volumes</b><br/>/etc/config/<br/>/etc/secrets/"]
ENV["<b>Environment Variables</b><br/>DB_URL<br/>DB_PASSWORD"]
end
end
%% Map the connections and labels
CM -->|"Injected as Environment <br/>Variables or volume<br/>"| Container
SEC -->|"Injected as Environment <br/>Variables or volume<br/>"| Container
class CM,SEC resourceNode;
class Pod podNode;
class Container containerNode;
class VOL,ENV innerNode;
ConfigMaps are intended for general purpose application configuration - names, URL's, Application specific environment variables, etc.
Secrets are intended to store sensitive information - API keys, passwords, certificates, etc.
Both are simple key:value pairs.
Danger
By default, secrets are only base64 encoded. Meaning, cluster administrators can easily decode these secrets. For production clusters, leverage secrets encryption on your chosen platform, either be using direct integration with key vaults, or through third party solutions.
It's incredibly easy to create either of these objects using kubectl:
kubectl create configmap <map-name> <data-source>
Map-name is an arbitrary name we give to this particular configmap, and “data-source” corresponds to a key-value pair that will reside in the configmap.
kubectl create configmap vt-cm --from-literal=blog=virtualthoughts.co.uk
At which point we can then describe it:
kubectl describe configmap vt-cm
Name: vt-cm
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
blog:
----
virtualthoughts.co.uk
To reference this ConfigMap in a pod, we declare it in the respective yaml:
Configmaps can be mounted as volumes or environment variables. The below example leverages the latter.
apiVersion: v1
kind: Pod
metadata:
name: config-test-pod
spec:
containers:
- name: test-container
image: busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: BLOG_NAME
valueFrom:
configMapKeyRef:
name: vt-cm
key: blog
The pod above will output the environment variables, so we can validate it’s leveraged the config map by extracting the logs from the pod:
kubectl logs config-test-pod | grep "BLOG_NAME="
...
BLOG_NAME=virtualthoughts.co.uk
...
An example that mounts as secret as a volume:
apiVersion: v1
kind: Pod
metadata:
name: config-test-pod
spec:
containers:
- name: test-container
image: busybox
command: [ "/bin/sh", "-c", "env" ]
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: blog-name
Exam Tip
Use configMaps for general purpose key-value pairs, and secrets for sensitive information
Exam Tip
Both secrets and configMaps can be created with kubectl and can use a file as a source, ie kubectl create secret generic my-secret --from-file=path/to/bar
Exam Tip
Leverage configMaps and secrets to avoid hard-coding details inside container images (API keys, configurable variables, etc).