13.实践篇:ConfigMap资源之到底该用-from-literal还是-from-file
13.实践篇:ConfigMap资源之到底该用-from-literal还是-from-file
1.What is ConfigMap?
ConfigMap(简称CM)允许你把配置文件从image镜像本地中解耦出来,来保持集装箱化应用的便携性。
ConfigMap可以通过监听在配置文件、命令行参数、环境变量等其他配置的架构中,然后在你的pod容器和系统组件运行时,达到配置的加载功能。
同时ConfigMap也建议将那些,可以使得你更好的进行变更和管理配置文件的配置,从pod和系统组件中剥离出来。
ConfigMap存储配置信息是很有用的,由于它是非加密性的配置,我强烈建议大家只保存非敏感的配置信息。
2.应用场景定义
正如上面所说,ConfigMap是非加密性的配置保存,你应该牢记,切勿在ConfigMap中保存敏感信息;
如果你需要保存敏感信息,建议使用Secret。
下一章节讲secret
3.如何创建一个ConfigMap
和其他基础对象、控制器类似,你也可以通过两种方式来申明一个ConfigMap:
3.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)读取,下面我将给你讲解他们是如何使用的。
3.1.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就是我们定义的变量值了,是不是一目了然了呢?
3.1.2.--from-file
从目录读取的好处就是,允许你更好的进行配置文件的管理。你可以想象成传统架构下,我们是如何管理nginx的vhost的,又比如,在prometheus中,对于File SD(基于文件的服务发现)的使用,其实和此处都是一个道理。
kubectl create configmap nginx-cfg -n config --from-file=/root/mainfasts/conf.d/
--from-file指明需要从那个目录下面读取,目录下的文件只要按照一定格式就可以成功被加载到了。
你需要注意的是:
通过目录加载ConfigMap,其变量名是文件名,变量值是文件内容!!!
3.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,那创建好的配置,我们如何去使用呢?
接下来,我将为大家简单讲解,如何使用!最后会有更详细的实战环节。
4.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
4.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的使用细节了呢?
@版权声明:51CTO独家出品,未经允许不能转载,否则追究法律责任