「Kubernetes Objects」- ConfigMap

  FROM JENKINS AUTOMATION

更新日期:2019年07月10日

内容简介

如果在镜像中包含了环境信息,则该镜像的可移植性是非常差的。例如,如果在镜像中包含了测试环境数据库的配置信息,那该镜像只能用于测试环境,不能部署到生产环境。

本文参照官方文档,对ConfigMap进行介绍。通过ConfigMap将配置信息从镜像中解耦,以提高镜像的可移植性。

ConfigMap ?

用于将「配置制品」从「镜像内容」中解耦,以实现镜像的可移植性。

本文提供一系列的示例,演示了「如何创建ConfigMap」以及「如何在Pod中使用ConfigMap中的数据」。

(定义)创建ConfigMap对象

有两种方法创建ConfigMap对象:

方法一、使用命令行:kubectl create configmap
方法二、使用生成器:使用「kustomization.yaml」中的ConfigMap生成器;(从1.14开始)

# 使用命令行

使用kubectl create configmap命令从「目录」、「文件」、「字面量」创建ConfigMap对象:

#!/bin/sh

kubectl create configmap <map-name> <data-source>

其中,参数<map-name>是ConfigMap的名字,参数<data-source>是用于从中提取数据「目录」、「文件」、「字面量」。

参数<data-source>对应了ConfigMap中的键值对:

  • key – 在命令行提供的「文件名」或者「key」;
  • value – 在命令行提供的「文件内容」或者「字面值」;

可以使用kubectl describe或者kubectl get来获取ConfigMap中的信息。

# 从「目录」中创建ConfigMap对象 #

#!/bin/sh

# Create the local directory
mkdir -p configure-pod-container/configmap/

# Download the sample files into `configure-pod-container/configmap/` directory
wget https://kubernetes.io/examples/configmap/game.properties -O configure-pod-container/configmap/game.properties
wget https://kubernetes.io/examples/configmap/ui.properties -O configure-pod-container/configmap/ui.properties

# 创建ConfigMap
# 该命令结合文件「game.properties」和「ui.properties」的内容,创建名为「game-config」的ConfigMap对象。
kubectl create configmap "game-config" \
    --from-file="configure-pod-container/configmap/"

# 查看ConfigMap对象的信息
kubectl describe configmaps game-config

# 数据存在于ConfigMap的「data」部分
kubectl get configmaps game-config -o yaml
# apiVersion: v1
# kind: ConfigMap
# metadata:
#   creationTimestamp: 2016-02-18T18:52:05Z
#   name: game-config
#   namespace: default
#   resourceVersion: "516"
#   selfLink: /api/v1/namespaces/default/configmaps/game-config
#   uid: b4952dc3-d670-11e5-8cd0-68f728db1985
# 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

# 从「文件」中创建ConfigMap对象 #

#!/bin/sh

################################################################################
# 当从文件创建时,使用「--from-file」选项。
# 这种用法与从目录中创建是一致的。
################################################################################
# 创建
kubectl create configmap "game-config-2" \
    --from-file="configure-pod-container/configmap/game.properties"

# 可以指定多次
kubectl create configmap "game-config-2" \
    --from-file=configure-pod-container/configmap/game.properties \
    --from-file=configure-pod-container/configmap/ui.properties

# 当使用「--from-file」选项时,在「data」部分中的「key」是文件名,也可以使用自定义的名字
kubectl create configmap "game-config-3" \
    --from-file=game-special-key=configure-pod-container/configmap/game.properties

# 显示ConfigMap对象的信息
kubectl describe configmaps "game-config-2"

################################################################################
# 当从文件创建时,使用「--from-env-file」选项。
# 这种用法与从前面的就不一样了。
################################################################################
kubectl create configmap "game-config-env-file" \
       --from-env-file="configure-pod-container/configmap/ui.properties"

# 查看文件内容
kubectl get configmap game-config-env-file -o yaml
# apiVersion: v1
# kind: ConfigMap
# metadata:
#   creationTimestamp: 2017-12-27T18:36:28Z
#   name: game-config-env-file
#   namespace: default
#   resourceVersion: "809965"
#   selfLink: /api/v1/namespaces/default/configmaps/game-config-env-file
#   uid: d9d1ca5b-eb34-11e7-887b-42010a8002b8
# data:
#   allowed: '"true"'
#   enemies: aliens
#   lives: "3"

# !!!如果指定了「--from-env-file」多次,那么只有最后一个是有效的。

# 从「字面值」创建ConfigMap对象 #

#!/bin/sh

# 这个做法类似于「--from-env-file」选项,只不过是从命令行直接指定
kubectl create configmap "special-config" \
   --from-literal=special.how=very \
   --from-literal=special.type=charm

# 使用生成器

从1.14开始,kubectl支持kustomization.yaml。您还可以从「生成器」创建ConfigMap对象,然后应用它,在Apiserver上创建对象。 应在目录中的kustomization.yaml中指定生成器。

# 从「文件」中创建ConfigMap对象 #

#!/bin/sh

# 从「configure-pod-container/configmap/kubectl/game.properties」中生成ConfigMap对象

# Create a kustomization.yaml file with ConfigMapGenerator
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-4
  files:
  - configure-pod-container/configmap/kubectl/game.properties
  # 默认的key是文件名,可以指定自定义的key值
  - game-special-key=configure-pod-container/configmap/kubectl/game.properties
EOF

# 从当前目录中应用定义来创建ConfigMap对象
kubectl apply -k .

# 查看定义
kubectl get configmap
kubectl describe configmaps/game-config-4-m9dm2f92bt

# !!!文件名以内容的哈希为后缀。以确保每次ConfigMap修改后生成新的ConfigMap对象。

# 从「字面值」中创建ConfigMap对象 #

#!/bin/sh

# Create a kustomization.yaml file with ConfigMapGenerator
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: special-config-2
  literals:
  - special.how=very
  - special.type=charm
EOF

# 从当前目录中应用定义来创建ConfigMap对象
kubectl apply -k .

(使用)使用ConfigMap中的某个数据来定义环境变量

# 使用ConfigMap中特定KEY的值作为环境变量 #

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      ##########################################################################
      env:
        # 定义环境变量的KEY值
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              # 要引用的ConfigMap对象的名称
              name: special-config
              # 该ConfigMap中的KEY值
              key: special.how
        # 引用另外一个ConfigMap中的值
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: env-config
              key: log_level
      ##########################################################################
      # 这些环境变量也可以容器中使用
      command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY)" ]
  restartPolicy: Never

(使用)使用ConfigMap中的所有数据来定义环境变量

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "env" ]
      ##########################################################################
      envFrom:
        - configMapRef:
            name: special-config
      ##########################################################################
  restartPolicy: Never

将ConfigMap挂载到卷中

当使用「–from-file」选项创建ConfigMap对象时,「文件名」被作为「key」存储在ConfigMap的「data」部分,而「文件内容」则作为「value」进行存储。

# 使用ConfigMap中的所有数据填充卷

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "ls /etc/config/" ]
      ##########################################################################
      # 挂载这个卷到/etc/config/目录中
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  ##############################################################################
  # 定义了一个卷,该卷引用了一个名为config-volume的ConfigMap对象。
  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

# !!!查看/etc/config/目录后,该目录下的会有大量的文件
# !!!其中,文件名为ConfigMap中的KEY值,而文件内容则为ConfigMap中KEY对应的VALUE值。

# 将ConfigMap中的数据挂载到卷中的特定目录

使用path字段,将特定的ConfigMap项挂载到特定的文件目录。

在下面的例子中,在ConfigMap中的SPECIAL_LEVEL将被挂载到/etc/config/keys中:

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/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

# 如果想要为每个文件指定权限,可以参考「Secrets/Using Secrets as Files from a Pod」部分。

# 已挂载的ConfigMaps会自动更新

当已经在Volume中使用的ConfigMap发生修改,投影的KEY也自然会更新。

kubelet会定期检查已挂载的ConfigMap是否是新的。

但是,它使用其本地基于TTL的缓存来获取ConfigMap的当前值。

所以,从「ConfigMap发生修改」到「Pod中的ConfigMap发生更新」的延迟,可以和「kubelet sync period」+「TTL」一样长。

!!!使用ConfigMap作为subPath卷,将不会收到ConfigMap的更新。

# TODO WHAT IS SUBPATH?

# 理解ConfigMap和Pod对象

「ConfigMap API资源」将配置数据存储为键值对。 可以在Pod中使用数据,也可以为「控制器」等系统组件提供配置。

ConfigMap类似于Secrets,但提供了一种处理不包含敏感信息的字符串的方法。

用户和系统组件都可以在ConfigMap中存储配置数据。

!!!ConfigMaps应引用属性文件,而不是替换它们。 可以将ConfigMap视为代表的内容,类似于Linux的/etc目录及其内容。
!!!例如,如果从ConfigMap创建Kubernetes卷,则ConfigMap中的每个数据项,都由卷中的单个文件表示。

ConfigMap的data字段包含配置数据。 如下面的示例所示,这可以很简单(就像使用–from-literal定义的单个属性),或类似复杂的(配置文件或使用–from-file定义的JSON二进制大对象):

apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: 2016-02-18T19:14:38Z
  name: example-config
  namespace: default
data:
  # example of a simple property defined using --from-literal
  example.property.1: hello
  example.property.2: world
  # example of a complex property defined using --from-file
  example.property.file: |-
    property.1=value-1
    property.2=value-2
    property.3=value-3

# 限制

(1)必须先创建ConfigMap,然后才能在Pod规范中引用它(除非您将ConfigMap标记为“optional”)。 如果引用不存在的ConfigMap,Pod将无法启动。 同样,对ConfigMap中不存在的Key的引用,将阻止Pod启动。

(2)如果使用envFrom从ConfigMaps定义环境变量,则将跳过被视为无效的Key。 将允许pod启动,但“无效名称”将记录在事件日志中(InvalidVariableNames)。 日志消息列出每个跳过的KEY:kubectl get events

(3)只能作用于指定的命名空间。

(4)Kubelet不支持将ConfigMaps用于APIServer上找不到的pod。 这包括通过Kubelet的–manifest-url标志,–config标志,Kubelet REST API创建的pod。(这些不是创建pod的常用方法)

参考文献




文章摘要:Cloud-native_Technologies:Kubernetes_API_Objects:ConfigMap

原文链接:「Kubernetes Objects」- ConfigMap