Kubernetes

kubernetes(k8s) – 配置ConfigMap

概念


ConfigMap的功能在k8s1.2版本中引入的,许多应用程序会从配置文件,命令行参数或环境变量中读取配置信息。ConfigMap API会给我们提供了向容器中注入配置信息的机制,ConigMap可以被用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制的对象

1. 为什么需要configmap


我们经常都需要为我们的应用程序配置一些特殊的数据,比如密钥、Token 、数据库连接地址或者其他私密的信息。你的应用可能会使用一些特定的配置文件进行配置,比如settings.py文件,或者我们可以在应用的业务逻辑中读取环境变量或者某些标志来处理配置信息。我们要做到这个,有好多种方案,比如:

  • 我们可以直接在打包镜像的时候写在应用配置文件里面,但是这种方式的坏处显而易见而且非常明显。
  • 我们可以在配置文件里面通过 env 环境变量传入,但是这样的话我们要修改 env 就必须去修改 yaml 文件,而且需要重启所有的 container 才行。(通过env设置不同的环境,使用不同的yaml配置文件)
  • 我们可以在应用启动的时候去数据库或者某个特定的地方拿,没问题!但是第一,实现起来麻烦;第二,如果配置的地方变了怎么办?

当然还有别的方案,但是各种方案都有各自的问题。

而且,还有一个问题就是,如果说我的一个配置,是要多个应用一起使用的,以上除了第三种方案,都没办法进行配置的共享,就是说我如果要改配置的话,那得一个一个手动改。假如我们有 100 个应用,就得改 100 份配置,以此类推……

kubernetes 对这个问题提供了一个很好的解决方案,就是用 ConfigMap 和 Secret。

有很多种方案可以将项目 和 项目的配置解耦:

configMap就是让项目镜像 和 配置、环境变量、配置文件等配置数据 解耦,保证镜像的可移植性

  • ConfigMap功能在kubernetes1.2版本中引入,许多应用程序会从配置文件,命令行参数或环境变量中读取配置信息,ConfigAPI给我们提供了向容器中注入配置信息的机制,ConfigMap可以被用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制大对象。
  • ConfigMap对像是一系列配置的集合,k8s会将这一集合注入到对应的Pod对像中,并为容器成功启动使用。注入的方式一般有两种,一种是挂载存储卷,一种是传递变量。ConfigMap被引用之前必须存在,属于名称空间级别,不能跨名称空间使用,内容明文显示。ConfigMap内容修改后,对应的pod必须重启或者重新加载配置(支持热更新的应用,不需要重启)。
  • Secret类似于ConfigMap,是用Base64加密,密文显示,一般存放敏感数据。一般有两种创建方式,一种是使用kubectl create创建,一种是用Secret配置文件。

2. 应用场景


应用场景:镜像往往是一个应用的基础,还有很多需要自定义的参数或配置,例如资源的消耗、日志的位置级别等等,这些配置可能会有很多,因此不能放入镜像中,Kubernetes中提供了Configmap来实现向容器中提供配置文件或环境变量来实现不同配置,从而实现了镜像配置与镜像本身解耦,使容器应用做到不依赖于环境配置。

向容器传递参数:

Kubernetes如果需要向容器传递参数,可以在Yaml文件中通过command和args或者环境变量的方式实现。(不使用configMap的场景)

示例: demo-mpconft.yaml

apiVersion: v1
kind: Pod
metadata:
  name: print-mapenv
spec:
  containers:
  - name: env-print-demo
    image: centos:7.9.2009
    imagePullPolicy: IfNotPresent
    env: #添加了一个环境变量
    - name: GREETING
      value: "hello"
    - name: HONORIFIC
      value: "welcome"
    - name: NAME
      value: "Kubernetes is a good product"
    command: 
    - "echo" #执行echo命令
    args: 
    - "$(GREETING) $(HONORIFIC) $(NAME)"  #命令中传入了这些参数,引用的就是上面env中定义的

等待一会儿时间后,看到STATUS是Completed,Ready是0/1,pod中的容器已经结束了 因为我们yaml文件里就要求容器运行以后只执行一条指令,执行完成后就结束了

# 创建后,命令 echo hello welcome Kubernetes is a good product 将在容器中运行,也就是环境变量中的值被传递到了容器中。
# 查看pod就可以看出
# [root@k8s-master yaml]# kubectl logs print-mapenv
hello welcome Kubernetes is a good product

现在测试的这种情况是将配置数据和yaml资源文件耦合在一起了,接下来我们使用configMap分离

3. 创建ConfigMap


3.1 help文档

通过hepl命令可以查看configmap的用法:

# [root@k8s-master-155-221 configmap]# kubectl create  configmap --help
......
Aliases:
configmap, cm  #可以使用cm替代

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
  # 从文件创建 key1为键 文件内容为值
  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
  # 直接命令行给定,键为key1 值为config1
  kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2   

  # Create a new configmap named my-config from the key=value pairs in the file
  # 从文件创建 文件名为键 文件内容为值
  kubectl create configmap my-config --from-file=path/to/bar   

  # Create a new configmap named my-config from an env file
  kubectl create configmap my-config --from-env-file=path/to/bar.env

  Usage:
  kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run=server|client|none]
[options]

Use "kubectl options" for a list of global command-line options (applies to all commands).

3.2 使用目录创建

# 指定目录
# 创建configmap目录
# ls /opt/yaml/configmap

# 创建game.properties文件
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

# ui.propertes文件
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
# 创建configmap ,指令
# game-config-test :configmap的名称
# --from-file:指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容
# [root@k8s-master configmap]# kubectl create configmap game-config-test --from-file=/opt/yaml/configmap
configmap/game-config-test created

# 查看configmap文件
# [root@k8s-master configmap]# kubectl get cm 
NAME               DATA   AGE
game-config-test   2      24s


# 查看详细信息 -o 指定输出格式为yaml
# [root@k8s-master configmap]# kubectl get cm game-config-test -o yaml
apiVersion: v1
data:
  game.properties: |   # | 前是文件名; | 后是文件内容
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
  ui.propertes: |     # | 前是文件名; | 后是文件内容
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
kind: ConfigMap      # 类型
metadata:
  creationTimestamp: "2021-06-04T06:45:42Z"
  name: game-config-test   # 名称
  namespace: default       # 命名空间
  resourceVersion: "625034"
  uid: 8a7f0064-f816-4e70-a367-bd37371dcaec

data就是数据区,存放的就是配置文件,key就是文件名,后面”|”后跟的就是配置文件内容,这个是yaml语法

# 描述configmap
# [root@k8s-master configmap]# kubectl describe cm game-config-test -n default
Name:         game-config-test
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

ui.propertes:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

Events:  <none>

清空环境 [root@k8s-master configmap]# kubectl delete cm/game-config-test -n default

3.3 根据文件创建

只需要指定为一个文件就可以从单个文件中创建ConfigMap

# 指定创建的文件即可
kubectl create configmap game-config-test2 --from-file=/opt/yaml/configmap/game.properties

#查看
kubectl get cm game-config-test2 -o yaml

--from-file这个参数可以使用多次,可以分别指定game.properties,ui.propertes,效果和指定整个目录是一样的。

# [root@k8s-master configmap]# kubectl create configmap game-config-test2  --from-file=/opt/yaml/configmap/game.properties --from-file=/opt/yaml/configmap/ui.propertes  
configmap/game-config-test2 created

# [root@k8s-master configmap]# kubectl get cm -n default
NAME                DATA   AGE
game-config-test2   2      8s

# [root@k8s-master configmap]# kubectl get cm  game-config-test2 -n default -o yaml

# [root@k8s-master configmap]# kubectl describe cm game-config-test2 -n default

清理环境 kubectl delete cm/game-config-test2 -n default

3.4 文字创建

# 使用--from-literal 方式直接创建configmap
# Create the ConfigMap
# [root@k8s-master configmap]# kubectl create configmap test-config-1 --from-literal=key1=value1 --from-literal=key2=value2
configmap/test-config-1 created

# 获取cm
# [root@k8s-master configmap]# kubectl get cm -n default
NAME               DATA   AGE
test-config-1      2      17s

# 以yaml格式查看cm
# Get the ConfigMap Details for my-config
# [root@k8s-master configmap]# kubectl describe cm/test-config-1 -n default
Name:         test-config-1
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
key1:
----
value1
key2:
----
value2
Events:  <none>
[root@k8s-master configmap]# kubectl get cm test-config-1 -n default -o yaml
apiVersion: v1
data:
  key1: value1
  key2: value2
kind: ConfigMap
metadata:
  creationTimestamp: "2021-06-04T07:07:50Z"
  name: test-config-1
  namespace: default
  resourceVersion: "627044"
  uid: 8f904ca7-94f7-4262-98d9-69385130df28


# 描述cm
# [root@k8s-master configmap]# kubectl describe cm/test-config-1 -n default
Name:         test-config-1
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
key1:
----
value1
key2:
----
value2
Events:  <none>

使用文字方式创建,利用 --from-literal 参数传递配置信息,该参数可以使用多次。

3.5 直接方法(yaml文件方式创建)

ConfigMap 是一个 API 对象, 让你可以存储其他对象所需要使用的配置。 和其他 Kubernetes 对象都有一个 spec 不同的是,ConfigMap 使用 data 和 binaryData 字段。这些字段能够接收键-值对作为其取值。data 和 binaryData 字段都是可选的。data 字段设计用来保存 UTF-8 字节序列,而 binaryData 则 被设计用来保存二进制数据。
ConfigMap 的名字必须是一个合法的 DNS 子域名。
data 或 binaryData 字段下面的每个键的名称都必须由字母数字字符或者 -、_ 或 . 组成。在 data 下保存的键名不可以与在 binaryData 下 出现的键名有重叠。
从 v1.19 开始,你可以添加一个 immutable[长期不变的 / 不可改变的] 字段到 ConfigMap 定义中,创建 不可变更的 ConfigMap。

示例:

# 直接通过配置文件的方式创建
# vim configmap-test1.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: game-config
  namespace: default
data:
  game.properties: |
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
# [root@k8s-master configmap]# kubectl apply -f configmap-test1.yaml 
configmap/configmap-test-one created

# [root@k8s-master configmap]# kubectl  get cm/configmap-test-one -n default
NAME                 DATA   AGE
configmap-test-one   2      23s

# [root@k8s-master configmap]# kubectl  get cm/configmap-test-one -n default -o yaml
apiVersion: v1
data:
  game.properties: |
    firstkey=firstvaule
    secondkey=secondvalue
    thirdkey=thirdvalue
    forthkey=forthvalue
  ui.properties: |
    key11=value11
    key21=value21
    key31=value31
    key41=value41
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"game.properties":"firstkey=firstvaule\nsecondkey=secondvalue\nthirdkey=thirdvalue\nforthkey=forthvalue\n","ui.properties":"key11=value11\nkey21=value21\nkey31=value31\nkey41=value41\n"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"configmap-test-one","namespace":"default"}}
  creationTimestamp: "2021-06-04T07:22:57Z"
  name: configmap-test-one
  namespace: default
  resourceVersion: "628411"
  uid: 5f6bc92c-ac17-401d-8948-44c1fdcab7ea

# [root@k8s-master configmap]# kubectl describe cm/configmap-test-one -n default
Name:         configmap-test-one
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
ui.properties:
----
key11=value11
key21=value21
key31=value31
key41=value41

game.properties:
----
firstkey=firstvaule
secondkey=secondvalue
thirdkey=thirdvalue
forthkey=forthvalue

Events:  <none>

4. pod中应用

你可以使用四种方式来使用 ConfigMap 配置Pod 中的容器:

  • 容器 entrypoint 的命令行参数
  • 容器的环境变量
  • 在只读卷里面添加一个文件,让应用来读取
  • 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap

这些不同的方法适用于不同的数据使用方式。 对前三个方法,kubelet 使用 ConfigMap 中的数据在 Pod 中启动容器。

第四种方法意味着你必须编写代码才能读取 ConfigMap 和它的数据。然而, 由于你是直接使用 Kubernetes API,因此只要 ConfigMap 发生更改,你的应用就能够通过订阅来获取更新,并且在这样的情况发生的时候做出反应。 通过直接进入 Kubernetes API,这个技术也可以让你能够获取到不同的名字空间里的 ConfigMap。

先创建两个configMap

# 创建第一个configMap,   special.how: very   键名:键值
# vim configmap-for-pod.yaml
---
apiVersion: v1
kind: ConfigMap
metadata: 
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm

# 创建第二个configMap
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO

清空环境,删除之前操作创建的configmap:

# 创建configMap:
# [root@k8s-master configmap]# kubectl apply -f config-for-pod.yaml
configmap/special-config created
configmap/env-config created

# [root@k8s-master configmap]# kubectl get cm -n default
NAME               DATA   AGE
env-config         1      12m
special-config     2      12m

4.1 第一种方式: 在pod中使用ConfigMap来替代环境变量

  • valueFrom -> configMapKeyRef 通过valueFrom 导入
  • envFrom -> configMapRef 通过envFrom 导入
# vim configmap-instead-podenv.yaml
# 第一种方式: 在pod中使用configmap配置,使用ConfigMap来替代环境变量
apiVersion: v1
kind: Pod
metadata:
  name: configmap-instead-podenv
spec:
  containers:
    - name: cm-instead-podenv
      image: centos:7.9.2009
      imagePullPolicy: IfNotPresent
      command: 
      - "/bin/sh"
      -  "-c"
      - "env"   # 容器一但运行会执行命令/bin/sh -c env,会在控制台打印一下

      env: # 第一种导入方式:在env中导入
        - name: SPECIAL_LEVEL_KEY   # name是当前容器环境变量的key
          valueFrom:                # 通过valueFrom导入
            configMapKeyRef: 
              name: special-config  # name是要引入哪个configMap的name
              key: special.how      # key是要引入该configMap中的哪个key
        - name: SPECIAL_TYPE_KEY
          valueFrom: 
            configMapKeyRef: 
              name: special-config 
              key: special.type 
      envFrom:                      # 第二种导入方式,直接使用envFrom导入
        - configMapRef: 
            name: env-config 
  restartPolicy: Never
# 查看日志可以发现,环境变量注入到了容器中了,打印env就结束了
# [root@k8s-master configmap]# kubectl apply -f configmap-instead-podenv.yaml
pod/configmap-instead-podenv created
# [root@k8s-master configmap]# kubectl get po 
NAME                       READY   STATUS      RESTARTS   AGE
configmap-instead-podenv   0/1     Completed   0          15s
# [root@k8s-master configmap]# kubectl logs pod/configmap-instead-podenv -n default
MYNGINX_PORT_80_TCP=tcp://10.96.28.181:80
HOSTNAME=configmap-instead-podenv
MYNGINX_PORT=tcp://10.96.28.181:80
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
MYSERVICE_SERVICE_PORT=80
MYNGINX_PORT_80_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_HOST=10.96.0.1
MYNGINX_PORT_80_TCP_PORT=80
MYSERVICE_PORT_80_TCP_ADDR=10.96.17.78
SPECIAL_TYPE_KEY=charm   # 这里的env是导入的
MYSERVICE_PORT_80_TCP=tcp://10.96.17.78:80
SPECIAL_LEVEL_KEY=very   # 这里的env是导入的
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
MYSERVICE_PORT=tcp://10.96.17.78:80
SHLVL=1
HOME=/root
log_level=INFO     # 这里的env是导入的
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
MYSERVICE_PORT_80_TCP_PORT=80
MYSERVICE_PORT_80_TCP_PROTO=tcp
MYNGINX_SERVICE_HOST=10.96.28.181
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
MYNGINX_PORT_80_TCP_ADDR=10.96.28.181
MYSERVICE_SERVICE_HOST=10.96.17.78
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
MYNGINX_SERVICE_PORT=80
_=/usr/bin/env

清除环境:kubectl delete -f configmap-instead-podenv.yaml

4.2 第二种方式:用ConfigMap设置命令行参数

用作命令行参数,将 ConfigMap 用作命令行参数时,需要先把 ConfigMap 的数据保存在环境变量中,然后通过 $(VAR_NAME) 的方式引用环境变量.

#第二种方式:用ConfigMap设置命令行参数
# vim configmap-for-cmdargs.yaml
apiVersion: v1
kind: Pod
metadata:
  name: configmap-for-cmdargs
spec:
  containers:
    - name: configmap-for-cmdargs
      image: centos:7.9.2009
      imagePullPolicy: IfNotPresent
      command: 
      - "/bin/sh"
      - "-c"
      - "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)"    # 命令行中通过${}获取环境变量参数
      env:
        - name: SPECIAL_LEVEL_KEY  # name是当前容器环境变量的key
          valueFrom:  # 通过valueFrom引入
            configMapKeyRef: 
              name: special-config  # name是要引入哪个configMap的name
              key: special.how      # key是要引入该configMap中的哪个key
        - name: SPECIAL_TYPE_KEY 
          valueFrom: 
            configMapKeyRef: 
              name: special-config 
              key: special.type 
  restartPolicy: Never
# [root@k8s-master configmap]# kubectl apply -f configmap-for-cmdargs.yaml
pod/configmap-for-cmdargs created
# [root@k8s-master configmap]# kubectl get pods -n default
NAME                    READY   STATUS      RESTARTS   AGE
configmap-for-cmdargs   0/1     Completed   0          21s
# [root@k8s-master configmap]# kubectl logs pod/configmap-for-cmdargs -n default
very charm

4.3 第三种方式:通过数据卷挂载ConfigMap

在数据卷里面使用这个ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容,即在 Pod 中将 ConfigMap 当做文件使用。

# 第三种方式:通过数据卷挂载ConfigMap
# vim configmap-pass-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pass-volume
spec:
  containers:
    - name: configmap-pass-volume
      image: centos:7.9.2009
      imagePullPolicy: IfNotPresent
      command: 
      - "/sbin/init"
      volumeMounts: # 挂载数据卷
        - name: configmap-volume # 指定数据卷名
          mountPath: /etc/config # 表示把conifg-volume数据卷挂载到容器的/etc/config目录下
  volumes:    # 定义数据卷
    - name: configmap-volume #给数据卷起名
      configMap:          #数据卷挂载configmap
        name: special-config #挂载的configmap名字
  restartPolicy: Never
# [root@k8s-master configmap]# kubectl apply -f configmap-pass-volume.yaml
pod/configmap-pass-volume created

# [root@k8s-master configmap]# kubectl get pods -n default
NAME                    READY   STATUS    RESTARTS   AGE
configmap-pass-volume   1/1     Running   0          8s

登录容器查看/etc/config目录下是否挂载成功

# 进入容器中
# [root@k8s-master configmap]# kubectl exec -it pod/configmap-pass-volume -n default -- bash

# 查看挂载
# [root@configmap-pass-volume /]# ls /etc/config/
special.how  special.type
# [root@configmap-pass-volume /]# cd /etc/config/
# [root@configmap-pass-volume config]# cat special.how special.type 
verycharm

清除环境: kubectl delete -f configmap-pass-volume.yaml

4.4 被挂载的 ConfigMap 内容会被自动更新-热更新:

# ConfigMap的热更新
# vim configmap-hot-update.yaml
---
# 创建一个configmap
apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
  namespace: default
data:
  log_level: INFO
---
#  创建pod
apiVersion: apps/v1
kind: Deployment 
metadata: 
  name: my-nginx 
spec:
  replicas: 3
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      restartPolicy: Always
      containers:
        - name: my-nginx
          image: nginx:1.20.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80 
              name: http-port
              protocol: TCP
          volumeMounts: # 挂载数据卷
            - name: configmap-volume-nginx
              mountPath: /etc/config  # 挂载到容器的/etc/config目录下
      volumes:
        - name: configmap-volume-nginx
          configMap: # 数据卷挂载了上面的ConfigMap
            name: log-config
# [root@k8s-master configmap]# kubectl apply -f configmap-hot-update.yaml
configmap/log-config created
deployment.apps/my-nginx created

# [root@k8s-master configmap]# kubectl get pods -n default
NAME                       READY   STATUS    RESTARTS   AGE
my-nginx-6fd588dfc-f5dzc   1/1     Running   0          45s

# 进入容器查看挂载情况
# [root@k8s-master configmap]# kubectl exec -it pod/my-nginx-6fd588dfc-f5dzc -n default -- bash
# root@my-nginx-6fd588dfc-f5dzc:/# ls /etc/config/
log_level  # key是文件名
# root@my-nginx-6fd588dfc-f5dzc:/# cat /etc/config/log_level 
INFO   # value是文件内容

修改ConfigMap

# kubectl edit configmap log-config -n default
# 修改log-level的值为DEBUG等待大概10秒钟时间,再次查看环境变量的值

# [root@k8s-master configmap]# kubectl edit configmap log-config -n default
configmap/log-config edited

# 再次查看环境变量的值发生了变化
# [root@k8s-master configmap]# kubectl exec pod/my-nginx-6fd588dfc-f5dzc -n default -- cat /etc/config/log_level
DEBUG