What are Kubernetes ConfigMaps? How to use and best practices

A Kubernetes ConfigMap is a tool to decouple configuration details from application code in a cluster. By centralizing configuration data it enhances application portability, enforces the DRY (Don’t Repeat Yourself) principle, and simplifies deployments.

In this article, we will take a deep dive into the world of ConfigMaps. We will explore their purpose and use cases, learn how to create and manage them and discuss some best practices that every Kubernetes user should know.

What are ConfigMaps in Kubernetes?

ConfigMaps are configuration abstractions in Kubernetes clusters that separate the configuration parameters from the application itself. They are a set of key-value pairs that can be used to configure application logic without having to restart pods.

A ConfigMap can hold a wide range of data, from environment variables and command-line arguments to full-fledged configuration files. For example, suppose you have an environment variable by the name “PRODUCT_TYPE” that is used by applications to conditionally implement product-specific logic. Instead of making this variable a part of the source code of all applications, you can define it inside a single ConfigMap object and make the object accessible wherever needed.

A peek inside a ConfigMap object

A ConfigMap object is a structured API object in Kubernetes that consists of two primary fields:

  • data: This field holds key-value pairs of configuration data, with keys being alphanumeric strings and values being UTF-8 encoded strings.
  • binaryData: Similar to the data field, this field stores key-value pairs but as Base64-encoded binary data.

For a better understanding, let’s look at a sample ConfigMap object:

        apiVersion: v1 
kind: ConfigMap

metadata:
name: my-config-map
data:
app_name: MyApp
app_version: 1.0.0
database_host: localhost
database_port: 3306
logging_level: INFO
binaryData:
some-binary-info: L2R0YW5zL2NlcnRpZmljYXRlLnJlZg==

In the above ConfigMap, we are storing information related to the database host and port, application name, and logging level inside the data field. We are also storing some arbitrary, non-sensitive binary information inside the binaryData field.

Together, these fields offer a flexible mechanism to store a wide range of configurations in a standardized format.

Note: keys stored in the two fields must never overlap.

Why use ConfigMaps?

There are several advantages to using ConfigMaps in Kubernetes:

Decoupled, centralized configurations

ConfigMaps reduce the clutter of configuration parameters from your source code, which leads to better readability and maintainability.

For example, instead of hard-coding parameters for different use cases, like databases, threads, and API gateways in your code, you can create dedicated ConfigMaps and read values from there.

Simplified deployments

By externalizing configuration data to ConfigMaps, you can avoid the need to rebuild container images whenever configuration changes are required. This streamlines the deployment processes, boosts agility, and reduces downtime associated with image updates.

For example, suppose you have a microservices architecture in which each microservice needs specific configurations, including API endpoints, feature toggles, and database connection details. If you use ConfigMaps, you can dynamically update any of these configurations without disrupting the running pods. Conversely, if these settings were embedded within the application code, you’d have to rebuild and redeploy your images.

Enhanced manageability

ConfigMaps offer a centralized and structured approach to managing configuration data. This makes it easier to track changes, apply updates, and maintain consistency across the cluster.

For instance, if you have a large-scale cluster, it would be difficult to track configuration changes across all pods without ConfigMaps. However, if you use ConfigMaps, you can seamlessly manage configurations from a central place.

Improved portability

When you consolidate configuration parameters using ConfigMaps, your applications become more portable across different environments. This is especially valuable when deploying applications in multiple stages, including development, testing, and production.

For example, you can tweak ConfigMap parameters on the fly to adapt your application’s behavior when moving between development, testing, and production environments.

Scalability

ConfigMaps can be effectively scaled to accommodate evolving business needs without overcomplicating the source code or slowing down the cluster.

For example, you can finetune performance parameters of an application (such as number of threads or connections) on the fly to cater to a sudden traffic surge.

When and when not to use ConfigMaps

ConfigMaps are a great way to manage configurations in a Kubernetes cluster but they are not always the best choice. Here are a few guidelines for when to use and when to avoid them.

Use ConfigMaps for:

  • Storing non-confidential configuration data that is frequently updated.
  • Storing parameters that will be accessed by several pods.
  • Storing configurations that vary across different environments, products, or deployments.
  • Storing application parameters including hostnames, logging settings, and number of threads.

Don’t use ConfigMaps for:

  • Storing sensitive data, includingpasswords, API keys, or certificates.
  • Storing large chunks of data like images or log files. A ConfigMap object can only store up to 1 Mebibyte (MiB) of data.
  • Storing data that needs to be encrypted, as ConfigMaps don’t provide encryption.
  • Storing data that will be accessed from outside the cluster. ConfigMaps are primarily designed for internal use (within the cluster).

ConfigMaps vs. Secrets in Kubernetes

Secrets, like ConfigMaps, provide a way to store data centrally, but their main purpose is to safeguard sensitive data, including passwords, encryption keys, and certificates. Unlike ConfigMaps, Secrets allow you to encrypt data both at rest and in transit.

Moreover, Secrets are only accessible to pods that have been explicitly granted access. This ensures compliance with the principle of least privilege. Conversely, by default, ConfigMaps can be accessed by all pods within the same namespace.

To summarize, use Secrets to manage security-critical data.se ConfigMaps for everything else.

Creating ConfigMaps in Kubernetes (4 ways)

Kubernetes offers different ways to create ConfigMaps.

Creating ConfigMaps from files

One of the simplest ways to create a ConfigMap is by using a configuration file. Kubernetes allows you to automatically parse the key-value pairs from the file into the ConfigMap data structure.


kubectl create configmap my-configmap --from-file=config.yaml

The above command will create a ConfigMap with the name my-configmap. You can also use multiple files to create a ConfigMap. Simply repeat the “--from-file” argument for each file:


kubectl create configmap my-configmap --from-file=config.yaml --from-
file=config2.yaml

Creating ConfigMaps from literals

If you have a limited number of key-value pairs you can also create a ConfigMap by passing literal strings to the kubectl command. Here’s an example:


kubectl create configmap my-config-map --from-literal=sample.name=value1 --
from-literal=sample.type=dummy

Creating ConfigMaps from directories

If you have a directory with multiple configuration files, you can create a ConfigMap by specifying the directory path. Kubernetes will process each file in the directory and extract the key-value pairs.


kubectl create configmap my-config-map --from-file=path/to/config/directory

The above command processes all the configuration files present in the specified path.

Creating ConfigMaps with generators

You can also leverage generators to dynamically create ConfigMaps from files, directories, or even key-value pairs. Generators are especially helpful when you want to automate complex deployment scenarios.

For example, if you want to generate a ConfigMap from files, you can define a Kustomization.yaml file as follows:


configMapGenerator:
- name: sample-config-1
options:
labels:
sample-config: config-1
files:
- setup-sample-pod-container/configurations/sample.properties

Save the file and then run the following command in the same directory to generate the ConfigMap:


kubectl apply -k .

Viewing ConfigMaps data

To view the contents of a ConfigMap, you can use the kubectl get and kubectl describe commands. For example, to get a list of all ConfigMaps, across all namespaces, you can use this command:


kubectl get configmaps --all-namespaces

To get all the ConfigMaps in a specific namespace:


kubectl get configmaps -n <namespace>

To display the data of a specific ConfigMap, you can use the following command:


kubectl get configmaps my-config-map -o yaml

This command fetches the ConfigMap named “my-config-map” and outputs its data in YAML format. A sample output can be:


apiVersion: v1
kind: ConfigMap

metadata:
creationTimestamp: 2023-03-11T12:32:02Z
name: app-config
namespace: my-namespace
resourceVersion: "321"
uid: a1234ad7-c457-22a2-4bc2-24a432ad2347

data:
app.properties: |
product=xyz
min_threads=2
tls=true
max_threads=10
daemon_threads=false
connection_pool=true
deployment=test

  log.properties: |
verbosity=high
console=false
location=/var/log/app
level=error

If you want more detailed information about a ConfigMap, you should use the kubectl describe command. Consider an example:


kubectl describe configmap my-config-map

This command will display additional information about the configMap, including its metadata. A sample output can be:


Name: app-config
Namespace: my-namespace
Labels: <none>
Annotations: <none>

Data
====
app.properties:
----
product=xyz
min_threads=2
tls=true
max_threads=10
daemon_threads=false
connection_pool=true
deployment=test

log.properties:
----
verbosity=high
console=false
location=/var/log/app
level=error

Events: <none>

ConfigMaps and pods

To integrate a ConfigMap into a pod, we will have to update the pod’s specification. Let’s consider an example:

      
apiVersion: v1
kind: Pod
metadata: name: my-app-pod
spec: containers:
- name: my-app-container
image: my-custom-image
command: [ "/bin/sh", "-c", "my-command" ]
env:
- name: MY_SPECIAL_VARIABLE
valueFrom: configMapKeyRef:
name: my-configmap
key: special_value
restartPolicy: OnFailure

In the above pod specification, we are creating a container named “my-app-container”. Inside the “env” section, we add an environment variable “MY_SPECIAL_VARIABLE” whose value is retrieved from a ConfigMap named “my-configmap”. The key of the variable inside the ConfigMap is “special_value”.

This is one of the easiest ways to reference a ConfigMap inside a pod specification. In the next sections, we will explore more advanced use cases.

Loading environment variables from multiple ConfigMaps

As your Kubernetes environment expands, you may need to distribute your configuration data across multiple ConfigMaps. Fortunately, Kubernetes allows you to load values from multiple ConfigMaps within the same pod specification.

      
apiVersion: v1
kind: Pod
metadata: name: my-app-pod
spec: containers:
- name: app-container
image: my-app-image
command: [ "/bin/sh", "-c", "my-command" ]
env:
- name: DATABASE_HOST
valueFrom: configMapKeyRef:
name: databaseConfigMap
key: database_host
- name: KONG_IP
valueFrom: configMapKeyRef:
name: GatewayConfigMap
key: kong_ip
restartPolicy: OnFailure

In the above specification, we are reading “DATABASE_HOST” from the “databaseConfigMap” configMap, and “KONG_IP” from the “GatewayConfigMap”.

Using ConfigMap variables inside pod commands

Sometimes you may need to use a ConfigMap variable as part of the container’s command or entry point. This is especially relevant if you store command line arguments for your applications inside a ConfigMap. Let’s consider an example:

      
apiVersion: v1
kind: Pod
metadata: name: my-app-pod
spec: containers:
- name: app-container
image: my-app-image
command: ["/bin/sh", "-c", "my-app-binary --minimum-threads=$(NUMBER_OF_THREADS)"]
env:
- name: NUMBER_OF_THREADS
valueFrom: configMapKeyRef:
name: app-config
key: number_of_threads
restartPolicy: OnFailure

In this pod specification, we are loading the “NUMBER_OF_THREADS” variable from a configMap and then also passing it to the command (entry point) of our container.

Using multiple ConfigMap variables and adding ConfigMap data to volumes

Now let’s consider an advanced use case: you want to load multiple environment variables from a ConfigMap and you want to mount ConfigMap data as files inside a container volume. Here’s how the pod specification will look:

      
apiVersion: v1
kind: Pod
metadata: name: my-configmap-pod
spec: containers:
- name: my-app
image: my-custom-image
command: ["my-command"]
env:
#name of the variable we want to read
- name: CUSTOM_ENV_VARIABLE
valueFrom: configMapKeyRef:
name: my-configmap #name of the configMap from which we will be reading the value
key: custom_env_variable #the key we will be reading
- name: DATABASE_URL
valueFrom: configMapKeyRef:
name: my-configmap
key: database_url
volumeMounts:
- name: config-volume
mountPath: "/config"
readOnly: true
volumes:
- name: config-volume
configMap:
name: my-configmap
items:
- key: "app.properties"
path: "app.properties"
- key: "logging.properties"
path: "logging.properties"

Inside the env section of the specification, we define the two environment variables we want to pass to the container: “CUSTOM_ENV_VARIABLE” and “DATABASE_URL”.

For both of these variables, we are retrieving values from a ConfigMap named “my-configmap”. Inside the “volumeMounts” section, we are mounting the ConfigMap as a volume inside the container, at the path “/config”.

Finally, inside the “volumes” section, we define a volume named “config-volume” based on “my-configmap”. We are extracting “app.properties” and “logging.properties” from the configMap and mounting them to the “/config” path of the container.

ConfigMaps best practices

To ensure effective utilization and seamless management of configurations, it’s important to adhere to some best practices that promote organization, security, and data integrity.

Naming conventions

Like with any other asset in software development, it’s important to follow consistent naming conventions for your ConfigMaps. Consistency fosters predictability, which makes it easier for you and your teammates to understand and locate specific configurations.

For example, adopting a template like "XYZ-config" for ConfigMap names, where "XYZ" represents the type of stored configurations, brings clarity. For database configurations, you might use "db-config", and for application configurations, you might use "app-config".

Using namespaces for proper organization

Don’t create ConfigMaps in the default (global) namespace. Instead, allocate them to specific namespaces. This is especially important to do in multi-tenant or complex environments, as it ensures that ConfigMaps are grouped according to their applications or functionalities. For example, you may assign namespaces to differentiate between development, staging, and production environments.

Never store security-critical data in ConfigMaps

It may seem convenient to store sensitive data in ConfigMaps along with the rest of the configuration parameters, but doing so can expose you to security risks. ConfigMaps are not designed to store security-critical data, and therefore lack even basic security features like encryption at rest. For safe storage of sensitive data, it’s recommended to use Kubernetes Secrets.

Leverage role-based access control (RBAC)

To adhere to the principle of least privilege, use Kubernetes RBAC to restrict access to ConfigMaps. Only grant necessary permissions to pods that require access. This reduces the risk of unauthorized modifications.

Leveraging immutable ConfigMaps

In Kubernetes, making a ConfigMap immutable is straightforward. Just set the “immutable” flag to true in the ConfigMap specification. Immutability not only ensures the consistency of configuration state over time, but also boosts the performance of the cluster (as the kube-apiserver doesn’t have to watch immutable ConfigMaps for changes).

Use appropriate versioning

Consider versioning ConfigMaps — i.e. creating new instances when updates are required. Consistent versioning allows for controlled changes and makes it easier to roll back in case a specific version has any issues.

Limiting the size of ConfigMaps

The official Kubernetes documentation advises against storing extensive amounts of information in ConfigMaps. If you have to store large files (greater than 1 MiB), use alternatives like Persistent Volumes.

As a golden rule, keep ConfigMaps focused on a specific set of configurations to avoid unnecessary complexity and bloat. Avoid the temptation to put unrelated configurations in a single ConfigMap, as this can lead to confusion and errors.

Use automation to keep ConfigMaps up to date

Leveraging automation can ensure that your ConfigMaps remain up to date. For example, you can integrate ConfigMap updates into your CI/CD pipeline. This will ensure that all changes are automatically applied during deployments, reducing the need for manual intervention.

You can also develop automation scripts to streamline common ConfigMap management tasks. These scripts can automate the creation, update, deletion, or application of ConfigMaps, reducing the chances of human error.

Monitor for unexpected changes to ConfigMaps

Leverage monitoring tools that can track changes to ConfigMaps and alert administrators when unexpected changes or unauthorized access is detected. A great choice for this purpose is Site24x7’s comprehensive Kubernetes monitoring tool. Following a proactive approach ensures that any potential security or configuration issues are addressed promptly.

Conclusion

ConfigMaps offer a flexible and standardized method for configuring and managing Kubernetes clusters. Whether you want to inject environment variables to containers, mount configuration files as volumes, or pass command-line arguments to your applications, you can use Kubernetes ConfigMaps to do so.

Was this article helpful?

Related Articles

Write For Us

Write for Site24x7 is a special writing program that supports writers who create content for Site24x7 "Learn" portal. Get paid for your writing.

Write For Us

Write for Site24x7 is a special writing program that supports writers who create content for Site24x7 “Learn” portal. Get paid for your writing.

Apply Now
Write For Us