ConfigMap

news2024/11/26 9:31:10

image-20230108193657317

目录

文章目录

    • 目录
    • 本节实战
    • 前言
    • 1、创建
      • :warning: yaml里易混淆的点
        • (1)`|`用法
        • (2)`|+`和`|-`用法
        • (3)`>`用法
      • 1.通过资源清单文件方法创建ConfigMap
      • 2.通过from-file关键字创建ConfigMap
        • (1)from-file 关键字:使用指定的目录进行创建 ConfigMap
        • (2)from-file 关键字:使用指定的文件进行创建 ConfigMap
        • (3)from-file 关键字:使用字符串进行创建ConfigMap
    • 2、使用
      • 1.使用 ConfigMap 来填充我们的环境变量
      • 2.使用 ConfigMap来设置命令行参数
      • 3.通过数据卷来使用ConfigMap
      • :warning: ConfigMap热更新&应用热更新
    • 3、使用SubPath
      • 1.subPath
      • 2.subPathExpr
    • 4、不可变更的 ConfigMap
    • 关于我
    • 最后

本节实战

实战项目
💘 实战:yaml中|和>测试-2023.1.10(测试成功)
💘 实战:ConfigMap创建测试-2023.1.8(测试成功)
💘 实战:使用 ConfigMap 来填充我们的环境变量-2023.1.14(测试成功)
💘 实战:使用 ConfigMap来设置命令行参数-2023.1.14(测试成功)
💘 实战:通过数据卷来使用ConfigMap-2023.1.14(测试成功)
💘 实战:在 ConfigMap 值被映射的数据卷里去控制路径-items-2023.1.14(测试成功)
💘 实战:ConfigMap里使用SubPath-2023.1.14(测试成功)
💘 实战:ConfigMap里使用subPathExpr-2023.1.15(测试成功)
💘 实战:不可变更的 ConfigMap-2023.1.15(测试成功)

前言

前面我们学习了一些常用的资源对象的使用,但是单纯依靠这些资源对象,还不足以满足我们的日常需求,一个重要的需求就是应用的配置管理敏感信息的存储和使用(如:密码、Token 、私钥等)、安全管控身份认证等等。

对于应用的可变配置在 Kubernetes 中是通过一个 ConfigMap 资源对象来实现的,ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时 Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件ConfigMap 将你的环境配置信息和容器镜像进行解耦,便于应用配置的修改。不过需要注意 ConfigMap 并不提供保密或者加密功能。如果你想存储的数据是机密的,则可以使用 Secret 对象,或者使用其他第三方工具来保证你的数据的私密性,而不是用 ConfigMap。

我们知道许多应用经常会有从配置文件、命令行参数或者环境变量中读取一些配置信息的需求,这些配置信息我们肯定不会直接写死到应用程序中去的,比如你一个应用连接一个 redis 服务,下一次想更换一个了的,还得重新去修改代码,重新制作一个镜像,这肯定是不可取的。而 ConfigMap 就给我们提供了向容器中注入配置信息的能力不仅可以用来保存单个属性,还可以用来保存整个配置文件,比如我们可以用来配置一个 redis 服务的访问地址,也可以用来保存整个 redis 的配置文件等等。

值得注意的是 ConfigMap 虽然也是一个 K8s 资源对象,但是和其他 Kubernetes 对象都有一个 spec 属性不同的是,ConfigMap 使用 data 和 binaryData 字段,这些字段能够接收键值对作为其值,data 和 binaryData 字段都是可选的,data 字段设计用来保存 UTF-8 字符串,而 binaryData 则被设计用来保存二进制数据作为 base64编码的字串。data 或 binaryData 字段下面的每个键的名称都必须由字母数字字符或者 -、_ 或 . 组成,在data 下保存的键名不可以与在 binaryData 下出现的键名有重叠。此外从 v1.19 版本开始,我们还可以添加一个immutable 字段到 ConfigMap 对象中,用于创建不可变更的 ConfigMap。

应用程序配置文件存储:ConfigMap的应用场景。

  • 将应用程序配置文件解耦出来,存放在k8s中。
  • 根据不同的业务环境,存放不同的应用配置文件。

你可以整一个nginx镜像,把它的配置文件给分离出来并存储到k8s的ConfigMap里面,然后再挂载到pod里进行使用。

image-20230108211904985

1、创建

⚠️ yaml里易混淆的点

ConfigMap对象yaml文件:

apiVersion: v1
kind: ConfigMap
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

⚠️ 注意:以下3种用法可能会比较容易混淆,多看几次就能记清楚了。(一般使用| |-2种用法就足够了)

(1)|用法

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

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

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

(2)|+|-用法

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

value: |
  hello
  hello

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

value: |-
  hello

# {"value": "hello"}

value: |+
  hello

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

(3)>用法

使用 > 右尖括号,用来表示折叠换行只有空白行才会被识别为换行,原来的换行符都会被转换成空格

lines: >
  我是第一行
  我也是第一行
  我仍是第一行
  我依旧是第一行

  我是第二行
  这么巧我也是第二行

# JSON
{"lines": "我是第一行 我也是第一行 我仍是第一行 我依旧是第一行\n我是第二行 这么巧我也是第二行"}

💘 实战:yaml中|和>测试-2023.1.10(测试成功)

image-20230114150853669

  • 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.25.4
   containerd://1.6.10
  • 实验软件(无)

  • 编写yaml文件

#cm-demo.yaml
apiVersion: v1
kind: ConfigMap
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
    
  lines: >
    我是第一行
    我也是第一行
    我仍是第一行
    我依旧是第一行
  
    我是第二行
    这么巧我也是第二行
    

image-20230111073452062

  • 部署并测试

image-20230111073745188

奇怪:这里不是第一次部署嘛?annotations这里为什么还会显示last-applied-configuration呢?……😢

总感觉这里的演示情况和前面理论部分有点出入:……😢

image-20230114150436732

前面的理论部分:

image-20230114150647368

image-20230114150736000

这里关于细节部分,还是有点疑惑……先就这样吧。

测试结束。😘

1.通过资源清单文件方法创建ConfigMap

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

apiVersion: v1
kind: ConfigMap
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 属性下面进行配置,前两个被用来保存单个属性,后面一个被用来保存一个配置文件

当然同样的我们可以使用kubectl create -f xx.yaml来创建上面的 ConfigMap 对象。

  • 注意:这里的key和value一定都是字符串

binaryData <map[string]string>

image-20230108195557650

2.通过from-file关键字创建ConfigMap

但是如果我们不知道怎么创建 ConfigMap 的话,不要忘记 kubectl 是我们最好的帮手,可以使用kubectl create configmap -h来查看关于创建 ConfigMap 的帮助信息:

[root@master1 ~]#kubectl create configmap --help
Create a config map based on a file, directory, or specified literal value.
……
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创建测试-2023.1.8(测试成功)

image-20230114151014010

  • 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.25.4
   containerd://1.6.10
  • 实验软件(无)

  • 创建测试文件

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

cd ~
mkdir testcm
cd testcm/
echo host=127.0.0.1 > redis.conf
echo port=6379 >> redis.conf

echo host=127.0.0.1 > mysql.conf
echo port=3306 >> mysql.conf

cat redis.conf
cat mysql.conf

(1)from-file 关键字:使用指定的目录进行创建 ConfigMap

  • 然后,我们就可以使用 from-file 关键字来创建包含这个目录下面所有配置文件的 ConfigMap:
[root@master1 ~]#kubectl create cm  cm-demo1 --from-file=testcm/
configmap/cm-demo1 created

其中 from-file 参数指定在该目录下面的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容。

  • 创建完成后,同样我们可以使用如下命令来查看 ConfigMap 列表:
[root@master1 ~]#kubectl get cm
NAME                  DATA   AGE
cm-demo1              2      46s
  • 可以看到已经创建了一个 cm-demo1 的 ConfigMap 对象,然后可以使用 describe 命令查看详细信息:
[root@master1 ~]#kubectl describe cm cm-demo1
Name:         cm-demo1
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
mysql.conf:
----
host=127.0.0.1
port=3306

redis.conf:
----
host=127.0.0.1
port=6379


BinaryData
====

Events:  <none>

我们可以看到两个 key 是 testcm 目录下面的文件名称,对应的 value 值就是文件内容。

  • 这里值得注意的是如果文件里面的配置信息很大的话,describe 的时候可能不会显示对应的值,要查看完整的键值,可以使用如下命令:
[root@master1 ~]#kubectl get cm cm-demo1 -oyaml
apiVersion: v1
data:
  mysql.conf: |
    host=127.0.0.1
    port=3306
  redis.conf: |
    host=127.0.0.1
    port=6379
kind: ConfigMap
metadata:
  creationTimestamp: "2023-01-08T13:55:22Z"
  name: cm-demo1
  namespace: default
  resourceVersion: "901730"
  uid: cbebf27b-f1b5-4b7c-bfe9-d3c07790a48d

(2)from-file 关键字:使用指定的文件进行创建 ConfigMap

除了通过文件目录进行创建,我们也可以使用指定的文件进行创建 ConfigMap。

  • 同样的,以上面的配置文件为例,我们创建一个 redis 的配置的一个单独 ConfigMap 对象:
[root@master1 ~]#kubectl create cm cm-demo2 --from-file=testcm/redis.conf -n default
configmap/cm-demo2 created
  • 查看
[root@master1 ~]#kubectl get cm cm-demo2
NAME       DATA   AGE
cm-demo2   1      17s
[root@master1 ~]#kubectl get cm cm-demo2 -oyaml
apiVersion: v1
data:
  redis.conf: |
    host=127.0.0.1
    port=6379
kind: ConfigMap
metadata:
  creationTimestamp: "2023-01-08T13:59:11Z"
  name: cm-demo2
  namespace: default
  resourceVersion: "902076"
  uid: 95b6f6ed-977a-4830-8124-2ce28a61eb96

我们可以看到一个关联 redis.conf 文件配置信息的 ConfigMap 对象创建成功了。

  • 另外值得注意的是 –from-file 这个参数可以使用多次,比如我们这里使用两次分别指定 redis.conf 和 mysql.conf 文件,就和直接指定整个目录是一样的效果了。
[root@master1 ~]#kubectl create cm cm-demo22 --from-file=testcm/redis.conf --from-file=testcm/mysql.conf -n default
configmap/cm-demo22 created
[root@master1 ~]#kubectl get cm cm-demo22
NAME        DATA   AGE
cm-demo22   2      10s
[root@master1 ~]#kubectl get cm cm-demo22 -oyaml
apiVersion: v1
data:
  mysql.conf: |
    host=127.0.0.1
    port=3306
  redis.conf: |
    host=127.0.0.1
    port=6379
kind: ConfigMap
metadata:
  creationTimestamp: "2023-01-08T14:01:14Z"
  name: cm-demo22
  namespace: default
  resourceVersion: "902262"
  uid: b044c573-35dc-4867-86ff-4d7cc07faa1b

(3)from-file 关键字:使用字符串进行创建ConfigMap

  • 另外,通过帮助文档我们可以看到我们还可以直接使用字符串进行创建,通过 --from-literal 参数传递配置信息,同样的,这个参数可以使用多次,格式如下:
[root@master1 ~]#kubectl create configmap cm-demo3 --from-literal=db.host=localhost --from-literal=db.port=3306
configmap/cm-demo3 created
[root@master1 ~]#kubectl get cm cm-demo3 -oyaml
apiVersion: v1
data:
  db.host: localhost
  db.port: "3306" #注意:这里的数字用引号阔起来了,被当做是字符串来处理
kind: ConfigMap
metadata:
  creationTimestamp: "2023-01-10T13:41:55Z"
  name: cm-demo3
  namespace: default
  resourceVersion: "905135"
  uid: b10d8e47-c9bf-46d1-8868-914f18ea490d

注意:一般数据较小的话,可以直接在资源配置清单里写一下,数据量比较大的话,就可以写到文件里进行创建使用。

测试结束。😘

2、使用

ConfigMap 创建成功了,那么我们应该怎么在 Pod 中来使用呢?我们可以使用四种方式来使用 ConfigMap 配置 Pod中的容器:

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

这些不同的方法适用于不同的数据使用方式,对前三个方法,kubelet 会使用 ConfigMap 中的数据在 Pod 中启动容器。第四种方法需要编写代码才能读取 ConfigMap 数据。

1.使用 ConfigMap 来填充我们的环境变量

💘 实战:使用 ConfigMap 来填充我们的环境变量-2023.1.14(测试成功)

image-20230114201700775

  • 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.25.4
   containerd://1.6.10
  • 实验软件(无)

  • 创建资源清单

#testcm1-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testcm1-pod
spec:
  containers:
    - name: testcm1
      image: busybox
      command: [ "/bin/sh", "-c", "env" ]
      env: #注意:这里是env方式
        - name: DB_HOST
          valueFrom:
            configMapKeyRef: #这里Ref翻译为引用
              name: cm-demo3
              key: db.host #注意:这个db.host仅仅只是cm-demo3这个ConnfigMap里的Key.
        - name: DB_PORT
          valueFrom:
            configMapKeyRef:
              name: cm-demo3
              key: db.port
      envFrom: #注意:这里是envFrom方式
        - configMapRef:
            name: cm-demo1
  • 我们来再次确认下之前创建好的cm
[root@master1 ~]#kubectl get cm cm-demo1 -oyaml
apiVersion: v1
data:
  mysql.conf: |
    host=127.0.0.1
    port=3306
  redis.conf: |
    host=127.0.0.1
    port=6379
kind: ConfigMap
metadata:
  creationTimestamp: "2023-01-08T13:55:22Z"
  name: cm-demo1
  namespace: default
  resourceVersion: "901730"
  uid: cbebf27b-f1b5-4b7c-bfe9-d3c07790a48d
[root@master1 ~]#kubectl get cm cm-demo3 -oyaml
apiVersion: v1
data:
  db.host: localhost
  db.port: "3306"
kind: ConfigMap
metadata:
  creationTimestamp: "2023-01-10T13:41:55Z"
  name: cm-demo3
  namespace: default
  resourceVersion: "905135"
  uid: b10d8e47-c9bf-46d1-8868-914f18ea490d
  • 部署上面的testcm1-pod.yaml并查看
[root@master1 ~]#kubectl apply -f testcm1-pod.yaml
pod/testcm1-pod created
[root@master1 ~]#kubectl get po
NAME          READY   STATUS      RESTARTS      AGE
testcm1-pod   0/1     Completed   2 (26s ago)   28s

#这个 Pod 运行后会输出如下所示的信息:
[root@master1 ~]#kubectl logs testcm1-pod
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=testcm1-pod
DB_PORT=3306 #这里
SHLVL=1
HOME=/root
mysql.conf=host=127.0.0.1  #特别,注意下这里:这里的key:value是一个整体,是作为文件名`mysql.conf`的value的;
port=3306

redis.conf=host=127.0.0.1  #这里
port=6379

KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
DB_HOST=localhost  #这里

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

符合预期,测试完成。😘

2.使用 ConfigMap来设置命令行参数

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

💘 实战:使用 ConfigMap来设置命令行参数-2023.1.14(测试成功)

image-20230114203348480

  • 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.25.4
   containerd://1.6.10
  • 实验软件(无)

  • 创建资源清单

#testcm2-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testcm2-pod
spec:
  containers:
    - name: testcm2
      image: busybox
      command: [ "/bin/sh", "-c", "echo $(DB_HOST) $(DB_PORT)" ]
      env:
        - name: DB_HOST
          valueFrom:
            configMapKeyRef:
              name: cm-demo3
              key: db.host
        - name: DB_PORT
          valueFrom:
            configMapKeyRef:
              name: cm-demo3
              key: db.port
  • 我们来再次确认下之前创建好的cm
[root@master1 ~]#kubectl get cm cm-demo3 -oyaml
apiVersion: v1
data:
  db.host: localhost
  db.port: "3306"
kind: ConfigMap
metadata:
  creationTimestamp: "2023-01-10T13:41:55Z"
  name: cm-demo3
  namespace: default
  resourceVersion: "905135"
  uid: b10d8e47-c9bf-46d1-8868-914f18ea490d
  • 部署并查看
[root@master1 ~]#kubectl apply -f testcm2-pod.yaml
pod/testcm2-pod created

#运行这个 Pod 后会输出如下信息:
[root@master1 ~]#kubectl logs testcm2-pod
localhost 3306

测试结束。😘

🍀 问题

注意:有的同学可能会说,既然我可以在容器中的命令行参数里使用这个变量,那么我是否可以在我的ConfigMap里去使用我的环境变量呢?

image-20230114203518722

3.通过数据卷来使用ConfigMap

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

💘 实战:通过数据卷来使用ConfigMap-2023.1.14(测试成功)

image-20230114205912965

  • 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.25.4
   containerd://1.6.10
  • 实验软件(无)

  • 创建资源清单

#testcm3-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testcm3-pod
spec:
  volumes:
    - name: config-volume
      configMap:
        name: cm-demo2
  containers:
    - name: testcm3
      image: busybox
      command: [ "/bin/sh", "-c", "cat /etc/config/redis.conf" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  • 我们来再次确认下之前创建好的cm
[root@master1 ~]#kubectl get cm cm-demo2 -oyaml
apiVersion: v1
data:
  redis.conf: |
    host=127.0.0.1
    port=6379
kind: ConfigMap
metadata:
  creationTimestamp: "2023-01-08T13:59:11Z"
  name: cm-demo2
  namespace: default
  resourceVersion: "902076"
  uid: 95b6f6ed-977a-4830-8124-2ce28a61eb96
  • 部署并测试
[root@master1 ~]#kubectl apply -f testcm3-pod.yaml
pod/testcm3-pod created
[root@master1 ~]#kubectl logs testcm3-pod
host=127.0.0.1
port=6379

符合预期,测试结束。😘

💘 实战:在 ConfigMap 值被映射的数据卷里去控制路径-items-2023.1.14(测试成功)

image-20230115090534317

  • 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.25.4
   containerd://1.6.10
  • 实验软件(无)

  • 当然我们也可以在 ConfigMap 值被映射的数据卷里去控制路径,如下 Pod 定义:

#testcm4-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testcm4-pod
spec:
  volumes:
    - name: config-volume
      configMap:
        name: cm-demo1
        items:
        - key: mysql.conf
          path: path/to/msyql.conf
  containers:
    - name: testcm4
      image: busybox
      command: [ "/bin/sh","-c","cat /etc/config/path/to/msyql.conf" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  • 我们来再次确认下之前创建好的cm
[root@master1 ~]#kubectl get cm cm-demo1 -oyaml
apiVersion: v1
data:
  mysql.conf: |
    host=127.0.0.1
    port=3306
  redis.conf: |
    host=127.0.0.1
    port=6379
kind: ConfigMap
metadata:
  creationTimestamp: "2023-01-08T13:55:22Z"
  name: cm-demo1
  namespace: default
  resourceVersion: "901730"
  uid: cbebf27b-f1b5-4b7c-bfe9-d3c07790a48d
  • 部署并测试
[root@master1 ~]#kubectl apply -f testcm4-pod
pod/testcm4-pod created
[root@master1 ~]#kubectl logs testcm4-pod
host=127.0.0.1
port=3306

符合预期,测试结束。😘

⚠️ ConfigMap热更新&应用热更新

另外需要注意的是,当 ConfigMap 以数据卷的形式挂载进 Pod 的时,这时更新 ConfigMap(或删掉重建ConfigMap),Pod 内挂载的配置信息会热更新kubelet 组件会在每次周期性同步时检查所挂载的 ConfigMap 是否为最新这时可以增加一些监测配置文件变更的脚本,然后重加载对应服务就可以实现应用的热更新以环境变量方式使用的ConfigMap 数据不会被自动更新,更新这些数据需要重新启动 Pod。

只有通过 Kubernetes API 创建的 Pod 才能使用 ConfigMap,其他方式创建的(比如静态 Pod)不能使用;ConfigMap 文件大小限制为 1MB (ETCD 的要求)。

💘 实战:测试ConfigMap热更新-2023.1.14(测试成功)

image-20230114212419180

  • 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.25.4
   containerd://1.6.10
  • 实验软件(无)

  • 创建资源清单

#testcm5-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testcm5-pod
spec:
  volumes:
    - name: config-volume
      configMap:
        name: cm-demo1
        items:
        - key: mysql.conf
          path: path/to/msyql.conf
  containers:
    - name: testcm4
      image: busybox
      command: [ "/bin/sh","-c"," cat /etc/config/path/to/msyql.conf;sleep 24h" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  • 查看之前的cm
[root@master1 ~]#kubectl get cm cm-demo1  -oyaml
apiVersion: v1
data:
  mysql.conf: |
    host=127.0.0.1
    port=3306
  redis.conf: |
    host=127.0.0.1
    port=6379
kind: ConfigMap
metadata:
  creationTimestamp: "2023-01-08T13:55:22Z"
  name: cm-demo1
  namespace: default
  resourceVersion: "901730"
  uid: cbebf27b-f1b5-4b7c-bfe9-d3c07790a48d
  • 部署资源并查看
[root@master1 ~]#kubectl apply -f testcm5-pod.yaml
pod/testcm5-pod created
[root@master1 ~]#kubectl logs testcm5-pod
host=127.0.0.1
port=3306
  • 更新configmap里的信息
[root@master1 ~]#kubectl edit cm cm-demo1
#将3306改成3307

image-20230114212113984

  • 查看pod打印日志及pod里的文件是否发生了变化
[root@master1 ~]#kubectl logs testcm5-pod
host=127.0.0.1
port=3306
[root@master1 ~]#kubectl exec -it testcm5-pod -- cat /etc/config/path/to/msyql.conf
host=127.0.0.1
port=3307

可以看到pod打印日志依然是3306,但pod容器里的文件已经发生了变化,符合预期。

测试结束。😘

🍀 问题:ConfigMap支持动态更改吗?pod启动后,更改ConfigMap。

大佬回答:

支持的。我记得大概有1min多的延迟,相当于任何的ConfigMap如果mount到pod里面,那么会有一个什么样的动作呢? 它会把这个ConfigMap从apiserver下下来,然后放在本地docker的一个DRI里面,然后通过docker的mount mount到里面去只要你的应用进程支持本地文件刷新的时候,它会重新去load,那么就可以动态更改。注意:我们有反复强调,以volume形式挂载到容器里的配置,是热更新,但不是实时更新,需要一定的加载时间!(关键看你的应用支不支持热加载!)

3、使用SubPath

1.subPath

上面我们介绍了可以将 ConfigMap 以数据卷的形式挂载到容器中去,但是如果原本容器目录下已经有一些文件或者数据,将数据挂载进去后便会覆盖容器目录下的数据,这个时候我们可以指定 volumeMounts.subPath 属性来指定卷内的子路径,而不是其根路径

注意:

subPath形式挂载的数据不能热更新,除非重建Pod。(这个就很尴尬了……要他有何用……

💘 实战:ConfigMap里使用SubPath-2023.1.14(测试成功)

image-20230115092422375

  • 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.25.4
   containerd://1.6.10
  • 实验软件(无)

  • 比如我们将一个 Nginx 容器的配置放置到一个 ConfigMap 对象中来进行管理:

#nginx-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: default
data:
  nginx.conf: |
    user  nginx;
    worker_processes  auto;
    
    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        include /etc/nginx/conf.d/*.conf;
    }
  • 然后我们将上面的配置文件挂载到容器中去使用,创建如下所示的一个资源对象:
# nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: web
          image: nginx:1.7.9
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config
              mountPath: /etc/nginx
      volumes:
        - name: config
          configMap:
            name: nginx-config
            items:
              - key: nginx.conf
                path: nginx.conf   
  • 按照我们的想法是将 ConfigMap 中的 nginx.conf 挂载到容器的 /etc/nginx 目录下面去,但是该目录下面原本已经有很多文件了,所以用上面的方式会将该目录中的数据覆盖掉,这样就会导致我们的 Nginx 应用启动失败。
[root@master1 ~]#kubectl apply -f nginx-config.yaml
configmap/nginx-config created
[root@master1 ~]#kubectl apply -f nginx-deploy.yaml
deployment.apps/nginx created

[root@master1 ~]# kubectl get pods -l app=nginx
NAME                     READY   STATUS             RESTARTS      AGE
nginx-5456544546-2nmt6   0/1     CrashLoopBackOff   3 (12s ago)   55s
[root@master1 ~]#kubectl logs nginx-5456544546-2nmt6
2023/01/15 01:16:41 [emerg] 1#0: open() "/etc/nginx/mime.types" failed (2: No such file or directory) in /etc/nginx/nginx.conf:14
nginx: [emerg] open() "/etc/nginx/mime.types" failed (2: No such file or directory) in /etc/nginx/nginx.conf:14

#注意:nginx下默认是有很多文件的
[root@master1 ~]#kubectl exec -it nginx-7498977d8c-r6sqx -- ls /etc/nginx
conf.d  fastcgi_params  koi-utf  koi-win  mime.types  nginx.conf  scgi_params  uwsgi_params  win-utf
  • 我们只需要在容器的 volumeMounts 中通过 subPath 指定下子路径即可:
# nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: web
          image: nginx:1.7.9
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf
      volumes:
        - name: config
          configMap:
            name: nginx-config
            items:
              - key: nginx.conf
                path: nginx.conf   

image-20230115092105030

  • 更新后我们的容器就可以正常启动了:
[root@master1 ~]# kubectl get pods -l app=nginx
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7498977d8c-r6sqx   1/1     Running   0          4s
[root@master1 ~]#kubectl logs nginx-7498977d8c-r6sqx
2023/01/15 01:23:03 [notice] 1#0: using the "epoll" event method
2023/01/15 01:23:03 [notice] 1#0: nginx/1.7.9
2023/01/15 01:23:03 [notice] 1#0: built by gcc 4.7.2 (Debian 4.7.2-5) 
2023/01/15 01:23:03 [notice] 1#0: OS: Linux 3.10.0-957.el7.x86_64
2023/01/15 01:23:03 [notice] 1#0: getrlimit(RLIMIT_NOFILE): 65536:65536
2023/01/15 01:23:03 [notice] 1#0: start worker processes
2023/01/15 01:23:03 [notice] 1#0: start worker process 6
2023/01/15 01:23:03 [notice] 1#0: start worker process 7

符合预期,测试结束。😘

2.subPathExpr

除此之外我们还可以使用带有扩展环境变量的 subPath ,该功能在 v1.17 版本已经进行稳定状态了,通过使用subPathExpr 字段可以基于 downward API 环境变量来构造 subPath 目录名,不过需要注意 subPath 和subPathExpr 属性是互斥的。

💘 实战:ConfigMap里使用subPathExpr-2023.1.15(测试成功)

image-20230115095952603

  • 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.25.4
   containerd://1.6.10
  • 实验软件(无)

  • 我们经常有在容器中创建以 Pod 名为路径的目录来保存日志数据,我们就可以使用该特性来实现。比如我们在 Pod 中使用subPathExpr 在 hostPath 卷的 /var/log 中创建目录 pod1 ,hostPath 卷采用来自 downward API 的Pod 名称生成目录名,然后宿主机目录 /var/log/pod1 被挂载到容器的 /logs 中。如下资源对象所示:

#test-subPathExpr.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
    - name: container1
      env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
      image: busybox:1.28
      command:
        [
          "sh",
          "-c",
          "while true; do echo 'Hello' >> /logs/hello.txt; sleep 1; done",
        ]
      volumeMounts:
        - name: log
          mountPath: /logs
          subPathExpr: $(POD_NAME) # 包裹变量名的是小括号,而不是大括号
  restartPolicy: Never
  volumes:
    - name: log
      hostPath:
        path: /var/log
  • 当我们创建上面的资源对象后会通过 downward api 获取到 POD_NAME 环境变量的值为 pod1,然后通过subPathExpr 会在宿主机的 /var/log 目录下面创建 pod1 子目录,然后和容器中的 /logs 目录进行映射,所以最终日志数据会出现在宿主机的 /var/log/pod1 目录下面。
[root@master1 ~]#kubectl get po pod1 -owide
NAME   READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod1   1/1     Running   0          43s   10.244.1.69   node1   <none>           <none>
[root@master1 ~]#ssh 172.29.9.62
Last login: Tue Dec 27 21:23:31 2022 from 172.29.0.1
[root@node1 ~]# tail -f /var/log/pod1/hello.txt
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
……

符合预期,测试结束。😘

4、不可变更的 ConfigMap

Kubernetes 特性 Immutable Secret 和 ConfigMaps 提供了一种将各个 Secret 和 ConfigMap 设置为不可变更的选项。对于大量使用 ConfigMap 的集群(至少有数万个各不相同的 ConfigMap 给 Pod 挂载)而言,禁止更改ConfigMap 的数据有以下好处:

  • 保护应用,使之免受意外(不想要的)更新所带来的负面影响。
  • 通过大幅降低对 kube-apiserver 的压力提升集群性能,这是因为系统会关闭对已标记为不可变更的 ConfigMap的 watch 操作。

此功能在 v1.21 版本就已经是稳定的特性了,可以通过 ImmutableEphemeralVolumes 特性门控来控制,我们只需要通过将 immutable 字段设置为 true 即可创建不可变更的 ConfigMap。

💘 实战:不可变更的 ConfigMap-2023.1.15(测试成功)

image-20230115153011799

  • 实验环境
实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.25.4
   containerd://1.6.10
  • 实验软件(无)

  • 编写配置清单

# immu-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: immu-cm
data:
  mysql.conf: |-
    host=127.0.0.1
    port=3306
immutable: true

一旦某 ConfigMap 被标记为不可变更,则无法逆转这一变化,也无法更改 data 或 binaryData 字段的内容,只能删除并重建 ConfigMap因为现有的 Pod 会维护一个已被删除的 ConfigMap 的挂载点,建议重新创建这些 Pods。

  • 部署上面的资源
[root@master1 ~]#kubectl apply -f immu-cm.yaml
configmap/immu-cm created
  • 当我们修改上面的 ConfigMap 数据内容后,重新更新该对象就会出现如下所示的错误信息:
[root@master1 ~]#kubectl edit cm immu-cm
#当编辑次不可变cm时,无法正常保存。

image-20230115125205268

这里我们直接在原来的资源清单重新编辑下,再apply下看下效果:

[root@master1 ~]#vim immu-cm.yaml
随便改动下一些参数:
[root@master1 ~]#kubectl apply -f immu-cm.yaml
The ConfigMap "immu-cm" is invalid: data: Forbidden: field is immutable when `immutable` is set

符合预期,测试结束。😘

关于我

我的博客主旨:

  • 排版美观,语言精炼;
  • 文档即手册,步骤明细,拒绝埋坑,提供源码;
  • 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!

🍀 微信二维码
x2675263825 (舍得), qq:2675263825。

image-20230107215114763

🍀 微信公众号
《云原生架构师实战》

image-20230107215126971

🍀 博客
www.onlyyou520.com

image-20230107215612315

image-20230107215651525

🍀 csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

image-20230107215149885

🍀 知乎
https://www.zhihu.com/people/foryouone

image-20230107215203185

最后

好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!

image-20230108211558395

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167778.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二十九、Kubernetes中CronJob(CJ)详解

1、概述 在kubernetes中&#xff0c;有很多类型的pod控制器&#xff0c;每种都有自己的适合的场景&#xff0c;常见的有下面这些&#xff1a; ReplicationController&#xff1a;比较原始的pod控制器&#xff0c;已经被废弃&#xff0c;由ReplicaSet替代 ReplicaSet&#xff…

yolov5训练自己的数据集,OpenCV DNN推理

学更好的别人&#xff0c; 做更好的自己。 ——《微卡智享》 本文长度为4238字&#xff0c;预计阅读9分钟 前言 上一篇《OpenCV--自学笔记》搭建好了yolov5的环境&#xff0c;作为目标检测在应用中&#xff0c;最重要的还是训练自己的数字集并推理&#xff0c;所以这一篇就专门…

『Kubernetes』在Linux中快速安装K8S集群

&#x1f4e3;读完这篇文章里你能收获到 K8S安装全过程博主自己实操笔记带你跳过所有坑感谢点赞收藏&#xff0c;避免下次找不到~ 文章目录一、基本环境配置1. 关闭selinux2. 关闭swap分区或禁用swap文件3. 修改网卡配置4. 关闭防火墙5. 设置机器HostName6. 更新系统时间二、k…

Vue 2.x源码学习:数据响应式改造

众所周知&#xff0c;Vue是以数据驱动视图展示的&#xff0c;即Vue会监听数据的变化&#xff0c;从而自动重新渲染页面的结构。 Vue主要通过三步走来实现这个功能&#xff1a; 第一步是对数据进行响应式改造&#xff0c;即对数据的读写操作进行劫持&#xff1b; 第二步是对模…

字符数组编程题(C语言)

文章目录1、用字符%c的形式给一个字符数组赋初值&#xff0c;然后以字符串%s的形式输出2、用字符getchar&#xff08;&#xff09;的形式给一个字符数组赋初值&#xff0c;然后以字符串puts&#xff09;的形式输出4、从键盘上输入一串字符gets&#xff0c;然后输出%s5、从键盘输…

Mysql导出100万条数据,9种导出方法优缺点和速度、文件大小测试

这里写目录标题1.DBase文件2.文本文件3. CSV文件4.HTML文件5.Excel数据表低版本6.Excel文件2007年以后版本7.SQL脚本文件8.XML文件9.JSON文件总结这一次我主要就是想针对mysql导出的速度和文件大小进行优缺点测试&#xff0c;这次主要就是用上之前生成的天气表这是表里面的数据…

除夕New Year Eve,祝大家团圆幸福!

除夕&#xff0c;为岁末的最后一天夜晚,意为旧岁至此而除&#xff0c;另换新岁。New years Eve is the last night at the end of the year.which means that the old year will be removed and a new year will be replaced.除夕&#xff0c;在国人心中是具有特殊意义的&#…

第一章 TCP/IP 协议

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.什么是TCP/IP ​编辑 二.什么是协议 1.三要素 2.协议与标准区别 三.广…

中小型企业如何从企业内容管理 (ECM) 系统提供的工具中受益?

在当今快节奏的商业世界中&#xff0c;时间变得非常宝贵。团队越大&#xff0c;就越难有效地管理时间。但即使是中小型企业也可以从企业内容管理 (ECM) 系统提供的工具中受益。 ECM 系统使各种规模的企业能够通过数字化纸质文档、捕获电子文档和电子邮件、自动化文档驱动的流…

(转)Chrome的最小字体12px限制最终解决办法

相信不少做网站的用户会有这样一个问题&#xff0c;Chrome 默认最小字体是12px&#xff08;最新版英文也有此问题&#xff09;&#xff0c;这个是 Chrome 为了更好显示中文设计的&#xff0c;但是这样一来就会出现某些上标、下标字体过大&#xff0c;影响用户体验。之前在开发H…

ue4c++日记2(继承|设置位置|对象移动)

目录 语句速查 静态网格定义 创建静态网格对象 设置对象位置 编辑器可编辑 编辑器可见 仅类默认值处可见 速览定义可查剩下 对象移动 1继承 例子 1.创建actor 2.命名和填写路径 小插曲 3.新建一个蓝图类继承上面创建的actor 4.其可蓝图化是因为创建的c类可蓝图化 5…

【算法基础】1.8离散化

文章目录离散化如何离散确定映射方式区间和当数据范围的跨度很大&#xff0c;但是数据很稀疏时&#xff0c;可以使用离散化。 离散化 如何离散 数据范围很大&#xff0c;但是并不是每个数字都会出现&#xff0c;就可以将原始数据按照顺序映射到一个小的数据范围。 确定映射方…

第五届字节跳动青训营 前端进阶学习笔记(二)JavaScript编码规范

文章目录1.前言2.写好JS的一些基本原则这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天 1.前言 本次课程主要讲解了有关JavaScript编码原则和代码优化的相关问题。 重点内容&#xff1a; HTML、CSS、JS各司其责具备正确性、扩展性、复用性的组件封装函数式编程思想代…

进程、线程及python的多线程编程

目录 一.进程、线程和并行执行 1.什么是进程、线程 注意 2.什么是并行执行 二.python的多线程编程 threading模块 语法 多线程编程的传参 演示 三.总结 一.进程、线程和并行执行 1.什么是进程、线程 现代操作系统比如Mac OS X,UNIX, Linux, Windows等&#xff0c;都是…

CSC|2023年艺术类人才培养特别项目解读及建议

目前国家留学基金委&#xff08;CSC&#xff09;官网已经发布了2023年艺术类人才培养特别项目通知&#xff0c;知识人网小编现将其选派工作流程、选派办法、申请材料及说明&#xff08;访问学者、博士后&#xff09;原文转载并加以解读、提出建议。知识人网解读及建议一、2023年…

新产品Digi XBee RR无线模块迁移指南

&#xff08;咨询申请 - 上海皕科电子有限公司--专注物联网 登记后&#xff0c;可提供相关资料&#xff0c;购买XBee模块&#xff0c;有机会获得USB评估底板及相关中文资料&#xff0c;或者免费申请借用评估套件&#xff09; 目录 一、简介 1、MicroPython 2、蓝牙 3、文件…

SpringBoot+easypol前后端分离实现excel导出(保姆级教程)

本篇博文目录1.后端2.前端(采用axios)3.运行效果1.后端 导入easypoi的依赖 <!--用来处理POL相关的操作:easypol--><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.2.0</version&…

Cadence OrCAD: 层次化设计中的电源和地符号

Cadence OrCAD: 层次化设计中的电源和地符号 层次化设计操作步骤&#xff1a;Cadence OrCAD: 层次化设计 Hierarchical Design 本文介绍一个小问题&#xff1a;分层设计中的电源和地符号的作用范围。 电源符号默认作用范围 OrCAD中电源和地符号默认是全局的&#xff0c;也就…

2023年1月中国数据库排行榜:OceanBase 持续两月登顶,前四甲青云直上开新局

一元复始&#xff0c;万象更新。 国产数据库在经历过耕获菑畲的一年后&#xff0c;产品、生态、人才队伍建设等都取得了重大的进展。2023年1月 墨天轮中国数据库流行度排行 火热出炉&#xff0c;本月排行榜“属性”列新增“多模型”&#xff0c;榜单前十名变动较小&#xff0c;…

基于springboot,vue影院订票系统

开发工具&#xff1a;IDEA服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7系统用户前台和管理后台两部分&#xff0c;项目采用前后端分离前端技术&#xff1a;vue elementUI服务端技术&#xff1a;springbootmybatis项目功…