貔貅云原生

貔貅云原生

ConfigMap

61
0
0
2023-12-05
ConfigMap

ConfigMap

ConfigMap 就是配置管理,应用经常会有从配置文件、命令行参数或者环境变量中读取一些配置信息的需求,这些配置信息我们肯定不会直接写死到应用程序中去的。ConfigMap 就给我们提供了向容器中注入配置信息的能力,不仅可以用来保存单个属性,还可以用来保存整个配置文件,比如我们可以用来配置一个 redis 服务的访问地址,也可以用来保存整个 redis 的配置文件。接下来我们就来了解下 ConfigMap 这种资源对象的使用方法。

创建

ConfigMap 资源对象使用 key-value 形式的键值对来配置数据,这些数据可以在 Pod 里面使用,如下所示的资源清单:

kind: ConfigMap
apiVersion: v1
metadata:
  name: cm-demo
  namespace: default
data:
  data.1: hello
  data.2: world
  config: |
    property.1=value-1
    property.2=value-2
    property.3=value-3

其中配置数据在 data 属性下面进行配置,前两个被用来保存单个属性,后面一个被用来保存一个配置文件。

我们可以看到 config 后面有一个竖线符 |,这在 yaml 中表示保留换行,每行的缩进和行尾空白都会被去掉,而额外的缩进会被保留。

lines: |
  我是第一行
  我是第二行
    我是吴彦祖
      我是第四行
  我是第五行

# JSON
{"lines": "我是第一行\n我是第二行\n  我是吴彦祖\n     我是第四行\n我是第五行"}

除了这两个指令之外,我们还可以使用竖线和加号或者减号进行配合使用,+ 表示保留文字块末尾的换行,- 表示删除字符串末尾的换行。

value: |
  hello

# {"value": "hello\n"}

value: |-
  hello

# {"value": "hello"}

value: |+
  hello

# {"value": "hello\n\n"} (有多少个回车就有多少个\n)

当然同样的我们可以使用kubectl create -f xx.yaml来创建上面的 ConfigMap 对象,但是如果我们不知道怎么创建 ConfigMap 的话,不要忘记 kubectl 是我们最好的帮手,可以使用kubectl create configmap -h来查看关于创建 ConfigMap 的帮助信息:

Examples:
  # Create a new configmap named my-config based on folder bar
  kubectl create configmap my-config --from-file=path/to/bar

  # Create a new configmap named my-config with specified keys instead of file basenames on disk
  kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt

  # Create a new configmap named my-config with key1=config1 and key2=config2
  kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2

我们可以看到可以从一个给定的目录来创建一个 ConfigMap 对象,比如我们有一个 testcm 的目录,该目录下面包含一些配置文件,redis 和 mysql 的连接信息,如下:

[root@kube01 ~]# ll test-cm/
总用量 8
-rw-r--r-- 1 root root 23 6月  27 15:25 mysql.config
-rw-r--r-- 1 root root 23 6月  27 15:24 redis.config

[root@kube01 ~]# cat test-cm/mysql.config
ip=127.0.0.1
port=3306

[root@kube01 ~]# cat test-cm/redis.config
ip=127.0.0.1
port=6379

可以通过第一种方式使用文件夹下面内容创建 configmap

[root@kube01 ~]# kubectl create configmap my-config-map --from-file=test-cm/
configmap/my-config-map created
[root@kube01 ~]# kubectl describe configmap my-config-map
Name:         my-config-map
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
redis.config:
----
ip=127.0.0.1
port=6379

mysql.config:
----
ip=127.0.0.1
port=3306


BinaryData
====

Events:  <none>

此时发现文件夹下面内容已经被创建成 configmap 形式,而 key 是文件夹下文件名,value 是文件内容。

除了通过文件目录进行创建,我们也可以使用指定的文件进行创建 ConfigMap,同样的,以上面的配置文件为例。

[root@kube01 ~]# kubectl create configmap my-redis-config --from-file=test-cm/redis.config
configmap/my-redis-config created
[root@kube01 ~]# kubectl describe configmap my-redis-config
Name:         my-redis-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
redis.config:
----
ip=127.0.0.1
port=6379


BinaryData
====

Events:  <none>

我们可以看到一个关联 redis.conf 文件配置信息的 ConfigMap 对象创建成功了,另外值得注意的是 --from-file 这个参数可以使用多次,比如我们这里使用两次分别指定 redis.conf 和 mysql.conf 文件,就和直接指定整个目录是一样的效果了。

另外,通过帮助文档我们可以看到我们还可以直接使用字符串进行创建,通过 --from-literal 参数传递配置信息,同样的,这个参数可以使用多次,格式如下:

[root@kube01 ~]# kubectl create configmap my-test-config --from-literal=db.host=127.0.0.1 --from-literal=db.port=3306
configmap/my-test-config created
[root@kube01 ~]# kubectl describe  configmap my-test-config
Name:         my-test-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
db.host:
----
127.0.0.1
db.port:
----
3306

BinaryData
====

Events:  <none>

使用

configmap 配置文件创建完毕后我们需要在 pod 里使用配置文件,使用方法有多种:

  • 设置环境变量的值;
  • 在容器里设置命令行参数;
  • 在数据卷里面挂载配置文件

首先使用的是设置环境变量的值

# env-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testcm1-pod
spec:
  containers:
    - name: testcm1
      image: busybox
      command: [ "/bin/sh", "-c", "env" ]
      env:
        - name: DB_IP
          valueFrom:
            configMapKeyRef:
              name: my-test-config
              key: db.host
        - name: DB_PORT
          valueFrom:
            configMapKeyRef:
              name: my-test-config
              key: db.port
      envFrom:
        - configMapRef:
            name: my-test-config

查看 Pod log 信息

[root@kube01 test-cm]# kubectl logs -f testcm1-pod
......
DB_PORT=3306
DB_IP=127.0.0.1
db.host=127.0.0.1
db.port=3306
......

我们可以看到 DB_HOST 和 DB_PORT 都已经正常输出了,另外的环境变量是因为我们这里使用 envFrom 直接把 my-test-config 给注入进来了,所以把他们的整个键值给输出出来了,这也是符合预期的。

另外我们也可以使用 ConfigMap来设置命令行参数,ConfigMap 也可以被用来设置容器中的命令或者参数值,如下 Pod:

# cat cmd-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testcm2-pod
spec:
  containers:
    - name: testcm1
      image: busybox
      command: [ "/bin/sh", "-c", "echo $(DB_IP) $(DB_PORT)" ]
      env:
        - name: DB_IP
          valueFrom:
            configMapKeyRef:
              name: my-test-config
              key: db.host
        - name: DB_PORT
          valueFrom:
            configMapKeyRef:
              name: my-test-config
              key: db.port

执行 apply 操作后查看 pod 日志

[root@kube01 test-cm]# kubectl logs -f testcm2-pod
127.0.0.1 3306

另外一种是非常常见的使用 ConfigMap 的方式:通过数据卷使用,在数据卷里面使用 ConfigMap,就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容,如下资源对象所示:

# cat mount-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testcm3-pod
spec:
  volumes:
    - name: config-volume
      configMap:
        name: my-config-map
  containers:
    - name: testcm3
      image: busybox
      command: [ "/bin/sh", "-c", "cat /etc/config/redis.config" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config

这边挂在的是整个 configmap 下的 key 与 value 形成文件在 pod 目录下,所以 pod 的 /etc/config 目录下有两个配置文件内容

通过日志查看发现 command 中脚本执行成功

[root@kube01 test-cm]# kubectl logs -f testcm3-pod
ip=127.0.0.1
port=6379

我们还可以指定 configmap 在 pod 中的挂载路径

apiVersion: v1
kind: Pod
metadata:
  name: testcm4-pod
spec:
  volumes:
    - name: config-volume
      configMap:
        name: my-config-map
        items:
        - key: mysql.config
          path: path/to/mysql.config
  containers:
    - name: testcm3
      image: busybox
      command: [ "/bin/sh", "-c", "cat /etc/config/path/to/mysql.config" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config

查看 Pod 日志发现挂载成功

[root@kube01 test-cm]# kubectl logs -f testcm4-pod
ip=127.0.0.1
port=3306

另外需要注意的是,当 ConfigMap 以数据卷的形式挂载进 Pod 的时,这时更新 ConfigMap(或删掉重建ConfigMap),Pod 内挂载的配置信息会热更新。这时可以增加一些监测配置文件变更的脚本,然后重加载对应服务就可以实现应用的热更新。