在 k8s 中使用配置主要可以有以下几种方式来实现:
1. 向容器传递命令行参数
2. 为每个容器指定自定义的环境变量
3. 通过特殊类型的卷将配置文件挂载到容器中
在 k8s 中覆盖命令行参数
和 docker 内一样,可以定义容器启动中的执行程序和参数,并且镜像的 ENTRYPOINT 和 CMD 会被 k8s 中的 command 和 args 覆盖。
Docker | K8s | 描述 |
ENTRYPOINT | command | 容器中运行可执行文件 |
CMD | args | 传给可执行文件的参数 |
在pod定义中可以这样子声明 command 和 args
kind: Pod spec: containers: - image: some/image command: ["/bin/command"] args: ["args1", "args2", "args3"]
在容器中指定环境变量
在 k8s 中声明环境变量,在容器中可以通过环境变量来进行配置,但是需要注意的是,在每个容器中,k8s 会自动暴露相同命名空间下每个 service 对应的环境变量。虽然环境变量是被设置在 pod 的容器定义中,但是并非是 pod 级别的,比如说运维需要在容器中声明一些运维中特殊声明的环境变量。比如集群中的dns域名解析,当前宿主ip,当前pod的ip等等。
kind: Pod spec: containers: - image: xxx/image env: - name: INTERVAL value: "30" name: env-config-name ...
在环境变量中引用另一个环境变量
env: - name: OTHER_VAR value: "foo" - name: THIS_VAR value: "$(OTHER_VAR)_change"
利用 config 配置
上面的两种配置方式更适合运维和 k8s 工程师在配置集群的时候进行硬编码的配置,对于服务开发来说,这两种配置方式不太合适。
使用指令 kubectl 创建 ConfigMap
$ kubectl create configmap set-config --from-literal=keyname=config-key-value --from-literal=one=two $ kubectl describe configmap set-config Name: set-config Namespace: default Labels: <none> Annotations: <none> Data ==== keyname: ---- config-key-value one: ---- two Events: <none>
configmap可以混合使用不同的自选选项:完整文件夹、单独文件、自定义键名条目下的文件以及字面量等等。
$ kubectl create configmap my-config --from-file=foo.json ## 单独文件 --from-file=var=foobar.conf ## 自定义键名条目下的文件 --from-file=config-opts/ ## 完整的文件夹 --from-literral=some=thing ## 字面量
在实际应用中,我们一般这样子使用 configmap,利用 configmap 配置不同环境下的配置文件,然后利用 volume 来挂载到 pod 容器文件夹内。
例如,先声明两个configmap,一个代表正式环境,一个代表测试环境
$ vim config-learn-test.xml <conf> <env>test</env> <service> <servicename></servicname> <host></host> <port></port> </service> <conf> $ vim config-learn-prod.xml <conf> <env>prod</env> <service> <servicename></servicname> <host></host> <port></port> </service> <conf>
生成 configmap
$ kubectl create configmap config-learn-prod --from-file=config-learn.xml=/path/configmap-learn/config-learn-prod.xml $ kubectl create configmap config-learn-test --from-file=config-learn.xml=/path/configmap-learn/config-learn-test.xml
注意这里两个都使用的配置名称为 config-learn.xml,这样方便统一配置名
创建 pod,并且声明需要的配置,如果环境是测试则选择 config-learn-test,如果环境为正式则选择 config-learn-prod
$ vim ./configmap-learn.yaml apiVersion: v1 kind: Pod metadata: name: configmap-learn spec: containers: - image: luksa/kubia name: kubia ports: - containerPort: 8080 protocol: TCP volumeMounts: - name: configname mountPath: /data/service/conf readOnly: true volumes: - name: configname configMap: name: config-learn-test
在生成的 pod 中去检验对应目录下的配置文件如下:
$ kubectl exec configmap-learn cat /data/service/conf/config-learn.xml
<conf>
<env>test</env>
<service>
<servicename></servicname>
<host></host>
<port></port>
</service>
<conf>
可以看到确实是采取的测试环境配置,而且如果此目录下有相同名字的配置文件,此文件会被覆盖。
编辑修改configmap
$ kubectl edit configmap config-learn-prod
# Please edit the object below. Lines beginning with a '#' will be ignored, # and an empty file will abort the edit. If an error occurs while saving this file will be # reopened with the relevant failures. # apiVersion: v1 data: config-learn.xml: | <conf> <env>prod</env> <service> <servicename></servicname> <host></host> <port></port> </service> <conf> kind: ConfigMap metadata: creationTimestamp: "2022-09-11T10:59:28Z" managedFields: - apiVersion: v1 fieldsType: FieldsV1 fieldsV1: f:data: .: {} f:config-learn.xml: {} manager: kubectl operation: Update time: "2022-09-11T10:59:28Z" name: config-learn-prod namespace: default resourceVersion: "23045374" selfLink: /api/v1/namespaces/default/configmaps/config-learn-prod uid: 79663144-2b5e-4e29-8c94-0469d5906e19
保存文件后关闭编辑器,configmap 会在不久后更新对应的文件,文件更新过程需要一些时间,最后会看到配置文件的变化。但是一般容器进程并不会监控文件的变化在载入之后,所以一般都是重启容器并载入配置的。