很多应用程序需要一些配置通过组合的配置文件,命令行参数和环境变量。这些配置应该与镜像内容分离以保持容器化应用程序的可移植性。ConfigMap API资源提供了将配置数据注入容器的机制,同时保持容器不受kubernetes的影响。ConfigMap可用于存储细粒度信息如单个属性,或粗粒度信息如整个配置文件或JSON对象。
ConfigMap概述
ConfigMap API资源保存配置数据的键值对,可以在pods中使用或者可以用于存储系统组件的配置数据。ConfigMap类似于Secrets,但是旨在更方便的使用不包含敏感信息的字符串。
注意:ConfigMap不打算充当属性文件的替换者。你可以认为类似于/etc目录,以及Linux计算机上的文件。一个例子是从ConfigMap创建一个Kubernetes卷,其中ConfigMap的数据项变成一个新的文件。
例如下面的例子:
kind: ConfigMap
apiVersion: v1
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: example-config
namespace: default
data:
example.property.1: hello
example.property.2: world
example.property.file: |-
property.1=value-1
property.2=value-2
property.3=value-3
data字段包含配置信息。可以看到ConfigMap可以用于细粒度的单个属性,或者是配置文件的内容。
配置数据在pods中有多种使用方式。ConfigMap有以下几种使用方式:
1.填充环境变量的值
2.设置容器内的命令行参数
3.填充卷的配置文件
用户和系统组建都可以在ConfigMap中存储配置数据。
新建ConfigMap
可以使用kubectl create configmap
命令行非常容易的从字面值,文件或目录中创建configmaps。
让我们尝试用不同的方式创建一个ConfigMap:
从目录创建
比如说我们有一个目录其中包含一些已经已经包含要填充ConfigMap数据的文件:
$ ls docs/user-guide/configmap/kubectl/
game.properties
ui.properties
$ cat docs/user-guide/configmap/kubectl/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 docs/user-guide/configmap/kubectl/ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
kubectl create configmap
可用于创建一个保存此目录中每个文件内容的ConfigMap:
$ kubectl create configmap game-config --from-file=docs/user-guide/configmap/kubectl
当 --from-file指向一个目录,每个目录中的文件直接用于填充ConfigMap中的key,key的名称是文件名称,key的值是这个文件的内容。让我们看看上面命令创建的ConfigMap:
$ kubectl describe configmaps game-config
Name: game-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties: 158 bytes
ui.properties: 83 bytes
可以看到map中的两个key是从我们指向的kubectl的目录中的文件名创建的。因为这些建的内容可能很大,kubectl describe
你只能看到他们key的名称和大小。如果想看这些key的值,可以通过kubectl get
获取:
$ kubectl 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
从文件创建
也可以通过--from-file指定文件,并将他多次传递给kubectc。下面的命令和上面的示例产生相同的结果:
$ kubectl create configmap game-config-2 --from-file=docs/user-guide/configmap/kubectl/game.properties --from-file=docs/user-guide/configmap/kubectl/ui.properties
$ kubectl 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
我们可以通过key=value表达式为每个文件设置key:
--from-file=game-special-key=docs/user-guide/configmap/kubectl/game.properties
:
$ kubectl create configmap game-config-3 --from-file=game-special-key=docs/user-guide/configmap/kubectl/game.properties
$ kubectl 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
通过字面值创建
也可以通过kubectl create configmap
创建ConfigMap使用字面值。--from-literal选项使用一个key=value语法,允许直接在命令行中直接提供字面值:
$ kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
$ kubectl 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
pods使用ConfigMap
用例:在环境变量中使用ConfigMap
ConfigMap可用于填充各个环境变量或者整个使用。例如下面的例子:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
可以在pod中这样使用ConfigMap的键:
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:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never
当这个pod运行起来的时候,它输出包含下面的行:
SPECIAL_LEVEL_KEY=very
SPECIAL_TYPE_KEY=charm
log_level=INFO
可选ConfigMap在环境变量中
有些情况环境变量不是总是需要。这些环境变量可以标记为可选的在pods:
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:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: a-config
key: akey
optional: true
restartPolicy: Never
当这个pod运行,输出是空的。
设置命令行参数用ConfigMap
ConfigMaps可以用于设置容器里面的命令行参数的值。这是使用Kubernetes替换$(value)语法完成的。考虑ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
为了把值注入到命令行,我们必须使用我们作为环境变量的键,例如上一个例子。我们可以参考在容器内命令行使用$(VAR_NAME)语法:
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
当pod运行起来的时候,从test-container容器的输出会是:
very charm
用例:使用ConfigMap通过卷插件
ConfigMaps也可以在卷内使用。再次返回我们的示例:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
在卷中使用ConfigMap我们有几个不同的选项。最基础的方式是填充卷文件,键值是文件名内容是键对应的值:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "cat /etc/config/special.how" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
restartPolicy: Never
当这个pod运行起来,会输出下面的内容:
very
我们还可以控制卷中的路径通过ConfigMap键映射:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh","-c","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
当这个pod运行起来,会输出下面:
very
映射key指定的路径和权限
你可以在每个文件基础上指定key映射的特定路径和权限。Secrets用户指南介绍语法。
可选ConfigMap通过卷插件
卷和文件也可以标记为可选。ConfigMap或指定的键不一定存在。将始终创建这些项目的挂载路径。
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "ls /etc/config" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: no-config
optional: true
restartPolicy: Never
当pod运行起来,输出将是空。
真实的示例:配置Redis
让我看一个真实示例:使用ConfigMap配置redis。加入我们想用推荐的配置注入redis作为缓存。redis的配置文件应该包含:
maxmemory 2mb
maxmemory-policy allkeys-lru
这个文件在docs/user-guide/configmap/redis
,我们可以用下面的命令新建一个ConfigMap:
$ kubectl create configmap example-redis-config --from-file=docs/user-guide/configmap/redis/redis-config
$ kubectl get configmap example-redis-config -o yaml
apiVersion: v1
data:
redis-config: |
maxmemory 2mb
maxmemory-policy allkeys-lru
kind: ConfigMap
metadata:
creationTimestamp: 2016-03-30T18:14:41Z
name: example-redis-config
namespace: default
resourceVersion: "24686"
selfLink: /api/v1/namespaces/default/configmaps/example-redis-config
uid: 460a2b6e-f6a3-11e5-8ae5-42010af00002
现在我们新建一个pod使用这个配置:
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
注意,这个pod有一个ConfigMap卷,它将example-redis-config ConfigMap的redis-config键的值放入一个名为redis.conf的文件中。这个卷是挂载到redis容器里面的/redis-master目录里面,我们的配置文件在/redis-master/redis.conf
,这个redis注解点在镜像里面的配置文件。
$ kubectl create -f docs/user-guide/configmap/redis/redis-pod.yaml
运行kubectl exec
进入到这个pod里面并运行redis-cli工具,可以检查我们的配置是否正确应用:
$ kubectl 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"
限制
ConfigMap必须在pod消耗他之前创建,除非被标记为可选。对于不存在的ConfigMap将阻止它启动。控制器可能被写入以容忍丢失数据,可以个根据具体情况查看通过ConfigMap配置的各个组件。
通过configMapKeyRef引用命名ConfigMap中不存在的键将阻止他的启动。
ConfigMaps用于填充环境变量通过envFrom,它们被认为具有无效的环境变量名称的键将跳过这些键。该pod被允许启动。将会有一个事件,原因是InvalidVariabelNames,该消息包含被跳过的无效的键的列表。该示例显示一个pod它指的是 default/myconfig ConfigMap包含两个无效的键,1badkey和2alsobad。
$ kubectl.sh get events
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON
0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom configMap default/myconfig were skipped since they are considered invalid environment variable names.
ConfigMap驻留到namespace里面。他们可以被引用和pod相同的namespace。ConfigMap配额大小是一个计划功能。
kubelet仅支持pod使用ConfigMap获取从API server。这包括使用kubectl创建每个pod,或者间接通过副本控制器。