Many applications require configuration using some combination of configuration files, command line arguments, and environment variables. These configuration artifacts should be decoupled from image content in order to keep containerized applications portable.
The ConfigMap
object provides mechanisms to inject containers with
configuration data while keeping containers agnostic of {product-title}. A
ConfigMap
can be used to store fine-grained information like individual
properties or coarse-grained information like entire configuration files or JSON
blobs.
The ConfigMap
API object holds key-value pairs of configuration data that
can be consumed in pods or used to store configuration data for system
components such as controllers. ConfigMap
is similar to
secrets, but designed to more conveniently
support working with strings that do not contain sensitive information.
For example:
kind: ConfigMap
apiVersion: v1
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: example-config
namespace: default
data: (1)
example.property.1: hello
example.property.2: world
example.property.file: |-
property.1=value-1
property.2=value-2
property.3=value-3
-
Contains the configuration data.
Configuration data can be consumed in pods in a variety of ways. A ConfigMap
can be used to:
-
Populate the value of environment variables.
-
Set command-line arguments in a container.
-
Populate configuration files in a volume.
Both users and system components may store configuration data in a
ConfigMap
.
You can use the following command to create a ConfigMap
easily from
directories, specific files, or literal values:
$ oc create configmap <configmap_name> [options]
The following sections cover the different ways you can create a ConfigMap
.
Consider a directory with some files that already contain the data with which
you want to populate a ConfigMap
:
$ ls example-files game.properties ui.properties $ cat example-files/game.properties enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 $ cat example-files/ui.properties color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice
You can use the following command to create a ConfigMap
holding the content
of each file in this directory:
$ oc create configmap game-config \ --from-file=example-files/
When the --from-file
option points to a directory, each file directly in that
directory is used to populate a key in the ConfigMap
, where the name of the
key is the file name, and the value of the key is the content of the file.
For example, the above command creates the following ConfigMap
:
$ oc describe configmaps game-config Name: game-config Namespace: default Labels: <none> Annotations: <none> Data game.properties: 121 bytes ui.properties: 83 bytes
You can see the two keys in the map are created from the file names in the
directory specified in the command. Because the content of those keys may be
large, the output of oc describe
only shows the names of the keys and their
sizes.
If you want to see the values of the keys, you can oc get
the object with the
-o
option:
$ oc get configmaps game-config -o yaml apiVersion: v1 data: game.properties: |- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 ui.properties: | color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice kind: ConfigMap metadata: creationTimestamp: 2016-02-18T18:34:05Z name: game-config namespace: default resourceVersion: "407"- selflink: /api/v1/namespaces/default/configmaps/game-config uid: 30944725-d66e-11e5-8cd0-68f728db1985
You can also pass the --from-file
option with a specific file, and pass it
multiple times to the CLI. The following yields equivalent results to the
Creating from Directories example:
-
Create the
ConfigMap
specifying a specific file:$ oc create configmap game-config-2 \ --from-file=example-files/game.properties \ --from-file=example-files/ui.properties
-
Verify the results:
$ oc get configmaps game-config-2 -o yaml apiVersion: v1 data: game.properties: |- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 ui.properties: | color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice kind: ConfigMap metadata: creationTimestamp: 2016-02-18T18:52:05Z name: game-config-2 namespace: default resourceVersion: "516" selflink: /api/v1/namespaces/default/configmaps/game-config-2 uid: b4952dc3-d670-11e5-8cd0-68f728db1985
You can also set the key to use for an individual file with the --from-file
option by passing an expression of key=value
. For example:
-
Create the
ConfigMap
specifying a key-value pair:$ oc create configmap game-config-3 \ --from-file=game-special-key=example-files/game.properties
-
Verify the results:
$ oc get configmaps game-config-3 -o yaml apiVersion: v1 data: game-special-key: |- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 kind: ConfigMap metadata: creationTimestamp: 2016-02-18T18:54:22Z name: game-config-3 namespace: default resourceVersion: "530" selflink: /api/v1/namespaces/default/configmaps/game-config-3 uid: 05f8da22-d671-11e5-8cd0-68f728db1985
You can also supply literal values for a ConfigMap
. The --from-literal
option takes a key=value
syntax that allows literal values to be supplied
directly on the command line:
-
Create the
ConfigMap
specifying a literal value:$ oc create configmap special-config \ --from-literal=special.how=very \ --from-literal=special.type=charm
-
Verify the results:
$ oc get configmaps special-config -o yaml apiVersion: v1 data: special.how: very special.type: charm kind: ConfigMap metadata: creationTimestamp: 2016-02-18T19:14:38Z name: special-config namespace: default resourceVersion: "651" selflink: /api/v1/namespaces/default/configmaps/special-config uid: dadce046-d673-11e5-8cd0-68f728db1985
The following sections describe some uses cases when consuming ConfigMap
objects in pods.
ConfigMaps
can be used to populate individual environment variables or can populate environment variables
from all keys that form valid environment variable names. As an example, consider the following ConfigMaps
:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config (1)
namespace: default
data:
special.how: very (2)
special.type: charm (2)
-
Name of the ConfigMap.
-
Enviroment variables to inject.
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config (1)
namespace: default
data:
log_level: INFO (2)
-
Name of the ConfigMap.
-
Enviroment variable to inject.
You can consume the keys of this ConfigMap
in a pod using
configMapKeyRef
sections:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "env" ]
env: (1)
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config (2)
key: special.how (3)
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config (2)
key: special.type (3)
optional: true (4)
envFrom: (5)
- configMapRef:
name: env-config (6)
restartPolicy: Never
-
Stanza to pull the specified environment variables from a
ConfigMap
. -
Name of the
ConfigMap
to pull specific environment variables from. -
Environment variable to pull from the
ConfigMap
. -
Makes the environment variable optional. As optional, the pod will be started even if the specified
ConfigMap
and keys do not exist. -
Stanza to pull all environment variables from a
ConfigMap
. -
Name of the
ConfigMap
to pull all environment variables.
When this pod is run, its output will include the following lines:
SPECIAL_LEVEL_KEY=very log_level=INFO
A ConfigMap
can also be used to set the value of the command or arguments in
a container. This is accomplished using the Kubernetes substitution syntax
$(VAR_NAME)
. Consider the following ConfigMaps
:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
To inject values into the command line, you must consume the keys you want to
use as environment variables, as in the
Consuming in Environment
Variables use case. Then you can refer to them in a container’s command using
the $(VAR_NAME)
syntax.
apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: gcr.io/google_containers/busybox command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ] env: - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: special.how - name: SPECIAL_TYPE_KEY valueFrom: configMapKeyRef: name: special-config key: special.type restartPolicy: Never
When this pod is run, the output from the test-container container will be:
very charm
A ConfigMap
can also be consumed in volumes. Returning again to the
following example ConfigMap
:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
You have a couple different options for consuming this ConfigMap
in a
volume. The most basic way is to populate the volume with files where the key is
the file name and the content of the file is the value of the key:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "cat", "/etc/config/special.how" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
restartPolicy: Never
When this pod is run, the output will be:
very
You can also control the paths within the volume where ConfigMap
keys are
projected:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "cat", "/etc/config/path/to/special-key" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: special.how
path: path/to/special-key
restartPolicy: Never
When this pod is run, the output will be:
very
For a real-world example, you can configure Redis using a ConfigMap
. To
inject Redis with the recommended configuration for using Redis as a cache, the
Redis configuration file should contain the following:
maxmemory 2mb maxmemory-policy allkeys-lru
If your configuration file is located at example-files/redis/redis-config,
create a ConfigMap
with it:
-
Create the
ConfigMap
specifying the configuration file:$ oc create configmap example-redis-config \ --from-file=example-files/redis/redis-config
-
Verify the results:
$ oc get configmap example-redis-config -o yaml apiVersion: v1 data: redis-config: | maxmemory 2mb maxmemory-policy allkeys-lru kind: ConfigMap metadata: creationTimestamp: 2016-04-06T05:53:07Z name: example-redis-config namespace: default resourceVersion: "2985" selflink: /api/v1/namespaces/default/configmaps/example-redis-config uid: d65739c1-fbbb-11e5-8a72-68f728db1985
Now, create a pod that uses this ConfigMap
:
-
Create a pod definition like the following and save it to a file, for example redis-pod.yaml:
apiVersion: v1 kind: Pod metadata: name: redis spec: containers: - name: redis image: kubernetes/redis:v1 env: - name: MASTER value: "true" ports: - containerPort: 6379 resources: limits: cpu: "0.1" volumeMounts: - mountPath: /redis-master-data name: data - mountPath: /redis-master name: config volumes: - name: data emptyDir: {} - name: config configMap: name: example-redis-config items: - key: redis-config path: redis.conf
-
Create the pod:
$ oc create -f redis-pod.yaml
The newly-created pod has a ConfigMap
volume that places the redis-config
key of the example-redis-config ConfigMap
into a file called
redis.conf. This volume is mounted into the /redis-master directory in
the Redis container, placing our configuration file at
/redis-master/redis.conf, which is where the image looks for the Redis
configuration file for the master.
If you oc exec
into this pod and run the redis-cli
tool, you can check that
the configuration was applied correctly:
$ oc exec -it redis redis-cli 127.0.0.1:6379> CONFIG GET maxmemory 1) "maxmemory" 2) "2097152" 127.0.0.1:6379> CONFIG GET maxmemory-policy 1) "maxmemory-policy" 2) "allkeys-lru"
A ConfigMap
must be created before they are consumed in pods. Controllers
can be written to tolerate missing configuration data; consult individual
components configured via ConfigMap
on a case-by-case basis.
ConfigMap
objects reside in a project. They can only be referenced by pods
in the same project.
The Kubelet only supports use of a ConfigMap
for pods it gets from the API
server. This includes any pods created using the CLI, or indirectly from a
replication controller. It does not include pods created using the
{product-title} node’s --manifest-url
flag, its --config
flag, or its REST
API (these are not common ways to create pods).