(k8s)kubernetes中ConfigMap

转载:ConfigMap

一、ConfigMap介绍

  • ConfigMap是一种API对象,用来将非机密性的数据保存到键值对中。使用时,Pod可以将其用作环境变量、命令行参数或存储卷中的配置文件。

  • ConfigMap将你的环境配置信息和容器镜像解耦,便于应用配置的修改。

  • 注意:ConfigMap并不提供保密或加密功能。如果你想存储的数据是机密性的,请使用Secret,或者使用其他第三方工具来保存你的数据的私密性,而不是用ConfigMap。

1.1、使用ConfigMap动机

  • 使用ConfigMap来讲你的配置数据和应用程序代码分开。

  • 比如,假设你正在开发一个应用,它可以在你自己的电脑上(用于开发)和在云上(用于实际流量)运行。你的代码里有一段是用于查看环境变量DATABASE_HOST,在本地运行时,你将这个变量设置为localhost,在云上,你将其设置为引用Kubernetes集群中的公开数据库组件的服务。

  • 这让你可以获取在云中运行的容器镜像,并且如果有需要的话,在本地调试完全相同的代码。

  • 说明:ConfigMap在设计上不是用来存储大量的数据的。在ConfigMap中保存的数据不可超过1M。如果你需要保存超出尺寸限制的数据,你可能希望考虑挂载存储卷或者使用独立的数据库或文件服务。

1.2、ConfigMap对象

  • ConfigMap是一个让你可以额存储其他对象所需使用的配置的API对象。和其他Kubernetes对象都有一个spec不同的是,ConfigMap使用databinaryData字段。这些字段能够结构键-值对作为其取值。databinaryData字段都是可选的。data字段设计用来保存UTF-8字符串,而binartyData则被设计用来保存二进制数据作为base64编码的字符串。

  • ConfigMap的名字必须是一个合法的DNS子域名。

  • databinaryData字段下面的每个键的名称都必须又字母数字字符或者-_.组成。在data下保存的键名不可以与在binaryData下出现的键名有重叠。

  • 从v1.19开始,你可以添加一个immutable字段到ConfigMap定义中,创建不可更得ConfigMap。

1.3、ConfigMap和Pod

  • 你可以写一个引用ConfigMap得Pod的spec,并根据ConfigMap中的数据在该Pod中配置容器。这个Pod和ConfigMap必须要在同一个名称空间中(名称空间是Kubernetes用来支持隔离的单个集群中的资源组的一种抽象)。

  • 说明:静态Pod中的spec字段不能引用ConfigMap或任何其他API对象。

二、示例

2.1、ConfigMap示例

  • 这是一个ConfigMap的示例,它的一些键只有一个值,其他的键的值看起来像是配置的片段格式。

    [root@master ~]# vim configmap.yaml
    apiVersion: "v1"
    kind: ConfigMap
    metadata:
    name: game-demo
    data:
    # 简单键值对:适用于简单的配置项,易于访问和修改。
    # 每一个键都映射到一个简单的值
    player_initial_lives: "3"
    ui_properties_file_name: "user-interface.properties"

    复制代码
    # 多行文件:适用于需要存储复杂的内容的配置项,比如配置文件,便于整体管理
    game.properties: |
      enemy.types=aliens,monsters
      player.maximum-lives=5   
    user-interface.properties: |
      color.good=purple
      color.bad=yellow
      allow.textmode=true

    应用ConfigMap资源

    [root@master ~]# kubectl apply -f configmap.yaml

    查看ConfigMap的详细信息

    [root@master ~]# kubectl describe configmap game-demo
    Name: game-demo
    Namespace: default
    Labels: <none>
    Annotations: <none>

    Data

    user-interface.properties:

    color.good=purple
    color.bad=yellow
    allow.textmode=true

    game.properties:

    enemy.types=aliens,monsters
    player.maximum-lives=5

    player_initial_lives:

    3
    ui_properties_file_name:

    user-interface.properties

    BinaryData

    Events: <none>

2.2、Pod引用ConfigMap

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

    • 1、在容器命令和参数内

    • 2、在容器的环境变量

    • 3、在只读卷里面添加一个文件,让应用来读取

    • 4、编写代码在Pod中运行,使用Kubernetes API来读取ConfigMap

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

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

  • 下面是一个Pod引用ConfigMap的示例,它通过使用game-demo中的值来配置一个Pod:

    [root@master ~]# vim pod-configmap.yaml
    apiVersion: "v1"
    kind: Pod
    metadata:
    name: configmap-demp-pod
    spec:
    containers:
    - name: demo
    image: alpine:latest
    imagePullPolicy: IfNotPresent
    command: ["sleep","3600"]
    env:
    # 定义环境变量
    - name: PLAYER_INITIAL_LIVES # 请注意这里的变量是容器中的变量名称,和ConfigMap中的变量是不一样的
    valueFrom:
    configMapKeyRef:
    name: game-demo # 这个值来自这个ConfigMap
    key: player_initial_lives # 需要取值的键,会把这个键的值赋予给新变量
    - name: UI_PROPERTIES_FILE_NAME
    valueFrom:
    configMapKeyRef:
    name: game-demo
    key: ui_properties_file_name
    volumeMounts:
    - name: config
    mountPath: "/config"
    readOnly: true
    volumes:
    # 你可以在Pod级别设置卷,然后将其挂载到Pod内的容器中
    - name: config
    # 定义这个卷的取值将会从ConfigMap中获取
    configMap:
    # 提供你要想挂载的ConfigMap的名字
    name: game-demo
    # 来自ConfigMap的一组键,将被创建为文件挂载到Pod中,并且文件名是path字段指定的
    items:
    - key: "game.properties"
    path: "game.properties"
    - key: "user-interface.properties"
    path: "user-interface.properties"

    备注:volumes中定义的items字段可以更精准的控制configmap中的哪些键值被变换为文件挂载到容器中。如果不指定items那么将把configmap中的所有键都转换为文件挂载到容器中

    应用资源清单

    [root@master ~]# kubectl apply -f pod-configmap.yaml

  • ConofigMap不会区分单行属性值和多行类似文件的值,重要的是Pod和其他对象如何使用这些值。

  • 上面的例子定义了一个卷并将它作为/config文件夹挂载到demo容器内,创建两个文件,/config/game.properties/config/user-interface.properties,尽管ConfigMap中包含了四个键,这是因为Pod定义中在volumes节指定了一个items数组。如果你完全忽略items数组,则ConfigMap中的每个键都会变成一个与该键同名的文件,因此你会得到四个文件。

2.3、验证Pod引入ConfigMap(变量)

复制代码
[root@master ~]# kubectl exec -it configmap-demp-pod -- sh
/ # echo $PLAYER_INITIAL_LIVES
3
/ # echo $UI_PROPERTIES_FILE_NAME
user-interface.properties

2.3、验证Pod引入ConfigMap(文件)

复制代码
[root@master ~]# kubectl exec -it configmap-demp-pod -- sh
/ # ls /config/
game.properties            user-interface.properties
/ # cat /config/game.properties 
enemy.types=aliens,monsters
player.maximum-lives=5   
/ # cat /config/user-interface.properties 
color.good=purple
color.bad=yellow
allow.textmode=true

三、使用ConfigMap

  • ConfigMap可以作为数据卷挂载。ConfigMap也可以被系统的其他组件使用,而不一定直接暴露给Pod。例如,ConfigMap可以保存系统中其他组件要使用的配置数据。

  • CinfigMap最常见的用法就是同一个名称空间里某个Pod(如控制器)中运行的容器执行配置,你也可以单独使用ConfigMap来调整其行为的插件(扩展Kubernetes功能的资源)或者operator(一种用于管理自定义资源的专用控制器)

3.1、在Pod中将ConfigMap当作文件使用

  • 要在一个Pod(如其他控制器如Deployment)的存储卷中使用ConfigMap:

    • 1、创建一个ConfigMap对象或者使用现有的ConfigMap对象。多个Pod可以引用同一个ConfigMap。

    • 2、修改Pod定义,在spec.volumes[]下添加一个卷。为该卷设置任意名称,之后将spec.volumes[].configMap.name字段设置为对你的ConfigMap对象的引用。

    • 3、为每个需要该ConfigMap的容器添加一个.spec.containers[].volumeMounts[]。设置.spec.containers[].volumeMounts[].readOnly=true并将.spec.containers[].volumeMounts[].mountPath设置为一个未使用的目录名,ConfigMap的内容将出现在该目录中

    • 4、更改你的镜像或命令行,以便程序能够从该目录中查找文件。ConfigMap中的每个data键会变成mountPath下面的一个文件名。

  • 下面是一个将ConfigMap以卷的形式进行挂载的Pod示例。

    [root@master ~]# vim pod-1.yaml
    apiVersion: "v1"
    kind: Pod
    metadata:
    name: mypod
    spec:
    containers:
    - name: mypod
    image: alpine:latest
    imagePullPolicy: IfNotPresent
    command: ["sleep","3600"]
    volumeMounts:
    - name: foo
    mountPath: "/etc/foo"
    readOnly: true

    复制代码
    volumes:
    - name: foo
      configMap:
        # 注意:如果是以这种情况挂载到Pod中,那么将会把这个ConfigMap里面所有的键全部转换为与键名相同名字的文件挂载到Pod中
        name: game-demo

    应用资源清单

    [root@master ~]# kubectl apply -f pod-1.yaml

    验证

    通过查看我们可以得知,如果再不指定itmes数组的情况下,会把configmap中的所有键转为文件挂载容器中

    [root@master ~]# kubectl exec -it mypod -- ls /etc/foo
    game.properties ui_properties_file_name
    player_initial_lives user-interface.properties

  • 如果Pod中有多个容器,则每个容器都需要自己的volumeMounts块,但针对每个ConfigMap,你只需要设置一个spec.volumes块,一个Pod多个容器类似于下面的示例

    [root@master ~]# cat pod-1.yaml
    apiVersion: "v1"
    kind: Pod
    metadata:
    name: mypod
    spec:
    containers:
    - name: mypod1
    image: alpine:latest
    imagePullPolicy: IfNotPresent
    command: ["sleep","3600"]
    volumeMounts:
    - name: foo
    mountPath: "/etc/foo"
    readOnly: true
    - name: mypod2
    image: alpine:latest
    imagePullPolicy: IfNotPresent
    command: ["sleep","3600"]
    volumeMounts:
    - name: foo
    mountPath: "/etc/foo"
    readOnly: true

    复制代码
    volumes:
    - name: foo
      configMap:
        # 注意:如果是以这种情况挂载到Pod中,那么将会把这个ConfigMap里面所有的键全部转换为与键名相同名字的文件挂载到Pod中
        name: game-demo

    [root@master ~]# kubectl apply -f pod-1.yaml

    [root@master ~]# kubectl exec -it mypod -c mypod1 -- ls /etc/foo
    game.properties ui_properties_file_name
    player_initial_lives user-interface.properties
    [root@master ~]# kubectl exec -it mypod -c mypod2 -- ls /etc/foo
    game.properties ui_properties_file_name
    player_initial_lives user-interface.properties

3.2、在Pod中使用ConfigMap作为环境变量使用

  • 使用configmap在Pod中设置环境变量

    • 1、对于Pod规约中的每个容器,为要使用的每个ConfigMap键添加一个环境变量到env[].valueFrom.configMapKeyRef字段

    • 2、修改你的镜像或命令行,以便程序查找指定变量中的值。

  • 下面是一个将ConfigMap定义为Pod的环境变量的示例

    [root@master ~]# vim pod-2.yaml
    apiVersion: "v1"
    kind: Pod
    metadata:
    name: env-configmap
    spec:
    containers:
    - name: envars-test-container
    image: alpine:latest
    imagePullPolicy: IfNotPresent
    command: ["sleep","3600"]
    env:
    - name: CONFIGMAP_USERNAME # 新变量的变量名
    valueFrom:
    configMapKeyRef:
    name: game-demo # 要进行取值的configmap名称
    key: game.properties # 要进行取值的键名

    需要注意的是,Pod中环境变量名称允许的字符范围是有限的。如果某些变量名不满足这些规则,则即使Pod可以被启动,你的容器也无法访问这些环境变量

    应用资源清单

    [root@master ~]# kubectl apply -f pod-2.yaml

    验证

    [root@master ~]# kubectl exec -it env-configmap -- sh
    / # echo $CONFIGMAP_USERNAME
    enemy.types=aliens,monsters player.maximum-lives=5

3.3、被挂载的ConfigMap内容会被自动更新

  • 当卷中使用的ConfigMap被更新时,所投射的键最终也会被更新。kubelet组件会在每次周期性同步时检查所有挂载的ConfigMap是否为最新。不过,kubelet使用的时其本地高速缓存来获得ConfigMap的当前值

  • 以环境变量方式使用的ConfigMap数据不会被自动更新。更新这些数据需要重新启动Pod。

3.5、不可变更的ConfigMap

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

    • 保护应用,使之免受意外(不想要的)更新所带来的负面影响。

    • 通过大幅降低对kube-apserser的压力提升集群性能,这是因为系统会关闭对已标记为不可变更的ConfigMap的监视操作。

  • 你可以通过将immutable字段设置为true创建不可变更的ConfigMap

    [root@master ~]# vim configmap.yaml
    apiVersion: "v1"
    kind: ConfigMap
    metadata:
    name: game-demo
    data:
    # 简单键值对:适用于简单的配置项,易于访问和修改。
    # 每一个键都映射到一个简单的值
    player_initial_lives: "3"
    ui_properties_file_name: "user-interface.properties"

    复制代码
    # 多行文件:适用于需要存储复杂的内容的配置项,比如配置文件,便于整体管理
    game.properties: |
      enemy.types=aliens,monsters
      player.maximum-lives=5   
    user-interface.properties: |
      color.good=purple
      color.bad=yellow
      allow.textmode=true 

    immutable: true

    应用资源清单

    [root@master ~]# kubectl apply -f configmap.yaml

    验证

    以下我把player_initial_lives变量的值改为10查看效果

    player_initial_lives: "10"

    可以看出设置为了不可变更的configmap之后,里面的内容是不允许更改的

    [root@master ~]# kubectl apply -f configmap.yaml
    The ConfigMap "game-demo" is invalid: data: Forbidden: field is immutable when immutable is set

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

相关推荐
能不能别报错4 小时前
K8s学习笔记(十六) 探针(Probe)
笔记·学习·kubernetes
能不能别报错6 小时前
K8s学习笔记(十四) DaemonSet
笔记·学习·kubernetes
火星MARK7 小时前
k8s面试题
容器·面试·kubernetes
Serverless社区8 小时前
阿里云函数计算 AgentRun 全新发布,构筑智能体时代的基础设施
阿里云·云原生·serverless·函数计算
赵渝强老师9 小时前
【赵渝强老师】Docker容器的资源管理机制
linux·docker·容器·kubernetes
能不能别报错10 小时前
K8s学习笔记(十五) pause容器与init容器
笔记·学习·kubernetes
稚辉君.MCA_P8_Java10 小时前
kafka解决了什么问题?mmap 和sendfile
java·spring boot·分布式·kafka·kubernetes
乄bluefox10 小时前
保姆级docker部署nacos集群
java·docker·容器
每天进步一点_JL11 小时前
Docker 是什么?
后端·docker·容器
一叶飘零_sweeeet11 小时前
从 0 到 1 掌控云原生部署:Java 项目的 Docker 容器化与 K8s 集群实战指南
docker·云原生·kubernetes·项目部署