13.ConfigMap资源之该用-from-literal还是-from-file
1.什么是ConfigMap?
ConfigMap(简称CM)允许你把配置文件从image镜像本地中解耦出来,来保持集装箱化应用的便携性。
ConfigMap可以通过监听在配置文件、命令行参数、环境变量等其他配置的架构中,然后在你的pod容器和系统组件运行时,达到配置的加载功能。
同时ConfigMap也建议将那些,可以使得你更好的进行变更和管理配置文件的配置,从pod和系统组件中剥离出来。
ConfigMap存储配置信息是很有用的,由于它是非加密性的配置,我强烈建议大家只保存非敏感的配置信息。
2.应用场景定义
正如上面所说,ConfigMap是非加密性的配置保存,你应该牢记,切勿在ConfigMap中保存敏感信息;
如果你需要保存敏感信息,建议使用Secret。
下一章节讲secret
3.如何创建一个ConfigMap
和其他基础对象、控制器类似,你也可以通过两种方式来申明一个ConfigMap:
1)命令行方式:
kubectl create configmap [NAME] [DATA]:
例如:kubectl create cm filebeat-cfg -n config --from-literal=redis_host="redis.test.com" --from-literal=log_level=“info”
你需要注意的是,通过命令行申明的方式,内部也细分了两种:
从字面读取(–from-literal)和从目录(–from-file)读取,下面我将给你讲解他们是如何使用的。
1.–from-literal
从字面读取的好处就是快速和便捷,你可以通过关键字参数的形式(**kargs),将配置信息直接传递至configmap,然后在pod启动的时候进行加载;
同时这个方式的弊端就是,变量的更新是做不到的,毕竟环境变量的加载只有在容器运行时才起作用。
kubectl create cm filebeat-cfg -n config --from-literal=redis_host="redis.test.com" --from-literal=log_level=“info”
其中,redis_host是变量名,redis.test.com就是我们定义的变量值了,是不是一目了然了呢?
2.–from-file
从目录读取的好处就是,允许你更好的进行配置文件的管理。
你可以想象成传统架构下,我们是如何管理nginx的vhost的,又比如,在prometheus中,对于File SD(基于文件的服务发现)的使用,其实和此处都是一个道理。
kubectl create configmap nginx-cfg -n config --from-file=/root/mainfasts/conf.d/
--from-file指明需要从那个目录下面读取,目录下的文件只要按照一定格式就可以成功被加载到了。
你需要注意的是:
通过目录加载ConfigMap,其变量名是文件名,变量值是文件内容!!!
2)yaml配置文件方式:
当然,你也可以通过yaml的方式,像申明其他资源一样,去申明一个ConfigMap,这并没有什么不同,只要注意它的配置字段就好了。
你可以通过下面命令找到ConfigMap的配置字段信息:
kubectl explain configmap
我这里给了一个ingress的ConfigMap的参考配置文件:configmap-demo.yaml
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"annotations":{},"labels":{"app.kubernetes.io/name":"ingress-nginx","app.kubernetes.io/part-of":"ingress-nginx"},"name":"nginx-configuration","namespace":"ingress-nginx"}}
creationTimestamp: "2019-12-05T07:10:54Z"
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
name: nginx-configuration
namespace: ingress-nginx
resourceVersion: "7097"
selfLink: /api/v1/namespaces/ingress-nginx/configmaps/nginx-configuration
uid: d9646c79-7c33-4afd-b3cc-03da176f6b53
4.如何使用一个ConfigMap
前面,我讲了很多都是如何去创建、申明一个ConfigMap,那创建好的配置,我们如何去使用呢?
接下来,我将为大家简单讲解,如何使用!最后会有更详细的实战环节。
1.–from-literal
如果你使用此方法进行申明,那你就得使用环境变量的方式,让容器读取到配置:
apiVersion: v1
kind: Pod
spec:
containers:
- name: nginx
image: nginx
env:
- name: nginx_host
valueFrom:
configMapKeyRef: #从configmap中读取
key: redis_host #上面我们定义的变量名
具体字段配置,请查阅:
kubectl explain pod.spec.containers.env.name.valueFrom.configMapKeyRef
2.–from-file
通过目录的方式进行配置加载,你还需要配合使用volume进行配置的读取,具体如下所示
apiVersion: v1
kind: Pod
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: nginx-conf #自定义volumes的名字,这里是引用
mountPath: /etc/nginx/conf.d/ #挂载到Pod中的路径
volumes:
- name: nginx-conf #自定义volumes的名字,这里是定义
configMap:
defaultMode: 0644
name: nginx-cfg #configMap名
items:
- key: server1.conf #configMap中的变量名
path: server1_new.conf #期望以什么名字保存在Pod目录中
具体字段配置,请查阅:
kubectl explain pod.spec.volumes.configMap
5.实战-from-literal
再次提醒:此方式的环境变量,Pod生命周期内的配置变更是不会热加载的。
1.首先我们在config的namespace中,创建一个名为filebeat-cfg的configmap用于测试,具体如下
kubectl create cm filebeat-cfg -n config --from-literal=redis_host="redis.test.com" --from-literal=log_level=“info”
2.然后,检查CM(configmap简称)配置情况,是否被成功读取
[root@centos-1 dingqishi]# kubectl get cm filebeat-cfg -n config -o yaml
apiVersion: v1
data:
log_level: info
redis_host: redis.test.com
kind: ConfigMap
metadata:
creationTimestamp: "2019-12-04T08:17:32Z"
name: filebeat-cfg
namespace: config
resourceVersion: "70462"
selfLink: /api/v1/namespaces/config/configmaps/filebeat-cfg
uid: 2cc00197-60b6-4850-9c24-ef4f385ae058
3.编辑nginx-cmcmd.yaml,并使用valueFrom的方式来加载我们的配置变量
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: config
spec:
containers:
- name: nginx
image: nginx
env:
- name: nginx_host
valueFrom:
configMapKeyRef: #从configmap中读取
key: redis_host
name: filebeat-cfg
- name: nginx_log_level
valueFrom:
configMapKeyRef:
key: log_level
name: filebeat-cfg
- name: nginx_static_value #静态配置
value: "123123"
4.最后apply -f启动Pod,并检查变量加载情况,发现已经能成功加载到变量了(nginx_host、nginx_log_level和nginx_static_value)
[root@centos-1 mainfasts]# kubectl exec -it nginx -n config -- /bin/sh
# printenv
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
nginx_host=redis.test.com
nginx_log_level=info
HOSTNAME=nginx
HOME=/root
PKG_RELEASE=1~buster
TERM=xterm
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
NGINX_VERSION=1.17.6
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
nginx_static_value=123123
KUBERNETES_PORT_443_TCP_PORT=443
NJS_VERSION=0.3.7
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
5.接着,我们尝试修改变量值,看一下pod生命周期内,是否真的不会被读取到呢?
编辑(edit)配置文件,修改对应变量(redis_host: www.baidu.com)。
[root@centos-1 dingqishi]# kubectl edit cm filebeat-cfg -n config -o yaml
[root@centos-1 dingqishi]# kubectl get cm filebeat-cfg -n config -o yaml
apiVersion: v1
data:
log_level: warning
redis_host: www.baidu.com
kind: ConfigMap
metadata:
creationTimestamp: "2019-12-04T08:17:32Z"
name: filebeat-cfg
namespace: config
resourceVersion: "76435"
selfLink: /api/v1/namespaces/config/configmaps/filebeat-cfg
uid: 2cc00197-60b6-4850-9c24-ef4f385ae058
6.继续观察Pod内变量,发现真的没有改变,和我们预期一致,测试成功!
# printenv
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
nginx_host=redis.test.com
nginx_log_level=info
HOSTNAME=nginx
HOME=/root
PKG_RELEASE=1~buster
TERM=xterm
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
NGINX_VERSION=1.17.6
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
nginx_static_value=123123
KUBERNETES_PORT_443_TCP_PORT=443
NJS_VERSION=0.3.7
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
7.删除Pod,重新apply,发现配置才会更新!
[root@centos-1 mainfasts]# kubectl delete -f pod-cfg.yaml
pod "nginx" deleted
[root@centos-1 mainfasts]# kubectl apply -f pod-cfg.yaml
pod/nginx created
[root@centos-1 mainfasts]# kubectl exec -it nginx -n config -- /bin/sh
# printenv
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
nginx_host=www.baidu.com
nginx_log_level=warning
HOSTNAME=nginx
HOME=/root
PKG_RELEASE=1~buster
TERM=xterm
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
NGINX_VERSION=1.17.6
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
nginx_static_value=123123
8.结论:
环境变量只会在Pod生成时加载,修改configMap,并不会被热加载到Pod中,需要重新生成Pod才行
9.如何解决Pod中配置热加载的问题呢?请看下面的例子,这时候就需要用–from-file了!
6.实战-from-file
1.首先我们先准备好所需的文件和目录:创建nginx所需目录和虚拟主机配置
[root@centos-1 conf.d]# pwd
/root/mainfasts/conf.d
[root@centos-1 conf.d]# cat server1.conf
server {
listen 80;
server_name www.baidu.com;
location / {
root /server1.html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
[root@centos-1 conf.d]# cat server2.conf
server {
listen 80;
server_name www.nginx.com;
location / {
root /server2.html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
2.然后,以–from-file的形式导入至configmap
kubectl create configmap nginx-cfg -n config --from-file=/root/mainfasts/conf.d/
3.为了养成一个好习惯,检查configmap配置载入情况还是很有必要的。
你有没有发现:
文件名成了变量名,文件内容成了变量值,他们以|进行分割
[root@centos-1 conf.d]# kubectl get cm -n config -o yaml
apiVersion: v1
items:
- apiVersion: v1
data:
log_level: warning
redis_host: www.baidu.com
kind: ConfigMap
metadata:
creationTimestamp: "2019-12-04T08:17:32Z"
name: filebeat-cfg
namespace: config
resourceVersion: "76435"
selfLink: /api/v1/namespaces/config/configmaps/filebeat-cfg
uid: 2cc00197-60b6-4850-9c24-ef4f385ae058
- apiVersion: v1
data:
server1.conf: |
server {
listen 80;
server_name www.baidu.com;
location / {
root /server1.html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server2.conf: |
server {
listen 80;
server_name www.nginx.com;
location / {
root /server2.html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
kind: ConfigMap
metadata:
creationTimestamp: "2019-12-04T10:11:23Z"
name: nginx-cfg
namespace: config
resourceVersion: "81456"
selfLink: /api/v1/namespaces/config/configmaps/nginx-cfg
uid: 86374cc1-605c-4b4a-abfa-769df0a4a94d
kind: List
metadata:
resourceVersion: ""
selfLink: ""
4.这里使用volumeMounts的方式,将configMap的资源挂载到pod内,编辑nginx-cmfiles-volumes.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: config
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: nginx-conf #自定义volumes的名字
mountPath: /etc/nginx/conf.d/ #挂载到Pod中的路径
volumes:
- name: nginx-conf #自定义volumes的名字
configMap:
defaultMode: 0644
name: nginx-cfg #configMap名
items:
- key: server1.conf #configMap中的变量名
path: server1_new.conf #期望以什么名字保存在Pod目录中
- key: server2.conf
path: server2_new.conf
5.apply -f配置文件,并进入Pod查看配置读取和挂载情况,是不是很神奇!
配置文件已经通过configmap的方式形成了。
[root@centos-1 mainfasts]# kubectl exec -it nginx -n config -- /bin/sh
# cd /etc/nginx/conf.d
# ls
server1_new.conf server2_new.conf
# cat server1_new.conf
server {
listen 80;
server_name www.baidu.com;
location / {
root /server1.html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# cat server2_new.conf
server {
listen 80;
server_name www.nginx.com;
location / {
root /server2.html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
6.这里我们还是要来测试一下热更新的问题。
修改configmap参数(分别将server_name修改成taobao和jingdong)
[root@centos-1 conf.d]# kubectl get cm nginx-cfg -n config -o yaml
apiVersion: v1
data:
server1.conf: |
server {
listen 80;
server_name www.taobao.com;
location / {
root /server1.html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server2.conf: |
server {
listen 80;
server_name www.jingdong.com;
location / {
root /server2.html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
kind: ConfigMap
metadata:
creationTimestamp: "2019-12-04T10:11:23Z"
name: nginx-cfg
namespace: config
resourceVersion: "87316"
selfLink: /api/v1/namespaces/config/configmaps/nginx-cfg
uid: 86374cc1-605c-4b4a-abfa-769df0a4a94d
7.几秒后Pod的配置文件也自动的进行了热更新
# cat server1_new.conf
server {
listen 80;
server_name www.taobao.com;
location / {
root /server1.html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# cat server2_new.conf
server {
listen 80;
server_name www.jingdong.com;
location / {
root /server2.html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
现在,你是否已经掌握ConfigMap的使用细节了呢?