问题描述
如果在镜像中包含环境配置信息,那么该镜像的可移植性是非常差的。例如,如果在镜像中包含了测试环境数据库的配置信息,那该镜像只能用于测试环境,不能部署到生产环境。
解决方法
通过 ConfigMap 对象,将配置从镜像中解耦,以实现镜像的可移植性。
该笔记参照官方文档,学习 ConfigMap 使用,并提供系列示例,演示如何创建 ConfigMap 以及如何在 Pod 中使用 ConfigMap 中的数据。
第一步、创建 ConfigMap 对象
有两种方法创建 ConfigMap 对象:
一)使用命令行:kubectl create configmap
二)使用生成器:使用 kustomization.yaml 中的 ConfigMap 生成器;(从 1.14 开始)
方法一、使用命令行
使用 kubectl create configmap 命令从目录、文件、字面量创建 ConfigMap 对象:
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 中的数据导入容器的环境变量中。
将 特定数据 导入环境变量
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
将 全部数据 导入环境变量
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: # 定义卷,该卷引用名为 config-volume 的 ConfigMap 对象 volumes: - name: config-volume configMap: name: special-config # 使用卷,将在容器中使用该卷 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 # 查看 /etc/config/ 目录后,该目录下的会有大量的文件 # 其中,文件名为 ConfigMap 中的 KEY 值,而文件内容则为该 KEY 对应的 VALUE 值。
将ConfigMap中的数据挂载到卷中的特定目录
使用 path 字段,将特定的 ConfigMap 项挂载到特定的文件目录。
apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: # 只定义需要挂载的属性,及挂载名称 volumes: - name: config-volume configMap: name: special-config items: - key: SPECIAL_LEVEL # 挂载的名字 path: keys # 使用卷,将在容器中使用该卷 containers: - name: test-container image: k8s.gcr.io/busybox command: [ "/bin/sh","-c","cat /etc/config/keys" ] volumeMounts: - name: config-volume mountPath: /etc/config # 在该示例中,在 ConfigMap 中的 SPECIAL_LEVEL 将被挂载到 /etc/config/keys 中 # 如果 /etc/config 之前包含其他文件,则使用这种方式之后,这些文件将不可见
如果想要为每个文件指定权限,可以参考「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的常用方法)
相关文章
「K8s」- 简单的Ingress示例
「Kubernetes Objects」- Managing Compute Resources(学习笔记)
「Kubernetes Objects」- PodPreset(学习笔记)
「Kubernetes Objects」- Service(学习笔记)
「Kubernetes Objects」- Pod(学习笔记)
「Kubernetes」- 使用存储(学习笔记)
「Kubernetes Objects」- CronJob(学习笔记)