Kubernetes之configMap

我们知道,在几乎所有的应用开发中,都会涉及到配置文件的变更,比如说在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 #自定义pod内环境变量名称(必须是“大写”、“下划线”)
valueFrom:
configMapKeyRef:
name: cm-appvars #configmap的name
key: appdatadir #configmap的key
- 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
#编辑configmap
[root@k8s-master volumes]# kubectl edit cm cm-appvars
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: #将configmap自动生成为环境变量
- 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 #configmap name

# 注意:cm-appvars中有两个key-value键值对,也就是会在/etc/nginx/conf.d/创建两个文件,key为文件名,value为文件内容

验证是否是把两个key生成了两个文件,value是文件中的内容

1
2
[root@master-1 app]# kubectl exec -it nginx-test4 -- ls /etc/nginx/conf.d/
appdatadir apploglevel
1
2
3
#编辑configmap
[root@k8s-master volumes]# kubectl edit cm cm-appvars
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;
}
1
2
3
#使用文件名作为key,文件名作为value创建一个configmap
[root@master-1 app]# kubectl create configmap my-config --from-file=./www.conf

使用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 -- nginx -T

使用 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、ln 命令)应用所用的实际配置目录下。

Kubernetes之configMap
https://system51.github.io/2019/08/26/Kubernetes-configMap/
作者
Mr.Ye
发布于
2019年8月26日
许可协议