很多应用程序需要一些配置通过组合的配置文件,命令行参数和环境变量。这些配置应该与镜像内容分离以保持容器化应用程序的可移植性。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: defaultdata: 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=3enemies.cheat=trueenemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=truesecret.code.lives=30$ cat docs/user-guide/configmap/kubectl/ui.properties color.good=purple color.bad=yellow allow.textmode=truehow.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=30kind: 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: defaultdata: special.how: very special.type: charm
apiVersion: v1 kind: ConfigMap metadata: name: env-config namespace: defaultdata: 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: defaultdata: 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: defaultdata: 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-cli127.0.0.1:6379> CONFIG GET maxmemory1) "maxmemory"2) "2097152"127.0.0.1:6379> CONFIG GET maxmemory-policy1) "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 REASON0s 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,或者间接通过副本控制器。
作者:YiQinGuo
链接:https://www.jianshu.com/p/571383da7adf