我们知道,在几乎所有的应用开发中,都会涉及到配置文件的变更,比如说在web的程序中,需要连接数据库,缓存甚至是队列等等。而我们的一个应用程序从写第一行代码开始,要经历开发环境、测试环境、预发布环境只到最终的线上环境。而每一个环境都要定义其独立的各种配置。如果我们不能很好的管理这些配置文件,你的运维工作将顿时变的无比的繁琐。为此业内的一些大公司专门开发了自己的一套配置管理中心,如360的Qcon,百度的disconf等。kubernetes也提供了自己的一套方案,即ConfigMap。kubernetes通过ConfigMap来实现对容器中应用的配置管理。
ConfigMap(配置文件注入Pod) 概述:
ConfigMap 供容器使用的典型用法如下:
- 生成为容器的环境变量。
- 以 Volume 的形式挂载为容器内部的文件或目录。
ConfiMap 以一个或多个 key:value 的形式保存在 Kubernetes 系统中提供应用使用,即可以用于表示一个变量的值(例如 apploglevel=info),也可以用于表示一个完整配置文件的内容(例如:server.xml=<?xml…>…)
创建 ConfigMap 资源对象
通过 yaml 配置文件方式创建
下面的例子 cm-appvars.yaml 描述了将几个应用所需的变量定义为 ConfigMap 的用法:
1 2 3 4 5 6 7 8
| cm-appvars.yaml apiVersion: v1 kind: ConfigMap metadata: name: cm-appvars data: apploglevel: info appdatadir: /var/data
|
执行创建:
1
| [root@master-1 app]# kubectl apply -f cm-appvars.yaml
|
查看创建好的 ConfigMap:
1 2 3
| [root@master-1 app]# kubectl get configmap NAME DATA AGE cm-appvars 2 63m
|
查看详细信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| [root@master-1 app]# kubectl describe configmap cm-appvars Name: cm-appvars Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","data":{"appdatadir":"/var/data","apploglevel":"info"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"cm-appva...
Data ==== appdatadir: ---- /var/data apploglevel: ---- info Events: <none>
|
查看 yaml 形式数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| [root@master-1 app]# kubectl get configmap cm-appvars -o yaml apiVersion: v1 data: appdatadir: /var/data apploglevel: info kind: ConfigMap metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"v1","data":{"appdatadir":"/var/data","apploglevel":"info"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"cm-appvars","namespace":"default"}} creationTimestamp: "2019-01-23T01:41:49Z" name: cm-appvars namespace: default resourceVersion: "81484" selfLink: /api/v1/namespaces/default/configmaps/cm-appvars uid: 0cf43d8e-1eb0-11e9-a8c7-d8490b8af3ae
|
通过 kubectl 命令行方式创建
如果不想使用 yaml 文件,可直接通过 kubectl 也可以创建 ConfigMap,可以使用参数 –from-file 或 –from-literal 指定内容,并且可以在一行命令中指定多个参数。
1 2
| 1、通过 --from-file 参数从文件中进行创建,可以指定 key 的名称,也可以在一个命令行中创建多个 key 的 ConfigMap,文件的内容被设置为 value,语法为: kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt
|
1 2
| 2、通过 --from-file 参数从文件中进行创建,文件名都被设置为 key,文件的内容被设置为 value,语法为: kubectl create configmap my-config --from-file=path/to/bar/file1.txt
|
1 2
| 3、--from-literal 从文本中进行创建,直接将指定的 key:value 创建为 ConfigMap 的内容语法为: kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2
|
容器应用对 ConfigMap 的使用有以下两种方法。
1、通过环境变量获取 ConfigMap 中的内容。(不支持动态更新)
2、通过 Volume 挂载的方式将 ConfigMap 中的内容关在为容器内部的文件或目录。(支持动态更新)
第一种方式示例(通过环境变量的方式使用 ConfigMap):
ConfigMap文件:
1 2 3 4 5 6 7
| apiVersion: v1 kind: ConfigMap metadata: name: cm-appvars data: apploglevel: info appdatadir: /var/data
|
在 Pod 定义中,将 ConfigMap “cm-appvars” 中的内容以环境变量设置为容器内部的环境变量,容器的启动命令将显示这两个环境变量的值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| apiVersion: v1 kind: Pod metadata: name: nginx-test4 namespace: default labels: app: nginx1 spec: containers: - name: nginxtest image: nginx:latest env: - name: APP_DATA_DIR valueFrom: configMapKeyRef: name: cm-appvars key: appdatadir - name: APP_LOG_LEVEL valueFrom: configMapKeyRef: name: cm-appvars key: apploglevel imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 - name: https containerPort: 443
|
1 2
| #进入查看是否成功加载 [root@master-1 app]# kubectl exec -it nginx-test4 -- printenv
|
1 2 3
| [root@k8s-master volumes] configmap/cm-appvars edited
|
1 2
| #查看是否编辑生效(是没有生效的,使用环境变量的方式注入不支持动态更新,因为pod在启动的时候就加载了环境变量) [root@master-1 app]# kubectl exec -it nginx-test4 -- printenv
|
从 Kubernetes 1.6 开始,引入了一个新的字段 envFrom,实现在 Pod 环境内将 ConfigMap(也可以用于 Secret 资源对象)中所有定义的 key=value 自动生成为环境变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| apiVersion: v1 kind: Pod metadata: name: nginx-test4 namespace: default labels: app: nginx1 spec: containers: - name: nginxtest image: nginx:latest envFrom: - configMapRef: name: cm-appvars imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 - name: https containerPort: 443
|
1 2
| #进入查看是否成功加载 [root@master-1 app]# kubectl exec -it nginx-test4 -- printenv
|
第二种方式示例(通过 VolumeMount 使用 ConfigMap)
使用volume将ConfigMap作为文件或目录直接挂载,其中每一个key-value键值对都会生成一个文件,key为文件名,value为文件内容,下面是一个示例:(当一个configmap中有多个key-value键值对时要注意每一个key-value键值对都会生成一个文件)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| apiVersion: v1 kind: Pod metadata: name: nginx-test4 namespace: default labels: app: nginx1 spec: containers: - name: nginxtest image: nginx:latest volumeMounts: - name: config mountPath: /etc/nginx/conf.d/ imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 - name: https containerPort: 443 volumes: - name: config configMap: name: cm-appvars
|
验证是否是把两个key生成了两个文件,value是文件中的内容
1 2
| [root@master-1 app]# kubectl exec -it nginx-test4 -- ls /etc/nginx/conf.d/ appdatadir apploglevel
|
1 2 3
| [root@k8s-master volumes] configmap/cm-appvars edited
|
1 2
| #查看是否编辑生效(修改已经生效) [root@master-1 app]# kubectl exec -it nginx-test4 -- printenv
|
configmap单key-value配置文件挂载:
使用volume将ConfigMap作为文件或目录直接挂载到某个服务上做服务的配置文件,例如下面将www.conf配置文件使用configmap的方式挂载到nginx的配置文件目录下作为nginx的配置文件。此方式还支持动态修改
1 2 3 4 5
| server { server_name myapp.magedu.com listen 80 root /data/web/html }
|
使用VolumeMount方式挂载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| apiVersion: v1 kind: Pod metadata: name: nginx-test4 namespace: default labels: app: nginx1 spec: containers: - name: nginxtest image: nginx:latest volumeMounts: - name: nginxconfig mountPath: /etc/nginx/conf.d/ imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 - name: https containerPort: 443 volumes: - name: nginxconfig configMap: name: my-config
|
此yaml的意思是将www.conf文件的内容注入到pod中,nginx将加载www.conf中的内容。创建出一个server出来。
验证是否生效:
1 2 3 4 5 6 7 8
| [root@master-1 app]# kubectl exec -it nginx-test4 -- cat /etc/nginx/conf.d/www.conf server { server_name myapp.magedu.com; listen 80; root /data/web/html; }
#注释:表示已经挂载成功
|
查看nginx是否加载配置
1
| [root@master-1 app]# kubectl exec -it nginx-test4
|
使用 ConfigMap 的限制条件
- 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、ln 命令)应用所用的实际配置目录下。