1.实验介绍
在使用 Pod 启动应用时,除了镜像之外通常还需要自定义一些参数或是配置,有的时候自定义的配置比较多,所以在 kubernetes 集群中提供了 ConfigMap 向容器中提供环境变量或配置文件以实现不同的配置,这样可以使镜像的配置信息与镜像解耦,通过不同的配置信息使应用程序能够得到更好的复用。
2. ConfigMap 简介
想象一个场景,在 kubernetes 集群中有的时候我们需要传递一些配置给应用,比如:数据库地址、用户名、密码等,我们可以有哪些办法呢?
- 在打包镜像时将配置信息直接写入配置文件中:使用这种方式特别死板,并且配置数据不能共享,坏处显而易见
- 在配置文件中通过 env 环境变量传入:这种方式如果要修改 env,就必须修改 YAML 文件,并重启所有 container,而且配置数据也不能共享
- 在应用启动时通过数据库获取配置数据:这种方式具有一定可行性,配置信息可以多应用共享,但是自己实现起来比较麻烦
所以,kubernetes 提供了统一的应用配置管理方案 ConfigMap 方便我们将配置信息与应用程序分离。
ConfigMap 概述
ConfigMap 在容器中使用的场景通常有 3 种,分别如下所示:
- 生成为容器中的环境变量
- 设置容器启动命令的启动参数(需设置为环境变量)
- 以 Volume 的形式挂载为容器内部的文件或目录
使用 ConfigMap 的限制条件
- ConfigMap 必须在 Pod 之前创建
- ConfigMap 受 Namespace 限制,只有处于相同 Namespace 中的 Pod 才可以引用它
- kubelet 只支持可以被 API Server 管理的 Pod 使用 ConfigMap,kubelet 在本 Node 上通过 --manifest-url 或 --config 自动创建的静态 Pod 无法引用 ConfigMap
- 在 Pod 对 ConfigMap 进行挂载(volume)操作时,在容器内部只能挂载为“目录”,不能挂载为“文件”。在挂载到容器内部后,在目录下将包含 ConfigMap 定义的每个 item,如果在该目录下原来还有其它文件,则容器内的该目录将被挂载的 ConfigMap 覆盖。如果想要保存原来的其它文件,可以将 ConfigMap 挂载到容器内部的临时目录,再通过启动脚本将配置文件复制(cp)或链接(link)到应用所在的实际目录下
3. 创建 ConfigMap 资源对象
创建 ConfigMap 资源对象的方式有两种:第一种是通过 YAML 配置文件的方式进行创建,第二种是通过 kubectl 命令行方式创建,第三种是通过 ConfigMap 生成器 kustomization.yaml 方式进行创建(从 kubernetes v1.14 版本开始支持 kustomization.yaml)。
ConfigMap 以一个或多个 key:value 的形式将配置信息保存在 kubernetes etcd 数据库中,键值对的形式既可以表示单个属性/一个变量的值,比如:apploglevel=info
,也可以表示整个配置文件/JSON 二进制对象的内容,比如:server.xml=<?xml...>...
。
ConfigMap 中保存的配置信息既可以在 Pod 中使用,也可以用于系统组件(比如:Controller)存储配置数据,ConfigMap 与我们后面将会介绍的 Secret 用法有些类似,不过 ConfigMap 主要用于存储不含敏感信息的数据。
下面我们将会详细讲解这三种不同的创建方式。
3.1 通过 YAML 配置文件方式创建
这种创建方式和使用其它的 YAML 文件是相同的,使用的命令为 kubectl create -f xxxx.yaml
。
在 /home/shiyanlou 目录下新建 cm-appvars.yaml 文件,并写入如下内容:
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars # ConfigMap 的名称
data: # 配置信息
apploglevel: info
appdatadir: /var/data
这里需要注意的是:ConfigMap 不是属性文件的替代品,它只是作为多个配置文件的引用,类似于 Linux 系统中的 /etc
目录,是专门用来存储配置文件的目录。在上面的 YAML 文件中,在 data
下配置的每一项都会成为一个新文件。
使用命令执行创建:
$ kubectl create -f cm-appvars.yaml
configmap/cm-appvars created
查看刚刚创建的 ConfigMap:
$ kubectl get configmap
NAME DATA AGE
cm-appvars 2 10m
# 查看刚刚创建的 cm-appvars 的详细信息
$ kubectl describe configmap cm-appvars
Name: cm-appvars
Namespace: default # 如果在 YAML 文件中没有指定命名空间的话,默认使用 default
Labels: <none>
Annotations: <none>
Data
====
appdatadir:
----
/var/data
apploglevel:
----
info
Events: <none>
3.2 通过 kubectl 命令行方式创建
命令形式如下:
kubectl create configmap <map-name> <data-source>
其中,<map-name>
是设置的 configmap 的名字,<data-source>
可以是目录、文件、或是 key-value 键值对。
<data-source>
中的可选参数为:--from-file
/--from-env-file
(从目录或文件创建) 和 --from-literal
(直接指定键值对创建)。configmap
也可以缩写为 cm
。
可以在命令行中执行 kubectl create configmap -h
查看具体参数和使用方法。
从目录中创建 ConfigMap
这种方式适用于在一个目录下有多个配置文件。
在 /home/shiyanlou
目录下新建 configmap
文件夹,并在 configmap
文件夹下新建两个文件,分别名为:game.properties
和 ui.properties
。
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
执行创建:
# 这里设置 configmap 的名称为 game-config
$ kubectl create configmap game-config --from-file=/home/shiyanlou/configmap/
configmap/game-config created
$ kubectl get configmap 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: "2019-09-23T08:37:09Z"
name: game-config
namespace: default
resourceVersion: "11509"
selfLink: /api/v1/namespaces/default/configmaps/game-config
uid: 212cd3eb-fd6d-43a4-8aed-d33968da8e1c
$ kubectl describe configmap game-config
Name: game-config
Namespace: default
Labels: <none>
Annotations: <none>
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
Events: <none>
从文件中创建 ConfigMap
可以从单独的文件或是多个文件中进行创建。
比如:
# 使用单个文件创建
kubectl create configmap game-config-2 --from-file=/home/shiyanlou/configmap/game.properties
# 使用多个文件创建
kubectl create configmap game-config-3 --from-file=/home/shiyanlou/configmap/game.properties --from-file=/home/shiyanlou/configmap/ui.properties
使用参数 --from-env-file
从 env-file 中创建 ConfigMap。env-file 是包含了环境变量的列表。
在 /home/shiyanlou/configmap
目录下新建 game-env-file.properties
文件,并写入如下内容:
enemies=aliens
lives=3
allowed="true"
执行创建:
$ kubectl create configmap game-config-env-file --from-env-file=/home/shiyanlou/configmap/game-env-file.properties
configmap/game-config-env-file created
$ kubectl get configmap game-config-env-file -o yaml
apiVersion: v1
data:
allowed: '"true"'
enemies: aliens
lives: "3"
kind: ConfigMap
metadata:
creationTimestamp: "2019-09-23T09:00:46Z"
name: game-config-env-file
namespace: default
resourceVersion: "13919"
selfLink: /api/v1/namespaces/default/configmaps/game-config-env-file
uid: 790cbece-1144-4ebe-9ea1-1e151f210ef7
另外使用文件创建的话,可以使用自定义的名称替代默认使用的文件名,比如:
# 使用 game.properties 文件创建,但是将其重命名为 game-special-key
$ kubectl create configmap game-config-4 --from-file=game-special-key=/home/shiyanlou/configmap/game.properties
configmap/game-config-4 created
# 可以看到这里显示的是 game-special-key,而不再是之前的 game.properties
$ kubectl describe configmap game-config-4
Name: game-config-4
Namespace: default
Labels: <none>
Annotations: <none>
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
Events: <none>
使用 key-value 键值对创建 ConfigMap
使用参数 --from-literal
直接在命令中设置 key-value 键值对。
比如:
# 传递多组键值对
$ kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
configmap/special-config created
$ kubectl get configmaps special-config -o yaml
apiVersion: v1
data:
special.how: very
special.type: charm
kind: ConfigMap
metadata:
creationTimestamp: "2019-09-23T09:16:09Z"
name: special-config
namespace: default
resourceVersion: "15490"
selfLink: /api/v1/namespaces/default/configmaps/special-config
uid: 231c59c3-dc4d-4650-a04f-af51debc94fa
3.3 通过生成器创建 ConfigMap
kubectl 从 1.14 版本开始支持 kustomization.yaml。我们可以使用生成器创建 ConfigMap,然后发送给 API Server 创建资源对象。生成器是在 kustomization.yaml 文件内部指定。
从文件创建生成器
比如使用 configmap/game.properties 文件生成一个 ConfigMap:
cat <<EOF >/home/shiyanlou/kustomization.yaml
configMapGenerator:
- name: game-config-5
files:
- configmap/game.properties
EOF
执行创建:
$ kubectl apply -k .
configmap/game-config-5-c6kgkt26m6 created
# 可以看到使用生成器创建的 ConfigMap 在名称末尾有一个 hash 后缀,这样可以确保每次配置文件内容修改以后生成器会生成一个新的 ConfigMap
$ kubectl get configmap|grep game-config-5
game-config-5-c6kgkt26m6 1 49s
$ kubectl describe configmaps/game-config-5-c6kgkt26m6
Name: game-config-5-c6kgkt26m6
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","data":{"game.properties":"enemies=aliens\nlives=3\nenemies.cheat=true\nenemies.cheat.level=noGoodRotten\nsecret.code.p...
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
Events: <none>
类似的我们可以将配置文件的名称进行重命名,只需要将 kustomization.yaml 中的 files
如下:
# 使用名称 game-special-key 替代 game.properties
- name: game-config-5
files:
- game-special-key=configmap/game.properties
然后执行 kubectl apply -k .
会生成新的 ConfigMap。
从键值对生成 ConfigMap
在终端执行如下命令写入值:
cat <<EOF >/home/shiyanlou/kustomization.yaml
configMapGenerator:
- name: special-config-2
literals:
- special.how=very
- special.type=charm
EOF
执行创建:
$ kubectl apply -k .
configmap/special-config-2-c92b5mmcf2 created
4. 在 Pod 中使用 ConfigMap
每次使用的时候,我们都需要先定义 ConfigMap,然后在 Pod 中引用定义好的配置信息。
4.1 通过环境变量方式使用 ConfigMap
使用一个 ConfigMap 中的配置信息作为环境变量
使用 key-value 键值对定义一个用作环境变量的 ConfigMap:
$ kubectl create configmap config-1 --from-literal=special.how=very
configmap/config-1 created
定义 Pod YAML 文件时,SPECIAL_LEVEL_KEY 环境变量使用在 ConfigMap 中定义的 special.how 配置信息的值,在 /home/shiyanlou
目录下新建 pods
文件夹,并在该文件夹下新建 pod-single-configmap-env-variable.yaml
文件,向该文件中写入如下内容:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: busybox
command: ['/bin/sh', '-c', 'env'] # 容器的启动命令是输出环境变量
env:
- name: SPECIAL_LEVEL_KEY # 定义环境变量的名称
valueFrom: # 环境变量 SPECIAL_LEVEL_KEY 的取值
configMapKeyRef:
name: config-1 # 环境变量的值取自于 config-1 ConfigMap
key: special.how # key 为 special.how
restartPolicy: Never
执行创建 Pod:
$ kubectl create -f pods/pod-single-configmap-env-variable.yaml
pod/dapi-test-pod created
# 查看状态为 Completed,因为启动容器后只查看了环境变量,并且设置为再也不重启,所以容器打印环境变量之后也变为完成状态,并且不会在重启
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
dapi-test-pod 0/1 Completed 0 18s
然后查看日志,检查是否有成功设置环境变量:
$ kubectl logs dapi-test-pod|grep SPECIAL_LEVEL_KEY
SPECIAL_LEVEL_KEY=very
使用多个 ConfigMap 中的配置信息作为环境变量
在 /home/shiyanlou/configmap
目录下新建 configmaps.yaml
文件,并写入如下内容:
apiVersion: v1
kind: ConfigMap
metadata:
name: config-2
namespace: default
data:
special.how: very
---
apiVersion: v1
kind: ConfigMap
metadata:
name: config-3
namespace: default
data:
log_level: INFO
执行创建:
$ kubectl create -f configmap/configmaps.yaml
configmap/config-2 created
configmap/config-3 created
在 Pod YAML 文件中使用前面定义的 ConfigMap 中的配置信息,将下面的内容写入 /home/shiyanlou/pods
目录下的 pod-multiple-configmap-env-variable.yaml
文件中:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod-2
spec:
containers:
- name: test-container-2
image: busybox
command: ['/bin/sh', '-c', 'env']
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: config-2
key: special.how
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: config-3
key: log_level
restartPolicy: Never
执行创建:
$ kubectl create -f pods/pod-multiple-configmap-env-variable.yaml
pod/dapi-test-pod-2 created
执行命令 kubectl logs dapi-test-pod-2
可以看到打印出的环境变量中有 LOG_LEVEL=INFO
以及 SPECIAL_LEVEL_KEY=very
。
使用 ConfigMap 中的所有配置信息作为环境变量
在 /home/shiyanlou/configmap
文件夹下新建 configmap-multikeys.yaml
文件,并写入如下内容:
apiVersion: v1
kind: ConfigMap
metadata:
name: config-4
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
执行创建:
$ kubectl create -f configmap/configmap-multikeys.yaml
configmap/config-4 created
使用 envFrom
将 ConfigMap 中的所有配置信息定义为容器的环境变量,ConfigMap 中的 key 会成为 Pod 中的环境变量名。在 /home/shiyanlou/pods
目录下新建 pod-configmap-envFrom.yaml
文件并写入如下内容:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod-3
spec:
containers:
- name: test-container-3
image: busybox
command: ['/bin/sh', '-c', 'env']
envFrom:
- configMapRef:
name: config-4
restartPolicy: Never
执行创建:
$ kubectl create -f pods/pod-configmap-envFrom.yaml
pod/dapi-test-pod-3 created
执行命令 kubectl logs dapi-test-pod-2
可以看到打印出的环境变量中有 SPECIAL_LEVEL=very
以及 SPECIAL_TYPE=charm
。
在 Pod 命令中引用环境变量
在 Pod YAML 文件的 command
部分可以使用 $(VAR_NAME)
方式引用环境变量。
在 /home/shiyanlou/pods
目录下新建 pod-configmap-env-var-valueFrom.yaml
文件并写入如下内容:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod-4
spec:
containers:
- name: test-container-4
image: busybox
command:
['/bin/sh', '-c', 'echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)']
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: config-4
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: config-4
key: SPECIAL_TYPE
restartPolicy: Never
执行创建:
$ kubectl create -f pods/pod-configmap-env-var-valueFrom.yaml
pod/dapi-test-pod-4 created
执行命令 kubectl logs dapi-test-pod-4
可以看到输出的环境变量 very
和 charm
。
4.2 通过卷挂载(volumeMount)方式使用 ConfigMap
前面我们提到过可以使用参数 --from-file
从文件中创建 ConfigMap,这个时候文件名就成为了 ConfigMap 中的 key,文件中的内容就是 key 对应的 value。
使用 ConfigMap 中的配置数据挂载到卷
Pod YAML 文件定义中,在 volumes
指定 ConfigMap 的名字,在 volumeMounts.mountPath
指定具体挂载到容器中的目录。
在 /home/shiyanlou/pods
目录下新建 pod-configmap-volume.yaml
文件,并写入如下内容:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod-5
spec:
containers:
- name: test-container-5
image: busybox
command: ['/bin/sh', '-c', 'ls /etc/config'] #查看是否成功挂载
volumeMounts:
- name: config-volume # 引用 volume 的名称
mountPath: /etc/config # 挂载到容器内的目录路径
volumes:
- name: config-volume # 定义 volume 的名称
configMap:
name: config-4 # 使用 ConfigMap "config-4"
restartPolicy: Never
执行创建:
$ kubectl create -f pods/pod-configmap-volume.yaml
pod/dapi-test-pod-5 created
查看日志,获取容器中 /etc/config 目录下的文件列表:
$ kubectl logs dapi-test-pod-5
SPECIAL_LEVEL
SPECIAL_TYPE
这样我们可以很明确的发现,ConfigMap 配置信息的 key 成为了挂载到容器后的文件名。如果容器在 /etc/config 目录下存在文件,挂载后原有文件将会被覆盖。
卷挂载时明确存储路径
使用 path
字段可以明确挂载到容器后的文件名。
在 /home/shiyanlou/pods
目录下新建 pod-configmap-volume-specific-key.yaml
文件,并写入如下内容:
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod-6
spec:
containers:
- name: test-container-6
image: busybox
command: ['/bin/sh', '-c', 'cat /etc/config/keys']
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: config-4
items:
- key: SPECIAL_LEVEL
path: keys # SPECIAL_LEVEL 的 value 以 keys 文件名进行挂载
restartPolicy: Never
执行创建:
$ kubectl create -f pods/pod-configmap-volume-specific-key.yaml
pod/dapi-test-pod-6 created
查看日志,检查 /etc/config/keys 文件中存储的值是否为 SPECIAL_LEVEL 对应的值:
$ kubectl logs dapi-test-pod-6
very
本文由 liyunfei 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Jun 29,2022