community/contributors/design-proposals/node/envvar-configmap.md

185 lines
4.7 KiB
Markdown

# 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.