# ConfigMaps as environment variables ## Goal Populating environment variables of a container from an entire ConfigMap. ## Design Points A container can specify a set of existing ConfigMaps to populate environment variables. There needs to be an easy way to isolate the variables introduced by a given ConfigMap. The contents of a ConfigMap may not be known in advance and it may be generated by someone or something else. Services may provide binding information via a ConfigMap. If you have a common service with multiple instances like a Message Queue or Database, there needs to be a way to uniquely identify and prevent collision when consuming multiple ConfigMaps in a single container using this feature. ## Proposed Design Containers can specify a set of sources that are consumed as environment variables. One such source is a ConfigMap. Each key defined in the ConfigMap's `Data` object must be a "C" identifier. If an invalid key is present, the container will fail to start. Environment variables defined by a `Container` are processed in a specific order. The processing order is as follows: 1. All automatic service environment variables 1. All `EnvFrom` blocks in order 1. All `Env` blocks in order. The last value processed for any given environment variable will be the decided winner. Variable references defined by an `EnvVar` struct will be resolved by the current values defined even if the value is replaced later. To prevent collisions amongst multiple ConfigMaps, each defined ConfigMap can have an optional associated prefix that is prepended to each key in the ConfigMap. Prefixes must be a "C" identifier. ### Kubectl updates The `describe` command will display the configmap name that have been defined as part of the environment variable section including the optional prefix when defined. ### API Resource A new `EnvFromSource` type containing a `ConfigMapRef` will be added to the `Container` struct. ```go // EnvFromSource represents the source of a set of ConfigMaps type EnvFromSource struct { // A string to place in front of every key. Must be a C_IDENTIFIER. // +optional Prefix string `json:"prefix,omitempty"` // The ConfigMap to select from ConfigMapRef *LocalObjectReference `json:"configMapRef,omitempty"` } type Container struct { // List of sources to populate environment variables in the container. // The keys defined within a source must be a C_IDENTIFIER. An invalid key // will prevent the container from starting. When a key exists in multiple // sources, the value associated with the last source will take precedence. // Values defined by an Env with a duplicate key will take precedence over // any listed source. // Cannot be updated. // +optional EnvFrom []EnvFromSource `json:"envFrom,omitempty"` } ``` ### Examples ### Consuming `ConfigMap` as Environment Variables ```yaml apiVersion: v1 kind: ConfigMap metadata: name: etcd-env-config data: number_of_members: "1" initial_cluster_state: new initial_cluster_token: DUMMY_ETCD_INITIAL_CLUSTER_TOKEN discovery_token: DUMMY_ETCD_DISCOVERY_TOKEN discovery_url: http://etcd_discovery:2379 etcdctl_peers: http://etcd:2379 duplicate_key: FROM_CONFIG_MAP REPLACE_ME: "a value" ``` This pod consumes the entire `ConfigMap` as environment variables: ```yaml apiVersion: v1 kind: Pod metadata: name: config-env-example spec: containers: - name: etcd image: openshift/etcd-20-centos7 ports: - containerPort: 2379 protocol: TCP - containerPort: 2380 protocol: TCP env: - name: duplicate_key value: FROM_ENV - name: expansion value: $(REPLACE_ME) envFrom: - configMapRef: name: etcd-env-config ``` The resulting environment variables will be: ``` number_of_members="1" initial_cluster_state="new" initial_cluster_token="DUMMY_ETCD_INITIAL_CLUSTER_TOKEN" discovery_token="DUMMY_ETCD_DISCOVERY_TOKEN" discovery_url="http://etcd_discovery:2379" etcdctl_peers="http://etcd:2379" duplicate_key="FROM_ENV" expansion="a value" REPLACE_ME="a value" ``` ### Consuming multiple `ConfigMap` as Environment Variables ```yaml apiVersion: v1 kind: ConfigMap metadata: name: env-config data: key1: a key2: b ``` This pod consumes the entire `ConfigMap` as environment variables: ```yaml apiVersion: v1 kind: Pod metadata: name: config-env-example spec: containers: - name: etcd image: openshift/etcd-20-centos7 ports: - containerPort: 2379 protocol: TCP - containerPort: 2380 protocol: TCP envFrom: - prefix: cm1_ configMapRef: name: env-config - prefix: cm2_ configMapRef: name: env-config ``` The resulting environment variables will be: ``` cm1_key1="a" cm1_key2="b" cm2_key1="a" cm2_key2="b" ``` ### Future Add similar support for Secrets. [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/proposals/envvar-configmap.md?pixel)]()