ConfigMaps in Kubernetes is a way to store and manage configuration data for your applications. Kubernetes ConfigMap allows you to decouple configuration from your application code, making it easier to manage and update configuration settings. In this article, you will learn about the ConfigMap, how to create it, how to use it, and Best Practices.
Do not store sensetive information in ConfigMaps, use Kubernetes Secrets instead.
What is ConfigMaps in Kubernetes?
ConfigMaps in Kubernetes are like storage boxes for your application’s configuration settings. They help you keep things organized by storing key-value pairs of configuration data separately from your application code. This makes it easy to manage and update settings without having to change your code every time.
ConfigMaps are powerful Kubernetes API Objects that allow you to decouple configuration artifacts from containerized applications. They provide a way to store non-sensitive configuration data in key-value pairs. Pods, containers, and other Kubernetes objects then consume it.
Here are some key points about ConfigMaps:
- Usage: Pods can consume ConfigMaps as environment variables, command-line arguments, or configuration files in a volume.
- Decoupling Configuration: By using ConfigMaps, you separate configuration data from your application code.
- No Secrecy or Encryption: Keep in mind that ConfigMaps do not provide secrecy or encryption. For confidential data, use Secrets or other tools.
- In the Kubernetes Cluster, the ConfigMaps are stored in the etcd database.
Example of ConfigMap:
First, create a file named configmap.yaml
with the following content:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
key1: value1
key2: value2
Then, create the ConfigMap using the kubectl
command:
kubectl create -f my-configmap.yaml
To view the contents of the ConfigMap, you can use the following command:
kubectl get configmap my-configmap -o yaml
Where are ConfigMaps Stored in Kubernetes?
In Kubernetes, ConfigMaps are stored as Kubernetes objects in the etcd distributed key-value database. Etcd is the primary data store used in the Kubernetes Control Plane.
When you create a ConfigMap using kubectl create configmap
or by defining it in a YAML file and applying it with kubectl apply
, the ConfigMap data is stored as a key-value pair in etcd. The key is the combination of the ConfigMap’s namespace and name, and the value is the ConfigMap’s data, including its metadata and the key-value pairs it contains.
All Kubernetes objects, including Pods, Services, Deployments, and ConfigMaps, are represented as entries in etcd. This allows the Kubernetes control plane components, such as the API server, scheduler, and controller managers, to read and modify the state of these objects as needed.
When a Pod needs to access the data from a ConfigMap, the Kubernetes API server retrieves the ConfigMap data from etcd and makes it available to the Pod. Either as environment variables or as files in a designated volume mount, depending on how the ConfigMap is consumed.
How to Create Kubernetes ConfigMaps?
There are several ways to create ConfigMaps in Kubernetes.
1. Create ConfigMap from literals with kubectl
command:
Here is an example of how to create a ConfigMap for various configs of MySQL using kubectl command. In real-world application, this is not recommended approach:
kubectl create configmap mysql-config --from-literal=MYSQL_HOST=mysql --from-literal=MYSQL_USER=root --from-literal=MYSQL_DATABASE=todo_db
2. Create ConfigMap from YAML file:
The recommended approach is to alternatively use a YAML file mysql-config.yaml with the following content:
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
data:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_DATABASE: todo_db
Then create the ConfigMap by running to create the ConfigMap named mysql-config
with the specified key-value pairs.:
kubectl apply -f mysql-config.yaml
3. Create ConfigMap from Files
Step-1: First, Create a file named mysql-config.cnf
with your desired MySQL configuration settings in your workspace. For example:
[mysqld]
innodb_buffer_pool_size = 256M
innodb_log_file_size = 50M
max_connections = 500
Step-2: Create the ConfigMap using kubectl:
kubectl create configmap mysql-config --from-file=mysql-config.cnf
Step-3: In your MySQL deployment YAML file, add a volume and volume mount to reference the ConfigMap:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-root-password
key: password
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-config-volume
mountPath: /etc/mysql/conf.d
readOnly: true
volumes:
- name: mysql-config-volume
configMap:
name: mysql-config
In this example, we’ve added a volume named mysql-config-volume
that references the mysql-config
ConfigMap. We’ve also added a volume mount to the MySQL container that mounts the ConfigMap at /etc/mysql/conf.d
. This will allow the MySQL container to read the configuration settings from the ConfigMap.
Note that the mountPath
of /etc/mysql/conf.d
is the default location where MySQL looks for additional configuration files.
4. Create ConfigMap from Directories
Step-1: We will take an example of MongoDB deployment here. Create a new directory called mongo-conf
and create the following files inside it:
# mongodb.conf
# Where and how to store data.
storage:
dbPath: /data/db
journal:
enabled: true
# Bind to local IP address only
net:
bindIp: 127.0.0.1
Also, create the Log config file.
# mongodb-log.conf
# Log file to send write audit activities
systemLog:
destination: file
path: /var/log/mongodb/mongodb.log
logAppend: true
# Log level
systemLog:
verbosity: 0
component:
accessControl:
verbosity: 0
#### Other configs #####
Step-2: Now you need to create the ConfigMpas from this directory using the following command:
kubectl create configmap mongo-config --from-file=mongo-conf/
This will create a ConfigMap named mongo-config
with the contents of the mongo.conf
and mongo-log.conf
files.
Step-3: Now, to use the ConfigMap in MongoDB deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb
spec:
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
volumes:
- name: config-mongodb
configMap:
name: mongo-config
containers:
- name: mongodb
image: mongo:4.4
ports:
- containerPort: 27017
volumeMounts:
- name: config-mongodb
mountPath: /etc/mongo
This will create a MongoDB deployment with a single replica that uses the mongo-config
ConfigMap to populate the MongoDB configuration file /etc/mongod.conf/mongo.conf
.
Note that we’ve used the subPath
field to specify the name of the configuration file within the ConfigMap.
List and inspecting ConfigMap in Kubernetes
To list and inspect ConfigMaps in Kubernetes, you can use the kubectl
command-line tool. Here are the steps:
1. List ConfigMaps:
To list all ConfigMaps in a specific namespace, use the following command:
kubectl get configmaps -n <namespace>
Replace <namespace>
with the namespace where the ConfigMaps are located. If you want to list ConfigMaps across all namespaces, omit the -n <namespace>
option.
2. Inspect ConfigMap Details:
To inspect the details of a specific ConfigMap, including its data and metadata, you can use the following command:
kubectl describe configmap <configmap-name> -n <namespace>
Replace <configmap-name>
with the name of the ConfigMap you want to inspect, and <namespace>
with the namespace where the ConfigMap is located.
Example:
Let’s say you have a ConfigMap named my-configmap
in the default
namespace. To list and inspect this ConfigMap, you would use the following commands:
# List ConfigMaps in the default namespace
kubectl get configmaps
# Inspect details of the my-configmap ConfigMap in the default namespace
kubectl describe configmap my-configmap
These commands will provide you with information about the ConfigMap, including its name, data, and metadata such as labels, annotations, creation time, and more. This information can be useful for debugging, troubleshooting, and understanding the configuration of your Kubernetes resources.
Using the ConfigMaps in Workloads:
1. Mounting ConfigMap as a volume:
I have provided a huge example here just to show you various ways in which ConfigMaps can be created. This YAML configuration defines a ConfigMap named nginx-conf with two key-value pairs under the data field:
- nginx.conf: This contains the configuration for an Nginx server.
- virtualhost.conf: This contains the configuration for a virtual host within Nginx
- The ConfigMap named
nginx-conf
is used as a volume in thenginx
container. The items specified within the ConfigMap (nginx.conf
andvirtualhost.conf
) are mounted at/etc/nginx
within the container.
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf
data:
nginx.conf: |
user nginx;
worker_processes 3;
error_log /var/log/nginx/error.log;
events {
worker_connections 10240;
}
http {
log_format main
'remote_addr:$remote_addr\t'
'time_local:$time_local\t'
'method:$request_method\t'
'uri:$request_uri\t'
'host:$host\t'
'status:$status\t'
'bytes_sent:$body_bytes_sent\t'
'referer:$http_referer\t'
'useragent:$http_user_agent\t'
'forwardedfor:$http_x_forwarded_for\t'
'request_time:$request_time';
access_log /var/log/nginx/access.log main;
include /etc/nginx/virtualhost/virtualhost.conf;
}
virtualhost.conf: |
upstream spring-petclinic {
server localhost:8080;
keepalive 1024;
}
server {
listen 80 default_server;
access_log /var/log/nginx/app.access_log main;
error_log /var/log/nginx/app.error_log;
location / {
proxy_pass http://spring-petclinic;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: spring-petclinic
image: dockerbikram/spring-petclinic:3.2.0
imagePullPolicy: Always
ports:
- containerPort: 8080
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx # mount nginx-conf volumn to /etc/nginx
readOnly: true
name: nginx-conf
- mountPath: /var/log/nginx
name: log
volumes:
- name: nginx-conf
configMap:
name: nginx-conf # place ConfigMap `nginx-conf` on /etc/nginx
items:
- key: nginx.conf
path: nginx.conf
- key: virtualhost.conf
path: virtualhost/virtualhost.conf # dig directory
- name: log
emptyDir: {}
2. Use ConfigMap as environment variables:
Here Pod uses the ConfigMap database-config
as environment variables:
apiVersion: v1
kind: ConfigMap
metadata:
name: database-config
data:
DATABASE_URL: jdbc:mysql://localhost:3306/mydatabase
DATABASE_NAME: mydatabase
---
apiVersion: v1
kind: Pod
metadata:
name: java-app-pod
spec:
containers:
- name: java-app-container
image: your-java-app-image
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: database-config
key: DATABASE_URL
- name: DATABASE_NAME
valueFrom:
configMapKeyRef:
name: database-config
key: DATABASE_NAME
3. Mounting ConfigMaps as command line arguments:
ConfigMap values can be interpolated into a container’s command line arguments as shown below.
apiVersion: v1
kind: Pod
metadata:
name: demo-pod
spec:
containers:
- name: app
command: ["demo-app", "--database-host", "$(DATABASE_HOST)"]
image: demo-app:latest
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: database-config
key: DATABASE_URL
4. Using Immutable ConfigMaps:
Immutable ConfigMaps, introduced in Kubernetes 1.19, are ConfigMaps that cannot be updated after creation. This means that once a ConfigMap is created, its data cannot be changed.
apiVersion: v1
kind: ConfigMap
metadata:
name: user-service-config
immutable: true
data:
DATABASE_URL: jdbc:mysql://db.example.com:3306/users
SERVER_PORT: "8080"
LOG_LEVEL: INFO
Updating ConfigMaps:
In Kubernetes, there are several ways to update ConfigMaps. Here are some common methods:
1. Imperative Command:
You can update a ConfigMap imperatively using the kubectl
command:
kubectl create configmap my-config --from-file=new-config.txt --dry-run=client -o yaml | kubectl apply -f -
In this command:
my-config
is the name of the ConfigMap.new-config.txt
is the file you want to use to update the ConfigMap.--dry-run=client
is used to simulate the update without making actual changes.-o yaml
is used to output the result in YAML format.| kubectl apply -f -
pipes the YAML output tokubectl apply
for applying the changes.
2. Declarative Approach (recommended):
You can update a ConfigMap declaratively by editing the YAML definition of the ConfigMap and then applying the changes using kubectl apply
:
kubectl apply -f updated-configmap.yaml
In this method, you modify the YAML file containing the ConfigMap definition directly, making the necessary changes, and then apply the updated YAML file using kubectl apply
.
3. Editing ConfigMap Directly:
You can also edit a ConfigMap directly using the kubectl edit
command:
kubectl edit configmap my-config
This command opens the ConfigMap in your default editor, allowing you to make changes directly. Once you save and exit the editor, the changes will be applied automatically.
4. Using kubectl patch
:
You can use kubectl patch
to update specific fields of a ConfigMap without having to edit the entire ConfigMap:
kubectl patch configmap my-config --patch "$(cat patch-file.yaml)"
In this command, patch-file.yaml
contains the patch to be applied to the ConfigMap.
5. Using External Tools:
There are also external tools and libraries available for managing Kubernetes resources, including ConfigMaps. Tools like Helm, Kustomize, or custom scripts can be used to update ConfigMaps in a more automated or controlled manner.
Handle Sensitive Config values – ConfigMap vs Secrets
Handling sensitive information in Kubernetes requires special consideration to maintain security and prevent unauthorized access. While ConfigMaps are suitable for storing non-sensitive configuration data, they are not designed to handle sensitive information such as passwords, API keys, or cryptographic keys. Instead, Kubernetes provides Secrets for managing sensitive data securely.
Why use Secrets over ConfigMaps for sensitive information:
- Encryption: Secrets are encrypted at rest within etcd, the key-value store used by Kubernetes to store cluster data. This provides an additional layer of security compared to ConfigMaps, which are stored in plain text.
- Base64 Encoding: Secrets automatically encode data in Base64 format, which adds a layer of obfuscation. While Base64 encoding is not encryption, it does provide a level of obscurity compared to plain text storage.
- Access Control: Kubernetes allows fine-grained access control for Secrets, enabling you to define who can create, read, update, or delete Secrets. This level of access control is essential for managing sensitive data securely.
- Use in Volume Mounts: Secrets can be mounted into containers as volumes or exposed as environment variables, making it easy to inject sensitive information into applications securely at runtime.
How to handle sensitive information in Secrets:
- Create Secrets: You can create Secrets using
kubectl
command-line tool or YAML manifests. Secrets can be created from literal values, files, or from environment variables.
kubectl create secret generic my-secret --from-literal=password=secretPassword
- Access Control: Ensure that only authorized users or service accounts have access to create, read, or modify Secrets. Use Kubernetes RBAC (Role-Based Access Control) to define appropriate permissions.
- Volume Mounts: Mount Secrets as volumes or expose them as environment variables in your Pods. Ensure that sensitive data is accessed securely within the application.
- Avoid Logging: Avoid logging sensitive information stored in Secrets. Ensure that your application’s logging configuration does not inadvertently log sensitive data.
- Regular Rotation: Periodically rotate Secrets, especially credentials and keys, to minimize the risk of exposure due to potential breaches or leaks.
By using Secrets to manage sensitive information in Kubernetes, you can ensure that your application’s security posture is robust and compliant with best practices for handling sensitive data.
Conclusion:
Kubernetes ConfigMaps provide a flexible and powerful way to manage configuration data in Kubernetes deployments. They allow you to decouple configuration from container images, making it easier to manage configurations across different environments and applications. By using ConfigMaps, you can store configuration data as key-value pairs or as files, and then mount them into your Pods as volumes or expose them as environment variables. This separation of configuration from application logic simplifies the management of configurations, promotes consistency, and facilitates the dynamic updating of configurations without the need to rebuild container images. With ConfigMaps, Kubernetes users can streamline the deployment process, enhance scalability, and improve the overall reliability of their applications.
Remember, you will use Secrets to store sentivie information like Password, Access_keys in Kubernetes.