应用部署的一个最佳实践是将应用所需的配置信息于程序进行分离,这样可以使得应用程序被更好的复用,通过不用配置文件也能实现更灵活的功能。将应用打包为容器镜像后,可以通过环境变量或外挂文件的方式在创建容器时进行配置注入。ConfigMap是Kubernetes v1.2版本开始提供的一种统一集群配置管理方案。
1、ConfigMap:容器应用的配置管理
容器使用ConfigMap的典型用法如下:
- 生产为容器的环境变量。
- 设置容器启动命令的启动参数(需设置为环境变量)。
- 以Volume的形式挂载为容器内部的文件或目录。
ConfigMap以一个或多个key:value
的形式保存在Kubernetes系统中共应用使用,既可以用于表示一个变量的值,也可以表示一个完整的配置文件内容。
通过yaml
配置文件或者直接使用kubelet create configmap
命令的方式来创建ConfigMap
2、创建ConfigMap资源、对象
1) 通过 yaml 配置文件方式创建
例1:下面的例子 cm-appvars.yaml
描述了将几个应用所需的变量定义为 ConfigMap 的用法:
# vim cm-appvars.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
apploglevel: info
appdatadir:/var/data
执行kubectl create命令创建该ConfigMap
$ kubectl create -f cm-appvars.yaml
configmap "cm-appvars.yaml"created
查看创建好的 ConfigMap:
# kubectl get configmap
NAME DATA AGE
cm-appvars 2 3s
查看描述:
# kubectl describe configmap cm-appvars
Name: cm-appvars
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
appdatadir:
----
/var/data
apploglevel:
----
info
Events: <none>
查看 yaml:
# kubectl get configmap cm-appvars -o yaml
apiVersion: v1
data:
appdatadir: /var/data
apploglevel: info
kind: ConfigMap
metadata:
creationTimestamp: 2018-11-09T01:47:14Z
name: cm-appvars
namespace: default
resourceVersion: "338011"
selfLink: /api/v1/namespaces/default/configmaps/cm-appvars
uid: 62177666-e3c1-11e8-aa71-340a985c23a9
例2:下面的例子cm-appconfigfile.yaml
将两个配置文件server.xml
和logging.properties
定义为configmap
的用法,设置key为配置文件的别名,value则是配置文件的文本的全部内容:
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
key-serverxml:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="utf-8"> <!-- encoder 可以指定字符集,对于中文输出有意义 -->
<!-- %.-1level 只显示信息级别的首字母,%-5level 左对齐显示信息级别全称 -->
<!-- 如需自定义关键字,用 %mdc{键名} 表示,程序中用MDC.put("键名","键值")设置,可动态设置 [%logger:%line]-->
<Pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] %logger %line --%mdc{client} [%X{TRACE_LOG_ID}] %msg%n
</Pattern>
</encoder>
</appender>
key-loggingproperties:
java -Xms1024m -Xmx2048m -Xmn1536m -Xss256k -XX:MaxPermSize=128m -XX:+UseConcMarr
kSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection -XXX
:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/tmp/jvm.log -XX:+HH
eapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote -Dcom.sun.management.jmm
xremote.port=4445 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management..
jmxremote.authenticate=false -XX:HeapDumpPath=/tmp/heapdump.hprof -jar /data/appp
deploy/$ENVIRONMENT/${PROJECT_JAR} >$jetty_log_path/$PROJECT_NAME.log
执行 kubectl create 命令创建该 ConfigMap:
$kubectl create -f cm-appconfigfiles.yaml
configmap ”cm-appconfigfiles” created
查看创建好的 ConfigMap:
# kubectl get configmap cm-appconfigfiles
NAME DATA AGE
cm-appconfigfiles 2 14s
查看描述:
# kubectl describe configmap cm-appconfigfiles
Name: cm-appconfigfiles
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
key-loggingproperties:
----
java -Xms1024m -Xmx2048m -Xmn1536m -Xss256k -XX:MaxPermSize=128m -XX:+UseConcMarr kSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection -XXX :+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/tmp/jvm.log -XX:+HH eapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote -Dcom.sun.management.jmm xremote.port=4445 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.. jmxremote.authenticate=false -XX:HeapDumpPath=/tmp/heapdump.hprof -jar /data/appp deploy/$ENVIRONMENT/${PROJECT_JAR} >$jetty_log_path/$PROJECT_NAME.log
key-serverxml:
----
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder charset="utf-8"> <!-- encoder 可以指定字符集,对于中文输出有意义 --> <!-- %.-1level 只显示信息级别的首字母,%-5level 左对齐显示信息级别全称 --> <!-- 如需自定义关键字,用 %mdc{键名} 表示,程序中用MDC.put("键名","键值")设置,可动态设置 [%logger:%line]--> <Pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] %logger %line --%mdc{client} [%X{TRACE_LOG_ID}] %msg%n</Pattern> </encoder> </appender>
Events: <none>
查看己创建的 ConfigMap 的详细内容,可以看到两个配置文件的全文 :
# kubectl get configmap cm-appconfigfiles -o yaml
apiVersion: v1
data:
key-loggingproperties: java -Xms1024m -Xmx2048m -Xmn1536m -Xss256k -XX:MaxPermSize=128m
-XX:+UseConcMarr kSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
-XXX :+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/tmp/jvm.log
-XX:+HH eapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote -Dcom.sun.management.jmm
xremote.port=4445 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management..
jmxremote.authenticate=false -XX:HeapDumpPath=/tmp/heapdump.hprof -jar /data/appp
deploy/$ENVIRONMENT/${PROJECT_JAR} >$jetty_log_path/$PROJECT_NAME.log
key-serverxml: <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="utf-8"> <!-- encoder 可以指定字符集,对于中文输出有意义 --> <!-- %.-1level 只显示信息级别的首字母,%-5level
左对齐显示信息级别全称 --> <!-- 如需自定义关键字,用 %mdc{键名} 表示,程序中用MDC.put("键名","键值")设置,可动态设置 [%logger:%line]-->
<Pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] %logger %line --%mdc{client}
[%X{TRACE_LOG_ID}] %msg%n</Pattern> </encoder> </appender>
kind: ConfigMap
metadata:
creationTimestamp: 2018-11-09T02:14:33Z
name: cm-appconfigfiles
namespace: default
resourceVersion: "340465"
selfLink: /api/v1/namespaces/default/configmaps/cm-appconfigfiles
uid: 32d3f97b-e3c5-11e8-aa71-340a985c23a9
2) 通过 kubelet 命令行方式创建
不使用 yaml 文件,直接通过kubectl create configmap
也可以创建 ConfigMap,可以使用参数--from-file
或--from-literal
指定内容,并且可以在一行命令中指定多个参数。
(1) 通过--from-file
参数从文件中进行创建,可以指定key
的名称,也可以在一个命令行中创建包含多个 key 的 ConfigMap,语法为:
# kubectl create configmap NAME --from-file=[key=]source --from-file=[key=]source
(2)通过--from-file
参数从目录中
进行创建,该目录下的每个配置文件名都被设置为 key. 文件的内容被设置为 value,语法为 :
# kubectl create configmap NAME --from-file=config-files-dir
(3) --from-literal
从文本中进行创建,直接将指定的key#=value#
创建为ConfigMap
的内容,语法为:
# kubectl create configmap NAME --from-literal=keyl=valuel --from-literal= key2=value2
下面对这几种用法举例说明。
例如,当前目录下含有配置文件
server.xml
,可以创建一个包含该文件内容的 ConfigMap:# kubectl create confiqmap cm-server.xml --from-file=server.xml
假设 configfiles 目录下包含两个配置文件 server.xml 和 logging.properties,创建一个包含这两个文件内容的 ConfigMap:
# kubectl create configmap cm-appconf --from-file=configfiles
使用 --from-literal 参数进行创建的示例如下:
#kubectl create configmap cm-appenv --from-literal=loglevel=info --from-literal=appdatadir=/var/data
查看
kubectl describe configmap cm-appenv Name: cm-appenv Namespace: default Labels: <none> Annotations: <none> Data ==== appdatadir: ---- /var/data loglevel: ---- info Events: <none>
容器应用对 ConfigMap 的使用有以下两种方法。
- 通过环境变量获取 ConfigMap 中的内容。
- 通过 Volume 挂载的方式将 ConfigMap 中的内容挂载为容器内部的文件或目录。
3、在Pod
中使用 ConfigMap
1) 通过环境变量方式使用 ConfigMap
以前面创建的 ConfigMap “cm-appvars”为例 :
# vim cm-appvars.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
apploglevel: info
appdatadir: /var/data
在 Pod “cm-test-pod”的定义中,将 ConfigMap “cm-appvars”中的内容以环境变量 (APPLOGLEVEL
和APPDATADIR
)设置为容器内部的环境变量,容器的启动命令将显示这两个环境变量的值(“env|grep APP”):
apiVersion: v1
kind: Pod
metadata:
name: cm-test-pod
spec:
containers:
- name: cm-test
image: busybox
command: ["/bin/sh","-c","env|grep APP"]
env:
- name: APPLOGLEVEL # 定义环境变量的名称
valueFrom: # key "apploglevel" 对应的值
configMapKeyRef:
name: cm-appvars # 环境变量的值取自 cm-appvars 中
key: apploglevel # key 为 "apploglevel"
- name: APPDATADIR
valueFrom:
configMapKeyRef:
name: cm-appvars
key: appdatadir
restartPolicy: Never
使用 kubectl create -f 命令创建该 Pod,由于是测试 Pod,所以该Pod
在执行完启动命令后将会退出,井且不会被系统自动重启(restartPolicy=Never
):
kubectl create -f cm-test-pod.yaml
pod ” cm-test-pod” created
使用kubectl get pods --show-all
查看己经停止的 Pod:
kubectl get pods --show-all
Flag --show-all has been deprecated, will be removed in an upcoming release
NAME READY STATUS RESTARTS AGE
cm-test-pod 0/1 Completed 0 4m
查看该 Pod 的日志,可以看到启动命令 env | grep APP
的执行结果如下:
kubectl logs cm-test-pod
APPDATADIR=/var/data
APPLOGLEVEL=info
说明容器内部的环境变量使用 ConfigMap cm-appvars 中的值进行了正确的设置。
从 Kubernetes vl.6 开始,引入了一个新的字段 envFrom,实现在 Pod 环境内将 ConfigMap (也可用于 Secret 资源对象〉中所有定义的key=value
自动生成为环境变量:
apiVersion: v1
kind: Pod
metadata:
name: cm-test-pod-env
spec:
containers:
- name: cm-test
image: busybox
command: ["/bin/sh","-c","env"]
envFrom:
- configMapRef:
name: cm-appvars # 根据 cm-appvars 中的 key=value 自动生成环境变量
restartPolicy: Never
通过这个定义,在容器内部将会生成如下环境变量:
# kubectl logs cm-test-pod-env
apploglevel=info
appdatadir=/var/data
需要说明的是 ,环境变量的名称受 POSIX 命名规范([a-zA-Z][a-zA-Z0-9]*)
约束 ,不能以数字开头。如果包含非法字符,则系统将跳过该条环境变量的创建,并记录一个 Event 来描 述环境变量无法生成,但并不阻止 Pod 的启动。
2)通过 volumeMount 使用 ConfigMap
在pod "cm-test-app"定义中,将configmap "cm-appconfigfile"中的内容以文件形式mount
到容器内部configfiles
目录中。
Pod配置文件cm-test-app.yaml
内容如下:
apiVersion: v1
kind: Pod
metadata:
name: cm-test-app
spec:
containers:
- name: cm-test-app
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
volumeMounts:
- name: serverxml # 引用volume名
mountPath: /configfiles # 挂载到容器内部目录
volumes:
- name: serverxml
configMap:
name: cm-appconfigfiles # 使用configmap定义的的cm-appconfigfile
items:
- key: key-serverxml # 将key=key-serverxml
path: server.xml # value将server.xml文件名进行挂载
- key: key-loggingproperties # 将key=key-loggingproperties
path: logging.properties # value将logging.properties文件名进行挂载
创建该Pod:
#kubectl create -f cm-test-app.yaml
Pod "cm-test-app"created
登录容器查看configfiles目录下的server.xml
和logging.properties
文件,他们的内容就是configmap “cm-appconfigfile”中定义的两个key的内容
# kubectl exec -ti cm-test-app -- bash
# cat /configfiles/server.xml
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder charset="utf-8"> <!-- encoder 可以指定字符集,对于中文输出有意义 --> <!-- %.-1level 只显示信息级别的首字母,%-5level 左对齐显示信息级别全称 --> <!-- 如需自定义关键字,用 %mdc{键名} 表示,程序中用MDC.put("键名","键值")设置,可动态设置 [%logger:%line]--> <Pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] %logger %line --%mdc{client} [%X{TRACE_LOG_ID}] %msg%n</Pattern> </encoder> </appender>root@cm-test-app:/usr/local/tomcat#
# cat /configfiles/logging.properties
java -Xms1024m -Xmx2048m -Xmn1536m -Xss256k -XX:MaxPermSize=128m -XX:+UseConcMarr kSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection -XXX :+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/tmp/jvm.log -XX:+HH eapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote -Dcom.sun.management.jmm xremote.port=4445 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.. jmxremote.authenticate=false -XX:HeapDumpPath=/tmp/heapdump.hprof -jar /data/appp deploy/$ENVIRONMENT/${PROJECT_JAR} >$jetty_log_path/$PROJECT_NAME.log
如果在引用 ConfigMap 时不指定 items,则将使用 volumeMount 方式在容器内的目录中为每个item生成一个文件名为key的文件。
Pod配置文件cm-test-app2.yaml内容如下:
apiVersion: v1
kind: Pod
metadata:
name: cm-test-app2
spec:
containers:
- name: cm-test-app2
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
volumeMounts:
- name: serverxml # 引用volume名
mountPath: /configfiles # 挂载到容器内部目录
volumes:
- name: serverxml # 定义 volume 名
configMap:
name: cm-appconfigfiles # 使用configmap定义的的cm-appconfigfile
创建该Pod:
#kubectl create -f cm-test-app2.yaml
Pod "cm-test-app2"created
登录容器,查看到/configfiles
目录下存在key-loggingproperties
和key-serverxml
文件,文件的名称来自 ConfigMap cm-appconfigfiles 中定义的两个key
的名称,文件的内容则为 value 的内容:
# ls /configfiles
key-loqqingproperties key-serverxml
使用ConfigMap的条件限制
- configmap必须在pod之前创建
- configmap也可以定义为属于某个Namespace,只有处于相同namespaces中的pod可以引用
- kubelet只支持可以被API Server管理的Pod使用ConfigMap。
- kubelet在本Node上通过
--manifest-url
或--config
自动创建的静态 Pod 将无法引用 ConfigMap。 - 在 Pod 对 ConfigMap 进行挂载(volumeMount)操作时,容器内部只能挂载为“目录”, 无法挂载为“文件”。在挂载到容器内部后,目录中将包含 ConfigMap 定义的每个item,如果该目录下原来还有其他文件,则容器内的该目录将会被挂载的 ConfigMap 覆盖。 如果应用程序需要保留原来的其他文件,则需要进行额外的处理。可以将 ConfigMap 挂载到容器内部的临时目录,再通过启动脚本将配置文件复制或者链接到(cp或link命令)应用所用的实际配置目录下。
大神,请教下,configmap可不可以被程序修改。我一个文件转成configmap,映射给多个pod使用,pod可以改变configmap的内容吗,从而影响其他pod
不可以,configmap只能从外部修改,而且pod重启之后,才能看到最新的变化。
volumeMounts: - name: noah-collector-config mountPath: /usr/local/noah2/basp-collector/conf/application.yml subPath: application.yml - name: noah-collector-conf mountPath: /usr/local/noah2/basp-collector/conf volumes: - name: noah-collector-config configMap: name: noah-collector - name: noah-collector-conf hostPath: #本地磁盘挂载conf文件夹 path: /usr/local/noah2/basp-collector/conf type: DirectoryOrCreate
当/usr/local/noah2/basp-collector/conf下不存在application.yml的时候,挂载到该目录的application.yml文件大小是0.
当/usr/local/noah2/basp-collector/conf下存在application.yml的时候,挂载到该目录的application.yml无法覆盖已有的application.yml.
大哥知道原因吗
兄弟贴到问题专区提问吧,这里不好施展。(下面有链接)
问题已回复,转至Kubernetes将configmap文件挂载到hostPath路径下失败
执行 kubectl create 命令创建该 Conf1gMap:
感谢,已更新。