Table of contents
Introduction
Configuration⚙️ is essential for any application to function properly. Any data that controls or influences how an application works can be considered configuration. Before jumping to ConfigMaps and Secrets let's understand something about environment variables.
Environment variables are name-value pairs that are stored and used by the operating system. They contain various information that programs need to run properly. Most commonly they are used for storing configuration settings, passing credentials & controlling program behavior
We know about the ENV variables in Docker - they are set using the ENV instruction in a Dockerfile or using the -e flag when running a container which can be used to configure applications inside Docker containers. For example, in a Dockerfile you can do:
ENV MY_VARIABLE=some_value
ENV PORT=80
Then when running the container you can override PORT:
docker run -e PORT=8080 my_image
env in Kubernetes
Just like the Dockerfile, you can specify environment variables directly in your Kubernetes Deployment YAML file. This means each deployment can get a customized environment. Let's see an example below. The environment variables will be passed to all Nginx containers started by this deployment.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
env:
- name: LANG
value: "English"
- name: API_URL
value: "http://localhost:5000/deploy"
One major shortfall is that the environment variables are tied to the specific container or deployment. This makes it inflexible in several ways.
Kubernetes ConfigMaps and Secrets are two ways to inject configuration data into your Pods and Containers. ConfigMaps allows you to separate configuration artifacts from image content to keep containerized applications portable. Secrets work similarly to ConfigMaps but are specifically meant to hold sensitive information like passwords, keys, and tokens.💁♂️Let's understand more about each of them
ConfigMaps
ConfigMaps allows you to store configuration data in a key-value pair format and expose those variables as environment variables to your Containers.
Some common use cases for ConfigMaps are:
Storing configuration data for applications running in Containers
Storing configuration data for templating Pod definitions
Storing database credentials, API keys, passwords, etc.
Use the kubectl create configmap
command to create ConfigMaps from directories, files, or literal values:
kubectl create configmap <map-name> <data-source>
You can write a ConfigMap .yaml file like this:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: INFO
PORT: "8080"
Then you can mount the ConfigMap as an environment variable in a Pod like this:
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
Or mount it as a volume in a Pod and access the data as files:
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config
You can pass in the --from-file
argument multiple times to create a ConfigMap from multiple data sources.
You can use the following command to create a ConfigMap from an individual file, or from multiple files.
For example,
kubectl create configmap <name> --from-file=SOME_PATH/.properties
which would produce the following ConfigMapYou can display details of the ConfigMap using the following command:
kubectl describe configmap app-config
Output:
When a ConfigMap currently consumed in a volume is updated, projected keys are eventually updated as well. The kubelet checks whether the mounted ConfigMap is fresh on every periodic sync.
You can get more detailed information on all this here:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
The Kubernetes feature Immutable Secrets and ConfigMaps provides an option to set individual Secrets and ConfigMaps as immutable. You can create an immutable ConfigMap by setting the immutable
field to true
. For example:
apiVersion: v1
kind: ConfigMap
metadata:
...
data:
...
immutable: true
Secrets
Secrets allow you to store and manage sensitive information like passwords, OAuth tokens, and SSH keys.
They work similarly to ConfigMaps, but have some differences:
Secrets are stored as base64 encoded strings
Only root and kubelet service accounts have permission to read Secret objects by default
Secrets are mounted as volumes or environment variables in Pods the same way as ConfigMaps
You can create a Secret like this:
apiVersion: v1
kind: Secret
metadata:
name: mysql-pass
type: Opaque
data:
password: cGFzc3dvcmQ=
Get the output as follows from this command kubectl get secret
or use the command to create from literals
kubectl create secret generic apikey --from-literal=API_KEY=123–456
Here is a YAML file to deploy Nginx using ConfigMaps and Secrets:
# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
log_level: INFO
index.html: |
<h1>Hello from Nginx!</h1>
# Secret
apiVersion: v1
kind: Secret
metadata:
name: nginx-secret
data:
username: YWRtaW4=
password: cGFzc3dvcmQxMjM=
# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
envFrom:
- configMapRef:
name: nginx-config
- secretRef:
name: nginx-secret
ports:
- containerPort: 80
This does the following:
Defines a ConfigMap called
nginx-config
with two keys:log_level
andindex.html
Defines a Secret called
nginx-secret
withusername
andpassword
In the Deployment:
It uses
envFrom
to populate environment variables from the ConfigMap and SecretThe Nginx container will have:
LOG_LEVEL
env var fromlog_level
key in ConfigMapUSERNAME
andPASSWORD
env vars from Secret
The main benefits are:
Easy updates - You can update the ConfigMap/Secret without modifying the Deployment
Separation of configuration - Configuration is not baked into the image
Conclusion
To conclude, The big difference between Secrets and ConfigMaps is that Secrets are obfuscated with a Base64 encoding. Since configurations are decoupled from container images, it's easier to troubleshoot configuration-related issues. It helps make applications deployed to Kubernetes more cloud-native and manageable at scale.
Thanks for reading! See you all in the next blog 🙂