Kubernetes ConfigMap详解
ConfigMap简介
ConfigMap是一种API对象,用来将非机密性的数据保存到键值对中。使用时Pods可以将其用作环境变量、命令行参数或者存储卷中的配置文件。服务需要连接mysql,redis等,代码中有一些配置需要经常改动。所以ConfigMap就是解决这些问题的。ConfigMap将环境配置信息和容器镜像解耦,便于应用配置的修改。不过需要注意的是
ConfigMap本身不提供加密功能。如果要存储的数据是机密的,使用Secret,或者使用其他第三方工具来保证你的数据的私密性,而不是用ConfigMap
ConfigMap在设计上不是用来保存大量数据的。在ConfigMap中保存的数据不可超过1MiB。如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数据库或者文件服务
ConfigMap的创建
可以使用kubectl create configmap从文件、目录或者key-value字符串创建等创建ConfigMap,也可以通过kubectl create -f file创建
使用key-value字符串创建
[root@k8s01 ~]# kubectl create configmap config-test-1 --from-literal=name=allen --from-literal=age=22
configmap/config-test-1 created
[root@k8s01 ~]# kubectl get configmap config-test-1 -o go-template --template='{{.data}}'
map[age:22 name:allen]
使用env文件创建
[root@k8s01 ~]# echo -e "name=allen\nage=25" | tee config.env
name=allen
age=25
[root@k8s01 ~]# kubectl create configmap config-test-2 --from-env-file=config.env
configmap/config-test-2 created
[root@k8s01 ~]# kubectl get configmap config-test-2 -o go-template --template='{{.data}}'
map[age:25 name:allen]
使用目录创建
[root@k8s01 ~]# mkdir config
[root@k8s01 ~]# echo 18 > config/age
[root@k8s01 ~]# echo allen > config/name
[root@k8s01 ~]# kubectl create configmap config-test-3 --from-file=config/
configmap/config-test-3 created
[root@k8s01 ~]# kubectl get configmap config-test-3 -o go-template --template='{{.data}}'
map[age:18
name:allen
]
使用Yaml/Json创建
[root@k8s01 ~]# cat tets.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: config-test-4
namespace: default
data:
name: allen
age: 16
[root@k8s01 ~]# kubectl create -f config-test-4.yaml
configmap/config-test-4 created
ConfigMap使用
ConfigMap可以通过三种方式在Pod中使用,三种分别方式为:设置环境变量、设置容器命令行参数以及在Volume中直接挂载文件或目录
注意:
ConfigMap必须在Pod引用它之前创建
使用envFrom时,将会自动忽略无效的键
Pod 只能使用同一个命名空间内的ConfigMap
创建ConfigMap
[root@k8s01 ~]# kubectl create configmap special-config --from-literal=name=all --from-literal=realname=allen
[root@k8s01 ~]# kubectl create configmap env-config --from-literal=log_level=INFO
用作环境变量
[root@k8s01 ~]# cat test.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test
image: busybox
command: ["/bin/sh", "-c", "env"]
env:
- name: SPECIAL_NAME_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: name
- name: SPECIAL_REALNAME_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: realname
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never
[root@k8s01 ~]# kubectl logs -f test-pod
HOSTNAME=test-pod
SPECIAL_NAME_KEY=all
log_level=INFO
SPECIAL_REALNAME_KEY=allen
值已成功写入了
用作命令参数
将ConfigMap用作命令行参数时,需要先把ConfigMap的数据保存在环境变量中,然后通过$(VAR_NAME)的方式引用环境变量
[root@k8s01 ~]# cat test.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test
image: busybox
command: ["/bin/sh", "-c", "echo $(SPECIAL_NAME_KEY) $(SPECIAL_REALNAME_KEY)" ]
env:
- name: SPECIAL_NAME_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: name
- name: SPECIAL_REALNAME_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: realname
restartPolicy: Never
[root@k8s01 ~]# kubectl logs -f test-pod
all allen
输出写入的配置
使用volume将ConfigMap作为文件或目录直接挂载
将创建的ConfigMap直接挂载至Pod 的/etc/config目录下,其中每一个key-value键值对都会生成一个文件,key为文件名,value为内容
[root@k8s01 ~]# cat test.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test
image: busybox
command: ["/bin/sh", "-c", "cat /etc/config/name"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
restartPolicy: Never
[root@k8s01 ~]# kubectl logs -f test-pod
all#
使用subpath将ConfigMap作为单独的文件挂载到目录
一般情况下configmap挂载文件时,会先覆盖掉挂载目录,然后再将congfigmap中的内容作为文件挂载进行。如果想不对原来的文件夹下的文件造成覆盖,只是将configmap中的每个key按照文件的方式挂载到目录下,可以使用subpath参数
[root@k8s01 ~]# cat test.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test
image: nginx
command: ["/bin/sh","-c","sleep 36000"]
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/name
subPath: name
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: name
path: name
restartPolicy: Never
[root@k8s01 ~]# kubectl exec -it test-pod-7856cd8988-bxwwl bash
root@test-pod:/etc/nginx# ls
conf.d mime.types name scgi_params
fastcgi_params modules nginx.conf uwsgi_params
被挂载的ConfigMap内容会被自动更新
当卷中使用的ConfigMap被更新时,所投射的键最终也会被更新。kubelet组件会在每次周期性同步时检查所挂载的ConfigMap是否为最新。 不过kubelet使用的是其本地的高速缓存来获得ConfigMap的当前值。
ConfigMap既可以通过watch操作实现内容传播(默认形式),也可实现基于TTL的缓存,还可以直接经过所有请求重定向到API服务器。 因此从ConfigMap被更新的那一刻算起,到新的主键被投射到Pod中去,这一 时间跨度可能与kubelet的同步周期加上高速缓存的传播延迟相等。 这里的传播延迟取决于所选的高速缓存类型 (分别对应watch操作的传播延迟、高速缓存的TTL时长或者 0)。
以环境变量方式使用的ConfigMap数据不会被自动更新,更新这些数据需要重新启动Pod
不可变更的ConfigMap
Kubernetes特性不可变更的Secret和ConfigMap提供了一种将各个Secret和ConfigMap设置为不可变更的选项。对于大量使用ConfigMap的集群(至少有数万个各不相同的ConfigMap给Pod 挂载)而言,禁止更改ConfigMap的数据有以下好处:
保护应用,使之免受意外更新所带来的负面影响
通过大幅降低对kube-apiserver的压力提升集群性能,这是因为系统会关闭对已标记为不可变更的ConfigMap的监视操作
可以通过将immutable字段设置为true创建不可变更的ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
...
data:
...
immutable: true
一旦某ConfigMap被标记为不可变更,则无法逆转这一变化,,也无法更改data或binaryData字段的内容。你只能删除并重建ConfigMap。 因为现有的Pod会维护一个对已删除的ConfigMap的挂载点,建议重新创建这些Pods