kubernets之configMap和secret
一 如何有效且更好的将配置写到pod的容器中
考虑一个问题,就是在传统的应用中,程序里面需要的配置一般以配置文件的形式或者shell脚本里面的参数是在执行的时候在命令行里面进行添加,但是在kubernets的pod中,应该如何将变量引入到pod的容器中呢?
二 容器启动的时候是如何将变量引入容器中的
2.1 了解ENTRYENTRYPOINT以及CMD
Dockerfile中两种指令分别代表容器启动时被调用的可执行程序以及参数
- ENTRYPOINT——定义容器启动时候的可执行程序
- CMD——指定参数传递给ENTRYPOINT的
- 当ENTRYPOINT不存在的时候CMD里面也可以当作容器启动时候的可执行程序
2.2 了解shell以及exec形式的区别
有以下两种形式的指令均可以作为容器的启动命令
- shell形式——如ENTRYPOINT node app.js
- exec形式——如ENTRYPOINT ['node','app.js']
- 两者的区别在于shell形式的启动进程将会以shell的形式启动,但是往往这是多余的,所以尽量使用exec的形式
三 在kubernets中覆盖命令以及参数
3.1 我们可以在pod中添加参数用以覆盖pod里面容器中的参数
apiVersion: v1 kind: pod ...... spec: - image: some/image command: [ "/bin/command" ] args: ["args1","args2","args3"]
- 在pod中我们用command来替换容器中的可执行文(等同于容器里面的entrypoint)
- 用args来替换容器中的 参数(等同于容器里面的cmd)
四 为容器设置环境变量
4.1 如前所述,容器化应用通常会使用环境变量的,同样在kubernets的pod中也支持使用环境的形式将配置写入到pod的容器中来供应用使用
...... kind: pod spec: containers: - image: luksa/fortune:env env: - name: INTERVAL value: "30"
- name: SECOND_VAR
value: "$(INTERVAL)bar"
name: html-generator
- 在环境变量中添加一个新的变量
- 可以看出环境变量的级别是容器级别而非pod级别的
- 甚至我们可以通过如上的形式来引用环境变量中的变量
- 这是一种方式,但是硬编码的形式不足之处在于无法对该pod进行复用
五 利用Configmap解耦配置
5.1 kubernets允许将配置选项分离到单独的资源对象中Configmap,本质上就是一个键值对映射,值既可以是一个短字面的量也可以是一个完整的配置文件,应用无须直接读取configmap,甚至都可以不知道它的存在,映射的内容通过环境变量或者卷文件的形式传递给容器,然后容器里面的应用通过${ENV_VAR}来进行引用,从而可以达到将configmap的条目当作命令行参数传递给进程的效果。
5.2 使用kubectl创建ConfigMap
k create configmap fortune-config --from-literal=sleep-interval=25
5.3 可以通过--from-literal参数为某个configmap添加多个键值对
k create configmap wxm_test_configmap --from-literal=name=wxm --from-literal=age=27 --from-literal=job=deploy
5.4 通过yaml文件创建configmap
apiVersion: v1
data:
firstkey:firstvalue
secondkey:secondvalue
kind: ConfigMap
metadata:
name: first-configmap
5.5 从文件内容创建configmap
k create configmap test-create-configmap-from-file-second --from-file=create-configmap-from-file.conf --from-file=wxm.conf [root@node01 configmap]# k get configmap test-create-configmap-from-file-second -o yaml apiVersion: v1 data: create-configmap-from-file.conf: | this is a test the content is nothing wxm.conf: | wq kind: ConfigMap metadata: creationTimestamp: "2021-01-04T06:59:34Z" name: test-create-configmap-from-file-second namespace: default resourceVersion: "2019025" selfLink: /api/v1/namespaces/default/configmaps/test-create-configmap-from-file-second uid: 66f19350-4e5a-11eb-ae9a-5254002a5691
- 从文件创建configmap的话和命令行创建configmap没有很大的差别,通过多次指定--from-file来指定文件路径进行创建
- 从文件创建configmap之后,文件的内容会被当作值,且文件名称会被当作键存储在kubernets集群中去
5.6 通过指定文件夹来创建configmap
k create configmap test-create-config-from-dir --from-file=/root/wxm/Chapter07/configmap k get configmap test-create-config-from-dir -o yaml apiVersion: v1 data: create-configmap-from-file.conf: | this is a test the content is nothing haha.conf: "\twrcdw fecs\n" wxm.conf: | wq kind: ConfigMap metadata: creationTimestamp: "2021-01-04T07:08:16Z" name: test-create-config-from-dir namespace: default resourceVersion: "2020190" selfLink: /api/v1/namespaces/default/configmaps/test-create-config-from-dir uid: 9db8ed42-4e5b-11eb-ae9a-5254002a5691
- 通过指定目录名称来创建configmap,目录下面所有的合法命名文件都会创建数据
六 给容器传递ConfigMap作为环境变量
6.1 通过yaml文件创建configmap内容如下所示
apiVersion: v1 kind: Pod metadata: name: fortune-env-from-configmap spec: containers: - image: luksa/fortune:env name: test-for-configmap env: - name: INTERVAL valueFrom: configMapKeyRef: name:fortune-config key: sleep-interval
6.2 进入创建的容器查看是否有渲染为环境变量
[root@node01 Chapter07]# k get po NAME READY STATUS RESTARTS AGE fortune 2/2 Running 0 7d4h fortune-env-from-configmap 1/1 Running 0 82s [root@node01 Chapter07]# k exec fortune-env-from-configmap -- env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=fortune-env-from-configmap INTERVAL=25 KUBERNETES_SERVICE_PORT=443 KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_PORT=tcp://10.96.0.1:443 KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_PORT=443 KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1 KUBERNETES_SERVICE_HOST=10.96.0.1 HOME=/root
- 可以看到确实会将集群中之前存在的configmap中sleep-interval的值渲染到了容器的变量
- 这里设置了一个环境变量INTERVAL,并将configmap的sleep-interval传递给了它
- 值得说明的是,如果pod里面引用了不存在的configmap的话,容器会被正常调度,但是会启动失败,当被引用的configmap被创建的时候,失败的容器会被自动重启
6.3 将所有的configmap的条例全部渲染到容器的环境变量中
apiVersion: v1 kind: Pod meatdata: name: test-for-all-env-from-configmap spec: containers: - image: luksa/fortune:env name: test-for-env-from-configmap envFrom: - prefix: CONFIG_ configMapRef: name: wxm-test-configmap
- 这个pod会引用wxm-test-configmap这个的下面的所有条目渲染为环境变量
- prefix这个参数为当各个变量添加前缀
6.4 查看创建的容器里面是否有这些环境变量
[root@node01 Chapter07]# k exec test-for-all-env-from-configmap -- env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=test-for-all-env-from-configmap CONFIG_age=27 CONFIG_job=deploy CONFIG_name=wxm KUBERNETES_SERVICE_PORT=443 KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_PORT=tcp://10.96.0.1:443 KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_PORT=443 KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1 KUBERNETES_SERVICE_HOST=10.96.0.1 HOME=/root
- 可以看到之前创建的configmap都渲染到了容器里面
6.5 还可以将configmap中条目当作参数传递给容器中主进程
apiVersion: v1 kind: Pod metadata: name: fortune-args-from-configmap spec: containers: - image: luksa/fortune:args env: - name: INTERVAL valueFrom: configMapKeyRef: name: fortune-config key: sleep-interval args: ["$(INTERVAL)"]
- 添加args参数将已经渲染到容器里面的环境变量的参数当作命令行参数传递给容器的主进程
6.6 使用configmap卷将条目暴露为文件
apiVersion: v1 kind: Pod metadata: name: fortune-configmap-volume spec: containers: - image: nginx:alpine name: web-server volumeMounts: - name: config mountPath: /etc/nginx/conf.d readOnly: true volumes: - name: config configMap: name: fortune-config items: - key: my-nginx-config.conf path: gzip.conf
- 将configmap以configmap卷的形式挂载到容器当中
- 并将指定的条例暴露为卷,其余的则会被渲染为环境变量
- 有一点需要说明的是,挂载卷到某个文件夹,会使该文件夹里面所有的内容都会被隐藏起来
6.7 如何将文件夹挂载到某个文件夹下面并且不会使其中的文件被隐藏呢?
apiVersion: v1 kind: Pod metadata: name: fortune-configmap-volume-bak-2 spec: containers: - image: nginx:alpine name: web-server volumeMounts: - name: config mountPath: /etc/wxmconfig.conf subPath: gzip.conf readOnly: true volumes: - name: config configMap: name: fortune-config
defaultMode: "6600" items: - key: my-nginx-config.conf path: gzip.conf
- 这个例子中,通过将fortune-config的configmap中的my-nginx-config.conf条目渲染成gzip的configmap卷
- 之后挂载到web-server /etc/wxmconfig.conf下面,这么做的好处是使得/etc下面的内容不会被隐藏
- 但是同样有个缺点就是无法被更新
- defaultMode:参数可以指定configmap挂载的权限
6.8 之前提到的,为了能够快速替换容器中的配置再不重启容器的情况下,通过pod中的容器挂载configmap卷,即可快速更新容器中的内容
apiVersion: v1 kind: Pod metadata: name: fortune-configmap-volume-2 spec: containers: - image: nginx:alpine name: web-server volumeMounts: - name: config mountPath: /etc/nginx/conf.d readOnly: true volumes: - name: config configMap: name: fortune-config
- 这个pod挂载了fortune-config的configmap卷
更改configmap卷
apiVersion: v1 data: my-nginx-config.conf: | server { listen 80; server_name www.kubia.com; gzip on; gzip_types text/plain application/xml; location / { root /usr/share/nginx/html; index index.html index.htm; } } sleep-interval: | 28 kind: ConfigMap metadata: creationTimestamp: "2021-01-04T08:37:05Z" name: fortune-config namespace: default resourceVersion: "2063247" selfLink: /api/v1/namespaces/default/configmaps/fortune-config uid: 067d2f8c-4e68-11eb-ae9a-5254002a5691
[root@node01 Chapter07]# k exec fortune-configmap-volume-2 -- cat /etc/nginx/conf.d/sleep-interval 28
- 将之前sleep-interval的内容为28,经过一段时间后,configmap里面的内容被替换为28
- 有一点疑问是渲染到环境变量里面之后的值无法更改
- 是否可以通过修改configmap关联的文件来修改configmap的内容
- pod里面的文件是如何被更新的,是通过连接一个..data/linkfile的文件,每次被更新之后linkfile会被更新之后指向被更新的文件如下所示
- 有一点需要注意的是挂载的是容器的单个文件而不是卷,则内容不会被更新
[root@node01 Chapter07]# k exec fortune-configmap-volume-2 -- ls -lA /etc/nginx/conf.d/ total 0 drwxr-xr-x 2 root root 56 Jan 4 14:26 ..2021_01_04_14_26_37.288908214 lrwxrwxrwx 1 root root 31 Jan 4 14:26 ..data -> ..2021_01_04_14_26_37.288908214 lrwxrwxrwx 1 root root 27 Jan 4 14:14 my-nginx-config.conf -> ..data/my-nginx-config.conf lrwxrwxrwx 1 root root 21 Jan 4 14:14 sleep-interval -> ..data/sleep-interval