ConfigMap详解

应用部署的一个最佳实践是将应用所需的配置信息与程序进行分离,这样可以使得应用程序被更好地复用,通过不同的配置也能实现更灵活的功能。
将应用打包为容器镜像后,可以通过环境变量或者外挂文件的方式在创建容器时进行配置注入,但在大规模容器集群的环境中,对多个容器进行不同的配置将变得非常复杂。
从Kubernetes v1.2开始提供了一种统一的应用配置管理方案——ConfigMap。本节对ConfigMap的概念和用法进行详细描述。

1. ConfigMap概述

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

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

2. 创建ConfigMap资源对象

2.1 通过yaml配置文件方式创建

下面的例子cm-appvars.yaml描述了将几个应用所需的变量定义为ConfigMap的用法:

apiVersion: v1
kind: ConfigMap
metadata:
  name: cm-appvars
data:
  apploglevel: info
  appdatadir: /var/data

执行kubectl create命令创建该ConfigMap:

kubectl create -f cm-appvars.yaml

查看创建好的ConfigMap:

# 查看ConfigMap列表
kubectl get configmap
# 查看ConfigMap cm-appvars
kubectl describe configmap cm-appvars
# 以yaml的形式输出cm-appvars
kubectl get configmap cm-appvars -o yaml

2.2 通过kubectl命令行方式创建

不使用yaml文件,直接通过kubectl create configmap也可以创建ConfigMap,可以使用参数--from-file--from-literal指定内容,并且可以在一行命令中指定多个参数。
(1)通过--from-file参数从文件中进行创建,可以指定key的名称,也可以在一个命令行中创建包含多个key的ConfigMap,语法为:

kubectl create configmap NAME --from-file=[key=]source --from-file=[key=]source

(2)通过--from-file参数从目录中进行创建,该目录下的每个配置文件名称都被设置为key,文件的内容被设置为value,语法为:

kubectl create configmap NAME  --from-file=config-files-dir

(3)--from-literal从文本中进行创建,直接将指定的key-value对创建为ConfigMap的内容,语法为:

kubectl create configmap NAME --from-literal=key1=value1 --from-literal=key2=value2

3. 使用ConfigMap

容器应用对ConfigMap的使用有以下两种方法:

  • 通过环境变量获取ConfigMap
  • 通过Volume挂载的方式将ConfigMap中的内容挂载为容器内部的文件或目录

3.1 在Pod中使用ConfigMap

(1)通过环境变量方式使用ConfigMap
以前面创建的ConfigMap “cm-appvars” 为例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: cm-appvars
data:
  apploglevel: info
  appdatadir: /var/data

在Pod “cm-test-pod” 的定义中,将ConfigMap “cm-appvars” 中的内容以环境变量(APPLOGLEVEL和APPDATADIR)设置为容器内部的环境变量,容器的启动命令将显示这两个环境变量的值("env | grep APP"):

apiVersion: v1
kind: Pod
metadata:
  name: cm-test-pod
spec:
  containers:
  - name: cm-test
    image: busybox
    command: ["/bin/sh", "-c", "env | grep APP"]
    env:
    - name: APPLOGLEVEL
      valueFrom:
        configMapKeyRef:
          name: cm-appvars
          key: apploglevel
    - name: APPDATADIR
      valueFrom:
        configMapKeyRef:
          name: cm-appvars
          key: appdatadir
    restartPolicy: Never

使用kubectl create -f命令创建该Pod,由于是测试Pod,所以该Pod在执行完启动命令后将会退出,并且不会被系统自动重启(restartPolicy: Never):

kubectl create -f cm-test-pod.yaml

使用kubectl get pods --show-all 查看已经停止的Pod
查看该Pod的日志,可以看到启动命令“env | grep APP”的执行结果如下:

$ kubectl logs cm-test-pod
APPDATADIR=/var/data
APPLOGLEVEL=info

从Kubernetes v1.6开始,引入了一个新的字段 envFrom ,实现在Pod环境内将ConfigMap(也可用于Secret资源对象)中所定义的key=value自动生成为环境变量:

apiVersion: v1
kind: Pod
metadata:
  name: cm-test-pod
spec:
  containers:
    - name: test-container
      image: busybox
      command: [ "/bin/sh", "-c", "env" ]
      envFrom:
      - configMapRef:
          name: cm-appvars
  restartPolicy: Never

通过这个定义,在容器内部将生成如下环境变量:

apploglevel=info
appdatadir=/var/data

需要说明的是,环境变量的名称受POSIX命名规范([a-zA-Z_][a-zA-Z0-9_]*)约束,不能以数字开头。
如果包含非法字符,则系统将跳过该条环境变量的创建,并记录一个Event来描述环境变量无法生成,但不会阻止Pod的启动。

3.2 在 Pod 命令里使用 ConfigMap 定义的环境变量

我们可以利用$(VAR_NAME)这个 Kubernetes 替换变量,在 Pod 的配置文件的command段使用 ConfigMap 定义的环境变量。

例子如下:

下面的 Pod 配置

apiVersion: v1
kind: Pod
metadata:
  name: cm-test-pod
spec:
  containers:
    - name: test-container
      image: busybox
      command: [ "/bin/sh", "-c", "echo $(APPLOGLEVEL) $(APPDATADIR)" ]
      env:
        - name: APPLOGLEVEL
          valueFrom:
            configMapKeyRef:
              name: cm-appvars
              key: apploglevel
        - name: APPDATADIR
          valueFrom:
            configMapKeyRef:
              name: cm-appvars
              key: appdatadir
  restartPolicy: Never

3.3 通过volumeMount使用ConfigMap

当您使用 --from-file 创建 ConfigMap 时, 文件名将作为键名保存在 ConfigMap 的 data 段,文件的内容变成键值。

从 ConfigMap 里的数据生成一个卷

下面的例子展示了一个名为 special-config 的 ConfigMap 的配置:

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.level: very
  special.type: charm

在 Pod 的配置文件里的 volumes 段添加 ConfigMap 的名字。 这会将 ConfigMap 数据添加到 volumeMounts.mountPath 指定的目录里面(在这个例子里是 /etc/config)。 command 段引用了 ConfigMap 里的 special.level.

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "ls /etc/config/" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        # Provide the name of the ConfigMap containing the files you want
        # to add to the container
        name: special-config
  restartPolicy: Never

Pod 运行起来后, 执行这个命令 ("ls /etc/config/") 将产生如下的输出:

special.level
special.type

添加 ConfigMap 数据到卷里指定路径

使用 path 变量定义 ConfigMap 数据的文件路径。 在我们这个例子里,special.level 将会被挂载在 config-volume 的文件 /etc/config/keys 下.

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh","-c","cat /etc/config/keys" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
        items:
        - key: special.level
          path: keys
  restartPolicy: Never

Pod 运行起来后,执行命令("cat /etc/config/keys")将产生下面的结果:

very

3.4 使用ConfigMap的限制条件

使用ConfigMap的限制条件如下:

  • ConfigMap必须在Pod之前创建(除非您把 ConfigMap 标志成”optional”)。如果您引用了一个不存在的 ConfigMap, 那这个Pod是无法启动的。就像引用了不存在的 Key 会导致 Pod 无法启动一样。
  • ConfigMap受Namespace限制,只有处于相同的Namespace中的Pod可以引用它;
  • ConfigMap中的配额管理还未能实现;
  • kubelet值支持可以被API Server管理的Pod使用ConfigMap。kubelet在当前Node上通过 --manifest-url--config 自动创建的静态Pod将无法引用ConfigMap;
  • 在Pod对ConfigMap进行挂载(volumeMount)操作是,容器内部只能挂载为目录,无法挂载为文件
  • 在挂载到容器内部后,目录中将包含ConfigMap定义的每个item,如果该目录下原理还有其他文件,则容器内的该目录会被挂载的ConfigMap覆盖
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容