配置分离:ConfigMap

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 配置分离:ConfigMap


云原生要素-配置分离:ConfigMap&Secret

什么是ConfigMap

ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。

举一个例子更直观的看出ConfigMap是什么:比如我有一个nginx的Pod资源,那么ConfigMap就相当于nginx.conf这个配置文件。

需要注意的是:这个 Pod 和 ConfigMap 必须要在同一个 命名空间 中,不可跨命名空间。

ConfigMap供容器使用的典型用法如下:

  • 生成容器内的环境变量。
  • 设置容器启动命令的启动参数(需设置为环境变量)。
  • 以Volume的形式挂载为容器内部的文件或目录。

ConfigMap与Secret类似,更倾向于前者适用于明文配置,后者适用于密码等配置。

ConfigMap的创建方式

configmap创建语法:

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

基于目录/文件方式创建configmap

  • 创建一个用于练习的目录及文件,其中包含两个用于测试的文件
[root@k8s-master01 ~]# mkdir /configmap
您在 /var/spool/mail/root 中有新邮件
[root@k8s-master01 ~]# cd /configmap/
[root@k8s-master01 configmap]# mkdir conf
[root@k8s-master01 configmap]# vim conf/test01.conf
[root@k8s-master01 configmap]# vim conf/test02.conf 
您在 /var/spool/mail/root 中有新邮件
[root@k8s-master01 configmap]# cat conf/test1.conf 
lives=3
name=haha
[root@k8s-master01 configmap]# cat conf/test2.conf 
color.good=yellow
user=mysql
  • 创建一个cm(cm为configmap的缩写),与创建其他资源类型一样
[root@k8s-master01 configmap]# kubectl create configmap cmfile --from-file=conf/
[root@k8s-master01 configmap]# kubectl get cm
NAME               DATA   AGE
cmfile             2      13s
kube-root-ca.crt   1      21d
# 可以看到刚才创建的资源已经成功了
  • 我们可以查看一下生成的cm的yaml文件
[root@k8s-master01 configmap]# kubectl get cm cmfile -oyaml
apiVersion: v1
data:
  test1.conf: |
    lives=3
    name=haha
  test2.conf: |
    color.good=yellow
    user=mysql
kind: ConfigMap
metadata:
  creationTimestamp: "2022-02-23T02:50:40Z"
  name: cmfile
  namespace: default
  resourceVersion: "1050098"
  uid: 39b904c2-c1a4-442c-a6fe-6a3d89af36ac
  • 找到data,可以看到data下内容包含了之前测试创建的两个文件及内容
  • 基于文件创建和目录是相似的,只要加上目录下的指定文件即可,比如:
[root@k8s-master01 configmap]# kubectl create cm cmfromfile --from-file=conf/test02.conf 
  • 有一个不常用的地方,自定义configmap中的名称
[root@k8s-master01 configmap]# vim test03.conf
[root@k8s-master01 configmap]# kubectl create cm test03 --from-file=test03-conf=test03.conf
configmap/test03 created
[root@k8s-master01 configmap]# kubectl get cm test03 -o yaml 
apiVersion: v1
data:
  test03-conf: |
    user=www
    passwd=123456
kind: ConfigMap
metadata:
  creationTimestamp: "2022-02-20T10:52:11Z"
  name: test03
  namespace: default
  resourceVersion: "914180"
  uid: 2f41ffa8-f200-48ee-8e61-729cfdf81b97
  • 可以看到上面例子中的test03.conf已经变成test03-conf格式了,这个了解即可。

基于env文件创建configmap

  • 其实方式都一样,不细写了,看下创建方式:适用于较多的键值对
[root@k8s-master01 configmap]# kubectl create cm envfile --from-env-file=envfile.conf 
configmap/envfile created
[root@k8s-master01 configmap]# kubectl get cm envfile -o yaml 
apiVersion: v1
data:
  age: "25"
  hehe: haha
  name: yy
kind: ConfigMap
metadata:
  creationTimestamp: "2022-02-23T03:02:58Z"
  name: envfile
  namespace: default
  resourceVersion: "1051876"
  uid: 27a62b22-cd46-4dbe-bf12-6b34a67befe8
# 可以看到里面的等号换成冒号

基于literal直接创建configmap

  • 比如我们只需要一两个或很少的变量,没有写成文件的必要的时候可以用这种方式
[root@k8s-master01 configmap]# kubectl create cm literaltest --from-literal=PORT=8080 --from-literal=PASSWORD=123456 

基于yaml文件创建configmap

使用valueFrom定义环境变量

适合配置参数比较少的地方


我们先创建一个deploy资源方便测试,–dry-run的作用是只生成yaml文件而不创建资源

kubectl create deployment dp-cm --image=nginx --dry-run=client -o yaml > dp-cm.yaml
  • 简单修改一下后剩余的yaml文件
[root@k8s-master01 configmap]# cat dp-cm.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: dp-cm
  name: dp-cm
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dp-cm
  strategy: {}
  template:
    metadata:
      labels:
        app: dp-cm
    spec:
      containers:
      - image: nginx
        name: nginx
  • 我们分别添加一个传统的环境变量和使用configmap定义一个
    spec:
      containers:
      - image: nginx
        name: nginx
        env:
        - name: TEST_ENV
          value: test_env
        - name: TEST_X
          valueFrom:
            configMapKeyRef:
              name: envfile
              key: hehe
  • env下第一个环境变量是我们按照传统模式定义;第二个是在configmap中取值,先看一下效果
[root@k8s-master01 configmap]# kubectl create -f dp-cm.yaml 
deployment.apps/dp-cm created
[root@k8s-master01 configmap]# kubectl exec dp-cm-f8c48c84c-zvcwt -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=dp-cm-f8c48c84c-zvcwt
NGINX_VERSION=1.21.6
NJS_VERSION=0.7.2
PKG_RELEASE=1~bullseye
TEST_ENV=test_env
TEST_X=haha
  • 最后两个分别是我们直接定义的变量和引用configmap中的变量
  • 如果引用多个变量只需要在后面添加定义即可
        - name: TEST_X
          valueFrom:
            configMapKeyRef:
              name: envfile
              key: hehe
        - name: TEST_Y
          valueFrom:
            configMapKeyRef:
              name: envfile
              key: name              

注意:如果引用的变量不存在会报错,Pod创建不成功

使用envfrom批量生成环境变量

    spec:
      containers:
      - image: nginx
        name: nginx
        envFrom:
        - configMapRef:
            name: envfile
  • 更新一下Pod,然后看一下结果
[root@k8s-master01 configmap]# kubectl replace -f dp-cm.yaml 
deployment.apps/dp-cm replaced
[root@k8s-master01 configmap]# kubectl exec dp-cm-8565c44587-x8k62 -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=dp-cm-8565c44587-x8k62
NGINX_VERSION=1.21.6
NJS_VERSION=0.7.2
PKG_RELEASE=1~bullseye
age=25
hehe=haha
name=yy
TEST_ENV=test_env
  • 可以看到后面三行小写名称的就是我们envfileconfigMap中的内容
  • 当一个Pod中变量有直接定义的也有从configMap定义时,我们可以加prefix前缀进行区分:
    spec:
      containers:
      - image: nginx
        name: nginx
        envFrom:
        - configMapRef:
            name: envfile
          prefix: fromCm_
        env:
        - name: TEST_ENV
          value: test_env

以文件形式挂载ConfigMap

  • 我们事先创建了一个redis-conf的cm副本,然后挂载到下面文件的Pod中
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: redisconf
          mountPath: /etc/config
      volumes:
      - name: redisconf
        configMap:
          name: redis-conf
  • 上面这部分内容中volumes下有两个name,第一个是需要挂载到Pod的名称,第二个是configMap的名称,已经做了区分了。
  • 执行yaml文件,进入Pod内部查看一下挂载情况
# 创建Pod
[root@k8s-master01 ~]# kubectl create -f dp-cm.yaml 
# 进入到Pod中查看挂载情况
[root@k8s-master01 ~]# kubectl exec -ti dp-cm-77b4666649-jd4sc -- bash
root@dp-cm-77b4666649-jd4sc:/# cd /etc/config/
root@dp-cm-77b4666649-jd4sc:/etc/config# ls
redis-conf
root@dp-cm-77b4666649-jd4sc:/etc/config# cat redis-conf 
hehe 123123
# 可以看到我们之前创建的文件已经挂载好了
  • 在线编辑cm文件内容,挂载到Pod中的文件也会随着更改
[root@k8s-master01 ~]# kubectl edit cm redis-conf 
[root@k8s-master01 ~]# kubectl get cm redis-conf -o yaml 
  redis-conf: |
    hehe 23412423412
[root@k8s-master01 ~]# kubectl exec -ti dp-cm-77b4666649-jd4sc -- bash
root@dp-cm-77b4666649-jd4sc:/# cat /etc/config/redis-conf 
hehe 23412423412
# Pod中的文件也随着修改了

防止覆盖操作

比如我们有一个nginx-conf的configMap要挂载到nginx的/etc/nginx目录下,如果直接操作的话会发生覆盖/etc/nginx下所有内容,导致Pod报错。

所以需要加上subPath来防止内容会覆盖,如下:

    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: nginxconf
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf  # 这样只会对这一个文件进行覆盖
      volumes:
      - name: nginxconf
        configMap:
          name: nginx-conf

自定义文件名与授权

  • 使用item自定义文件名:相当于做一个软连接
      volumes:
      - name: redisconf
        configMap:
          name: redis-conf
          items:
          - key: redis.conf
            path: redis2.conf
  • 使用defaultMode给ConfigMap中文件进行权限管理
      volumes:
      - name: redisconf
        configMap:
          name: redis-conf
          items:
          - key: redis.conf
            path: redis2.conf
            mode: 0644 # 具体文件权限,优先级高
          defaultMode: 0666 # configMap的默认权限

热更新操作

如果是通过yaml文件创建的,只需要在yaml文件中修改,然后kubectl replace更新即可

如果是通过命令创建的话:

  • 可以把cm导成yaml文件进行修改,然后更新,但是可能会出现错误,不建议。
  • 还可以修改创建cm前使用的原始文件,比如nginx.conf文件,然后利用--dry-run=client生成一个yaml文件,然后进行更新。如下:
kubectl create cm nginx-conf --from-file=nginx.conf --dry-run=client -oyaml | kubectl replace -f -

使用限制

  • 需要提前创建ConfigMap或者Secret
  • 引用的Key必须存在
  • envFrom、valueFrom无法热更新操作
  • envFrom配置环境变量,如果Key无效,会忽略无效的Key
  • 资源需要在同一个命名空间
  • subPath也是无法热更新的

内容不可变

ConfigMap或Secret中加入以下内容,执行后不可再修改资源

immutable: ture


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
2月前
|
JSON Kubernetes API
深入理解Kubernetes配置:编写高效的YAML文件
深入理解Kubernetes配置:编写高效的YAML文件
|
3月前
|
JSON Kubernetes 数据格式
访问kubernetes CRD的几种方式
访问kubernetes CRD的几种方式
56 1
|
5月前
|
Kubernetes 应用服务中间件 API
Kubernetes关键组件解析
【6月更文挑战第12天】Kubernetes是一个用于管理容器集群的平台,由Master节点负责集群控制,而Node节点执行管理命令。
|
6月前
|
存储 Kubernetes 关系型数据库
Kubernetes详解(二)——Kubernetes结构与资源对象
Kubernetes详解(二)——Kubernetes结构与资源对象
103 0
|
6月前
|
Kubernetes Ubuntu Linux
玩转Kubernetes—尝试以不同方式初始化集群
玩转Kubernetes—尝试以不同方式初始化集群
83 0
|
Kubernetes 应用服务中间件 nginx
k8s--kubernetes 组件、资源管理方式
k8s--kubernetes 组件、资源管理方式
|
存储 Kubernetes 调度
10-Kubernetes-Pod详解-结构和定义
10-Kubernetes-Pod详解-结构和定义
|
弹性计算 Kubernetes 调度
【kubernetes】Deployment Controller 副本调度控制器
【kubernetes】Deployment Controller 副本调度控制器
104 0
|
Kubernetes Docker 容器
kubernetes 【组件】configmap配置更新
kubernetes 【组件】configmap配置更新
|
存储 Kubernetes 网络协议
kubernetes ConfigMap 文件映射详解
kubernetes ConfigMap 文件映射详解
kubernetes ConfigMap 文件映射详解

相关实验场景

更多