玩转Configmap配置应用的各种姿势

时间:2022-09-26 15:15:45

在 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 会在不久后更新对应的文件,文件更新过程需要一些时间,最后会看到配置文件的变化。但是一般容器进程并不会监控文件的变化在载入之后,所以一般都是重启容器并载入配置的。