在生产环境中经常会遇到需要修改配置文件的情况,传统的修改方式不仅会影响到服务的正常运行,而且操作步骤也很繁琐。为了解决这个问题,kubernetes项目从1.2版本引入了ConfigMap功能,用于将应用的配置信息与程序的分离。这种方式不仅可以实现应用程序被的复用,而且还可以通过不同的配置实现更灵活的功能。在创建容器时,用户可以将应用程序打包为容器镜像后,通过环境变量或者外接挂载文件的方式进行配置注入。
ConfigMap是以key:value的形式保存配置项,既可以用于表示一个变量的值(例如config=info),也可以用于表示一个完整配置文件的内容(例如server.xml=…)。ConfigMap在容器使用的典型用法如下。
将配置项设置为容器内的环境变量。
将启动参数设置为环境变量。
以Volume的形式挂载到容器内部的文件或目录。
系统中可以通过YAML配置文件或者直接使用kubectl create configmap命令行的方式来创建ConfigMap,下面将详细介绍这两种方式的操作流程。
创建YAML文件appvar.yaml,其中描述将应用所需的变量定义为ConfigMap的用法(注意加粗部分),key为配置文件的别名,value表示是配置文件的全部文本内容。
[root@master ~]# vim appvar.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: appvar
data:
apploglevel: info
appdatadir: /var/data
执行kubectl create命令创建ConfigMap,并使用相关命令查看创建好的Config,命令操作如下所示。
使用YAML文件创建ConfigMap。
[root@master ~]# kubectl create -f appvar.yml
configmap/appvar created
[root@master ~]# kubectl get configmap
NAME DATA AGE
appvar 2 17s
使用describe命令查看ConfigMap详细信息。
[root@master ~]# kubectl describe configmap appvar
Name: appvar
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
appdatadir:
----
/var/data
apploglevel:
----
info
Events: <none>
以YAMl格式查看ConfigMap。
[root@master ~]# kubectl get configmap appvar -o yaml
apiVersion: v1
data:
appdatadir: /var/data
apploglevel: info
kind: ConfigMap
metadata:
creationTimestamp: "2019-10-24T05:28:24Z"
name: appvar
namespace: default
resourceVersion: "1179869"
selfLink: /api/v1/namespaces/default/configmaps/appvar
uid: 19d2ddf0-f61f-11e9-9023-000c29fb2a34
从上面命令的执行结果可以看出变量被成功创建。
在kubectl create configmap命令种使用参数–from-file或–from-literal指定文件、目录或者文本,也可以创建一个或者多个ConfigMap参数。
(1)指定文件,语句格式如下:
Kubectl create connfigmap NAME --from-file=[key= ] source --from-file=[key= ] source
(2)指定目录,语句格式如下:
需要注意,目录中的每个配置文件名都被会被设置为key,文件中的内容将被设置为value,语法为:
Kubectl create connfigmap NAME --from-file=config-files-dir
(3)指定文本,语句格式如下:
此方式将直接指定key:value,语法为:
Kubectl create connfigmap NAME --from-literal=key1=value1 --from-literal=key2=value2
读者可以结合以下实例,更好的理解ConfigMap语句的用法。
在当前目录下创建ConfigMap文件server.xml,使用改文件创建一个ConfigMap。具体操作如下所示。
[root@master ~]# kubectl create configmap cm-server.xml --from-file=server.xml
configmap/cm-server.xml created
[root@master ~]# kubectl describe configmap cm-server.xml
Name: cm-server.xml
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
server.xml:
----
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-server.xml
namespace: default
data:
Events: <none>
在configs目录下包含两个配置文件server.xml和log.xml,使用该目录创建一个包含这两个文件内容的ConfigMap,指令操作如下所示。
[root@master ~]# kubectl create configmap cm-dir --from-file=configs
configmap/cm-dir created
[root@master ~]# kubectl describe configmap cm-dir
Name: cm-dir
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
log.xml:
----
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-log.xml
namespace: default
data:
server.xml:
----
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-server.xml
namespace: default
data:
Events: <none>
在命令行中使用–from-literal参数进行创建ConfigMap的相关操作指令如下所示。
[root@master ~]# kubectl create configmap cm-text --from-literal=var=/tmp/config --from-literal=log=info
configmap/cm-text created
[root@master ~]# kubectl describe configmap cm-text
Name: cm-text
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
var:
----
/tmp/config
log:
----
info
Events: <none>
在Kubernetes中创建好ConfigMap后,容器可以通过以下两种方法使用ConfigMap中的参数内容。
(1)通过环境变量的方式获取ConfigMap中的内容。
(2)通过Volume挂载的方式将ConfigMap中的内容挂载为容器内部的文件或目录。
下面将对这两种使用方式进行详细的介绍。
以创建的ConfigMap“appvar.yaml”为例:
[root@master ~]# vim appvar.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: appvar
data:
apploglevel: info
appdatadir: /var/data
创建Pod,以便于使用ConfitgMap中的内容,指令操作如下所示。
apiVersion: v1
kind: Pod
metadata:
name: pod-test
spec:
containers:
- name: test
image: busybox
command: [ "/bin/sh", "-c", "env | grep APP" ]
env:
- name: APPLOG //定义环境变量APPLOG
valueFrom:
configMapkeyRef:
name: appvar //指定config
key: apploglevel //指定config中的key
- name: APPDIR //定义环境变量APPDIR
valueFrom:
configMapkeyRef:
name: appvar
key: appdatadir
restartPolicy: Never
在上面Pod代码的定义中,将ConfigMap“appvar”中定义的内容以环境变量(APPLOGLEVEL和APPDATADIR)方式设置为容器内部的环境变量,在容器的启动命令中将会显示这两个环境变量的值(“env | grep APP”)。
使用kubectl create -f命令创建该Pod,由于是测试Pod,所以该Pod在执行完启动命令后将会退出,并且不会被系统自动重启(restartPolicy=Never)。
[root@master ~]# kubectl create -f pod-test.yaml
pod/pod-test created
使用kubectl get pods命令查看创建的Pod,指令操作如下所示。
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
cm-test-pod 0/1 Completed 0 4d
dapi-test-pod 0/1 ErrImagePull 0 3d22h
pod-test 0/1 Completed 0 75s
volume-test-pod 0/1 Completed 0 3d21h
查看该Pod的日志,可以看到启动命令“env | grep APP”的执行结果如下所示。
[root@master ~]# kubectl logs pod-test
APPDIR=/var/data
APPLOG=info
根据以上代码的执行结果,可以看出容器内部的环境变量使用ConfigMap cm-appvar中的值进行了正确设置。
Kubernetes在1.6版本引入新字段envFrom,可以实现在Pod环境中将ConfigMap中所有定义的key=value自动生成为环境变量,代码格式如下所示。
apiVersion: v1
kind: Pod
metadata:
name: pod-test
spec:
containers:
- name: test
image: busybox
command: [ "/bin/sh", "-c", "env|grep APP" ]
envfrom:
- configMapRef:
name: cm-appvar
restartPolicy: Never
主要注意的是,环境变量的名称受POSIX命名规范约束,不能以数字开头。如果配置中包含非法字符,系统将会跳过该条环境变量的创建,并记录一个Event用来提醒用户环境变量无法生成,但并不阻止Pod的启动。
为了可以使读者更好的对比学习,这里同样使用“cm-apache.yaml”文件。
[root@master ~]# vim cm-apache.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-apache
data:
html: hello world
path: /var/www/html
创建YAML文件“pod-volume-test.yaml”,并在配置中加入Volume信息,代码如下所示。
apiVersion: v1
kind: Pod
metadata:
name: pod-volume-test
spec:
containers:
- name: apache
image: httpd
ports:
- containerPort: 80
volumeMounts:
- name: volume-test
mountPath: /var/www/html
volumes:
- name: volume-test
configMap:
name: cm-apache
items:
- key: html
path: main.html
- key: path
path: path.txt
创建该Pod,指令如下所示。
[root@master ~]# kubectl create -f pod-volume-test.yaml
pod/pod-volume-test created
查看创建好的Pod是否正常运行,指令如下所示。
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
cm-test-pod 0/1 Completed 0 4d2h
dapi-test-pod 0/1 ImagePullBackOff 0 4d
pod-test 0/1 Completed 0 116m
pod-volume-test 1/1 Running 0 36s
volume-test-pod 0/1 Completed 0 3d23h
root@pod-volume-test:/# cd /var/www/html/
root@pod-volume-test:/var/www/html# ls
main.html path.txt
root@pod-volume-test:/var/www/html# cat main.html
hello world
root@pod-volume-test:/var/www/html# cat path.txt
/var/www/html
使用ConfigMap的限制条件如下。
◎ ConfigMap必须在Pod之前创建。
◎ ConfigMap受Namespace限制,只有处于相同Namespace中的Pod才可以引用它。
◎ ConfigMap中的配额管理还未能实现。
◎ kubelet只支持可以被API Server管理的Pod使用ConfigMap。kubelet在本Node上通过 --manifest-url或–config自动创建的静态Pod将无法引用ConfigMap。
◎ 在Pod对ConfigMap进行挂载(volumeMount)操作时,在容器内部只能挂载为“目录”,无法挂载为“文件”。在挂载到容器内部后,在目录下将包含ConfigMap定义的每个item,如果在该目录下原来还有其他文件,则容器内的该目录将被挂载的ConfigMap覆盖。如果应用程序需要保留原来的其他文件,则需要进行额外的处理。可以将ConfigMap挂载到容器内部的临时目录,再通过启动脚本将配置文件复制或者链接到(cp或link命令)应用所用的实际配置目录下。