应用部署的一个最佳实践是将应用所需的配置信息和程序分离。
将应用程序打包为容器镜像以后,可以通过环境变量或者外挂文件的方式在创建容器时进行配置注入。
但在大规模容器集群的环境中,对多个容器进行不同的配置将变得非常复杂。
kubernetes从1.2版本开始提供了一种统一的应用配置管理方案:
ConfigMap
3.5.1 ConfigMap概述
ConfigMap供容器使用的典型用法如下:
- 生成容器内的环境变量
- 设置容器启动命令的启动参数(需设置为环境变量)
- 以Volume的形式挂载为容器内部的文件或目录
ConfigMap以一个或多个key:value的形式保存在kubernetes系统中。
3.5.2 创建ConfigMap资源对象
可以通过yaml文件或者kubectl create configmap命令行的方式创建ConfigMap
使用yaml创建ConfigMap
下面的例子 cm-appvars.yaml中展示了将几个应用所需的环境变量定义为ConfigMap的用法:
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:
kubectl get configmap
kubectl describe configmap cm-apvars
kubectl get configmap cm-appvars -o yaml
下面的例子中展示了将2个配置文件server.xml和logging.properties定义为ConfigMap的用法,
设置key为配置文件的别名,value则是配置文件的全部文本内容:
cm-appconfigfiles.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appconfigfiles
data:
key-serverxml: |
<?xml version='1.0' encoding='urf-8'?>
...
key-loggingproperties: "handlers
=1catalina.org.apache.juli..."
运行kubectl create 命令创建该ConfigMap:
kubectl create -f cm-appconfigfiles.yaml
查看创建好的Configmap:
kubectl get configmap cm-appconfigfiles
kubectl describe configmap cm-appconfigfiles
kubectl get configmap cm-appconfigfiles -o yaml
使用kubectl命令行方式创建
不使用yaml文件,直接通过kubectl create configmap 也可以创建ConfigMap。
可以使用–from-file或–from-literal指定内容,并且可以在一行命令中指定多个参数。
- 使用–from-file 参数从文件中进行创建,可以指定key的名称,也可以在一个命令行中创建包含多个key的ConfigMap:
kubectl create configmap NAME --from-file=[key=]source --from-file=[key=]source
- 通过–from-file 参数在目录下进行创建,该目录下的每个配置文件名都被设置为key,文件内容为value:
kubectl create configmap NAME --from-file=config-files-dir
- 使用–from-literal 时会从文本中进行创建,直接将指定的key=value创建为ConfigMap的内容:
kubectl create configmap NAME --from-literal=key1=value1 --from-literal=key2=value2
下面对这几种用法举例说明
例如,在当前目录下含有配置文件server.xml,可以创建一个包含该文件内容的ConfigMap:
kubectl create configmap cm-server.xml --from-file=server.xml
kubectl describe configmap cm-server.xml
假设在configfiles目录下包含2个文件server.xml和logging.properties,创建一个包含这2个文件的ConfigMap:
kubectl create configmap cm-appconf --from-file=configfiles
kubectl describe configmap cm-appconf
3.5.3 在Pod中使用ConfigMap
容器应用对CofigMap的使用有以下2中方法:
- 通过环境变量获取ConfigMap中的内容
- 通过Volume挂载的方式将ConfigMap中的内容挂载为容器内部的文件或目录
通过环境变量方式使用ConfigMap
以前面创建的ConfigMap “cm-appvars” 为例:
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
applogleve: 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/bash", "-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在运行完启动命令后将会退出,并且不会被系统自动重启(spec.restartPolicy=Never)
kubectl create -f cm-test-pod.yaml
运行kubectl get pods --show-all 命令查看已停止的pod:
kubectl get pods --show-all
查看该pod的日志,可以看到启动命令env | grep APP的运行结果:
# kubectl logs cm-test-pod
APPDATADIR=/var/data
APPLOGLEVEL=info
说明容器内部的环境变量使用ConfigMap cm-appvars中的值进行了正确的设置。
kubernetes从1.6版本开始引入了一个新的字段envFrom,实现了在pod环境中将ConfigMap(也可用于Secret资源对象)中所有定义的key=value自动生成为环境变量:
apiVersion: v1
kind: Pod
metadata:
name: cm-test-pod
spec:
containers:
- name: cm-test
image: busybox
command: ["/bin/bash", "-c", "env"]
envFrom:
- configMapRef:
name: cm-appvars # 根据cm-appvars中的key=value自动生成环境变量
restartPolicy: Never
通过这个定义,在容器内部将会生成如下环境变量:
apploglevel=info
appdatadir=/var/data
需要注意环境变量的命名受POSIX命名规范
[a-zA-Z_][a-zA-Z0-9_]*
约束,不能以数字开头。
如果包含非法字符,则系统将跳过该条环境变量的创建,并记录一个Event来提示环境变量无法生成,但并不阻止pod的启动。
通过volumeMount使用ConfigMap
上面cm-appconfigfiles.yaml的例子包含2个配置文件的定义:server.xml和logging.properties。
在pod “cm-test-app”的定义中,将ConfigMap “cm-appconfigfiles”中的内容以文件的形式挂载到容器内部的/configfiles目录下:
apiVersin: v1
kind: Pod
metadata:
name: cm-test-pod
spec:
containers:
- name: cm-test-app
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
volumeMounts:
- name: serverxml # 引用Volume的名称
mountPath: /configfiles # 挂载到容器内的目录
volumes:
- name: serverxml # 定义Volume的名称
configMap:
name: cm-appconfigfiles # 使用ConfigMap "cm-appconfigfiles"
items:
- key: key-serverxml # 对应ConfigMap中的key
path: server.xml # 将value挂载到server.xml文件
- key: key-loggingproperteis
path: logging.properties
创建该pod:
kubectl create -f cm-test-app.yaml
登陆容器,查看在/configfiles目录下存在server.xml和logging.properties文件,他们的内容就是ConfigMap “cm-appconfigfiles”中两个key定义的内容:
kubectl exec -it cm-test-app -- bash
# cat /configfiles/server.xml
# cat /configfiles/logging.properties
如果在引用ConfigMap时不指定items,则使用volumeMount方式在容器内的目录下为每个item都生成一个文件名为key的文件。
pod配置文件内容如下:
apiVersin: v1
kind: Pod
metadata:
name: cm-test-pod
spec:
containers:
- name: cm-test-app
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
volumeMounts:
- name: serverxml # 引用Volume的名称
mountPath: /configfiles # 挂载到容器内的目录
volumes:
- name: serverxml # 定义Volume的名称
configMap:
name: cm-appconfigfiles # 使用ConfigMap "cm-appconfigfiles"
创建该pod,然后登陆到容器查看/configfiles目录下存在key-loggingproperties和key-serverxml文件,
文件的名称来自在ConfigMap cm-appconfigfiles中定义的2个key的名称,文件内容则为value的内容
kubectl create -f cm-test-app.yaml
# ls /configfiles
key-loggingproperties key-serverxml
3.5.4 使用ConfigMap的限制条件
使用ConfigMap的限制条件如下:
- ConfigMap必须在pod之前创建,pod才能引用它
- 如果pod使用envFrom基于ConfigMap定义环境变量,则无效的环境变量名称将会被忽略,并在事件中被记录为InvalidVariableNames
- ConfigMap受命名空间限制,只有处于同命名空间中的pod才可以引用它
- ConfigMap无法用于静态pod