本篇文章是对 configmap 和 secret 的一个总结,详细信息可看 这里
在 container 的 image 中可通过 ENTRYPOINT 和 CMD 分别定义执行命令和参数。其中,ENTRYPOINT 定义容器启动时调用的可执行程序,CMD 指定传递给 ENTRYPOINT 的参数。
传递的参数可被 pod 的文本定义覆盖。并且,对于容器的主进程也有两种形式运行:
两种形式的执行示例如下:
注意,以 shell 形式运行的容器,其无法响应 Kubernetes 发送的 signal TERM 信号。即在容器 graceful shutdown 时,容器会忽视 kubernetes 发送的 signal TERM 信号。对于“规定”时间内未响应的容器,kubernetes 会再次发送 KILL 信号强制 kill 容器。详细信息看 这里。
对于容器的启动命令传递参数是常见的,那么对于配置文件呢?直接传递配置文件而不是环境变量该怎么做呢?
Kubernets 为应对这种场景(当然不局限于这一种场景),引入 configmap 的概念。configmap 和 pod 的定义解耦,使得同一份 configmap 可以被多个 pod 使用,同时 configmap 可以动态传递参数给容器,而不需要容器重启。
configmap 可以往容器中传递环境变量,命令行参数和文本文件。其中,传递文本文件是通过 configmap 卷的方式实现的。
类似于 configmap,secret 可以被看作为一种“加密”数据的 configmap,它存放的是“敏感”数据,如系统自带的 default serviceaccount,其访问 kubernetes 需要系统自带的 default token secret 实现认证,鉴权操作。
前面说了使用 configmap 的好处之一是可以动态更改容器配置,而不需要重启容器。试想如果配置通过 image 传递给 pod,如果需要更改 image 的配置则势必要重新部署 pod 以使 image 改动生效。此种场景下对业务势必有影响,而使用 configmap 则不需要。
创建 configmap 和 pod 如下:
[root@chunqiu configmap (Master)]# cat configmap.yaml kind: ConfigMap apiVersion: v1 metadata: name: initparse data: parse: | import json [root@chunqiu configmap (Master)]# cat statefulSet.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: chunqiu spec: replicas: 1 ... template: ... spec: volumes: - name: oam-init-volume configMap: name: initparse containers: - name: oam volumeMounts:$ - name: oam-init-volume$ mountPath: /etc/config/parse
使用 statefulSet 创建 pod。其中, configmap 以卷的形式 mount 到容器中的 /etc/config/parse 路径下:
[root@chunqiu configmap (Master)]# kubectl exec -it chunqiu-0 /bin/bash -n chunqiu [root@chunqiu-0:/] # cat /etc/config/parse/parse import json
可以看到 configmap 中的内容已被 mount 到容器中。进一步地,修改 configmap 中的配置,查看改动是否动态映射到容器中:
# 修改 configmap [root@chunqiu configmap (Master)]# kubectl edit configmaps initparse -n chunqiu configmap/initparse edited [root@chunqiu configmap (Master)]# kubectl describe configmaps initparse -n chunqiu Name: initparse Namespace: chunqiu Data ==== parse: ---- import json import log # 查看容器内文件是否改动 [root@chunqiu configmap (Master)]# kubectl exec -it chunqiu-0 /bin/bash -n chunqiu [root@chunqiu-0:/] # cat /etc/config/parse/parse import json import log
在另一个窗口 watch pod 的更新,发现 pod 未更新。可以看到改动生效了,且容器并未重启。
这里有几点需要注意的是:
[root@chunqiu-0:/etc/config/parse] # ls -lA total 0 drwxr-xr-x. 2 root root 19 Sep 6 15:41 ..2021_09_06_15_41_46.939921926 lrwxrwxrwx. 1 root root 31 Sep 6 15:41 ..data -> ..2021_09_06_15_41_46.939921926 lrwxrwxrwx. 1 root root 12 Sep 6 15:40 parse -> ..data/parse
映射到容器中的文本文件实际上是一个指向 ..data/parse 的软链接,该软链接经过层层链接最终指向文本为日期+时间+字符串的文本,该文本即是 kubernetes 映射到容器中的实际文件。可以看出,kubernetes 并不是对 configmap 的多次改动频繁更新,而是只更新一次。再次更新 configmap 查看文件文件内容:
# 更新 configmap 信息 [root@chunqiu configmap (Master)]# kubectl edit configmaps initparse -n chunqiu configmap/initparse edited [root@chunqiu configmap (Master)]# kubectl describe configmaps initparse -n chunqiu Name: initparse Data ==== parse: ---- import json import log import print # 查看容器中文本文件 [root@chunqiu-0:/etc/config/parse] # ls -lA total 0 drwxr-xr-x. 2 root root 19 Sep 6 15:59 ..2021_09_06_15_59_07.176029107 lrwxrwxrwx. 1 root root 31 Sep 6 15:59 ..data -> ..2021_09_06_15_59_07.176029107 lrwxrwxrwx. 1 root root 12 Sep 6 15:40 parse -> ..data/parse [root@chunqiu-0:/etc/config/parse] # cat /etc/config/parse/parse import json import log import print
可以看到,容器中的文本文件在过一段时间后更新,且最终链接到的文本文件亦被更新。
mount secret 到 pod 的方式和 configmap 类似,这里不做过多展开。值得一提的是 secret 中的数据保存在内存中,而不是硬盘:
[root@chunqiu-0:/etc/config/parse] # mount | grep parse /dev/sda5 on /etc/config/parse type xfs (ro,relatime,seclabel,attr2,inode64,noquota) [root@chunqiu-0:/etc/config/parse] # mount | grep service tmpfs on /run/secrets/kubernetes.io/serviceaccount type tmpfs (ro,relatime,seclabel)
可以看到,前面 configmap mount 到容器的文本文件,是以 xfs 形式保存在 sda5 这块硬盘上,而 secret mount 的文本文件是以 tmpfs 的形式保存在 node 上的内存中,数据不会被外部应用读写到,安全性更高。
这里简要提下 statefulSet 和 configmap,configmap 可以 mount 到多个由 statefulSet 管理的 pod 上。
对于 statefulSet 来说其默认的管理 pod 策略是 OrderedReady,即对于 statefulSet 的更新,scale,创建,删除等操作严格按照顺序进行,前一个 pod 状态没有 running 无法进行后一个 pod 操作。
不过,对于不需要定义这么严格的按顺序操作的 statefulSet 该怎么做呢?
Kubernetes 提供了 .spec.podManagementPolicy 为 Parallel 的参数来修改 pod 的管理策略。对于定义为 Parallel 的管理策略,pod 的创建,删除,scale 不需要按顺序 ready,不过 pod 的更新还是和 OrderedReady 类型保持一致。