Kubernetes 配置Pod使用ConfigMap
配置 Pod 使用 ConfigMap
很多应用在其初始化或运行期间要依赖一些配置信息。大多数时候, 存在要调整配置参数所设置的数值的需求。 ConfigMap 是 Kubernetes 用来向应用 Pod 中注入配置数据的方法。
ConfigMap 允许你将配置文件与镜像文件分离,以使容器化的应用程序具有可移植性。 本页提供了一系列使用示例,这些示例演示了如何创建 ConfigMap 以及配置 Pod 使用存储在 ConfigMap 中的数据。
在开始之前
你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 建议在至少有两个节点的集群上运行本教程,且这些节点不作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:
要检查版本,请输入 kubectl version
。
创建 ConfigMap
你可以使用 kubectl create configmap
或者在 kustomization.yaml
中的 ConfigMap 生成器来创建 ConfigMap。注意,kubectl
从 1.14 版本开始支持 kustomization.yaml
。
使用 kubectl create configmap 创建 ConfigMap
你可以使用 kubectl create configmap
命令基于目录、 文件或者字面值来创建 ConfigMap:
kubectl create configmap <映射名称> <数据源>
其中,<映射名称>
是为 ConfigMap 指定的名称,<数据源>
是要从中提取数据的目录、 文件或者字面值。 ConfigMap 对象的名称必须是合法的 DNS 子域名.
在你基于文件来创建 ConfigMap 时,<数据源>
中的键名默认取自文件的基本名, 而对应的值则默认为文件的内容。
你可以使用kubectl describe
或者 kubectl get
获取有关 ConfigMap 的信息。
基于目录创建 ConfigMap
你可以使用 kubectl create configmap
基于同一目录中的多个文件创建 ConfigMap。 当你基于目录来创建 ConfigMap 时,kubectl 识别目录下基本名可以作为合法键名的文件, 并将这些文件打包到新的 ConfigMap 中。普通文件之外的所有目录项都会被忽略 (例如:子目录、符号链接、设备、管道等等)。
例如:
# 创建本地目录
mkdir -p configure-pod-container/configmap/
# 将示例文件下载到 `configure-pod-container/configmap/` 目录
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
kubectl create configmap game-config --from-file=configure-pod-container/configmap/
以上命令将 configure-pod-container/configmap
目录下的所有文件,也就是 game.properties
和 ui.properties
打包到 game-config ConfigMap 中。你可以使用下面的命令显示 ConfigMap 的详细信息:
kubectl describe configmaps game-config
输出类似以下内容:
Name: game-config
Namespace: default
Labels: <none>
Annotations: <none>
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
configure-pod-container/configmap/
目录中的 game.properties
和 ui.properties
文件出现在 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"
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
你可以使用 kubectl create configmap
基于单个文件或多个文件创建 ConfigMap。
例如:
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties
将产生以下 ConfigMap:
kubectl describe configmaps game-config-2
输出类似以下内容:
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
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
你可以多次使用 --from-file
参数,从多个数据源创建 ConfigMap。
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties --from-file=configure-pod-container/configmap/ui.properties
你可以使用以下命令显示 game-config-2
ConfigMap 的详细信息:
kubectl describe configmaps game-config-2
输出类似以下内容:
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
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
当 kubectl
基于非 ASCII 或 UTF-8 的输入创建 ConfigMap 时, 该工具将这些输入放入 ConfigMap 的 binaryData
字段,而不是 data
中。 同一个 ConfigMap 中可同时包含文本数据和二进制数据源。 如果你想查看 ConfigMap 中的 binaryData
键(及其值), 你可以运行 kubectl get configmap -o jsonpath='{.binaryData}' <name>
。
使用 --from-env-file
选项从环境文件创建 ConfigMap,例如:
Env 文件包含环境变量列表。其中适用以下语法规则:
- Env 文件中的每一行必须为 VAR=VAL 格式。
- 以#开头的行(即注释)将被忽略。
- 空行将被忽略。
- 引号不会被特殊处理(即它们将成为 ConfigMap 值的一部分)。
将示例文件下载到 configure-pod-container/configmap/
目录:
wget https://kubernetes.io/examples/configmap/game-env-file.properties -O configure-pod-container/configmap/game-env-file.properties
wget https://kubernetes.io/examples/configmap/ui-env-file.properties -O configure-pod-container/configmap/ui-env-file.properties
Env 文件 game-env-file.properties
如下所示:
cat configure-pod-container/configmap/game-env-file.properties
enemies=aliens
lives=3
allowed="true"
kubectl create configmap game-config-env-file \
--from-env-file=configure-pod-container/configmap/game-env-file.properties
将产生以下 ConfigMap:
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"
从 Kubernetes 1.23 版本开始,kubectl
支持多次指定 --from-env-file
参数来从多个数据源创建 ConfigMap。
kubectl create configmap config-multi-env-files \
--from-env-file=configure-pod-container/configmap/game-env-file.properties \
--from-env-file=configure-pod-container/configmap/ui-env-file.properties
将产生以下 ConfigMap:
kubectl get configmap config-multi-env-files -o yaml
输出类似以下内容:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:38:34Z
name: config-multi-env-files
namespace: default
resourceVersion: "810136"
uid: 252c4572-eb35-11e7-887b-42010a8002b8
data:
allowed: '"true"'
color: purple
enemies: aliens
how: fairlyNice
lives: "3"
textmode: "true"
定义从文件创建 ConfigMap 时要使用的键
在使用 --from-file
参数时,你可以定义在 ConfigMap 的 data
部分出现键名, 而不是按默认行为使用文件名:
kubectl create configmap game-config-3 --from-file=<我的键名>=<文件路径>
<我的键名>
是你要在 ConfigMap 中使用的键名,<文件路径>
是你想要键所表示的数据源文件的位置。
例如:
kubectl create configmap game-config-3 --from-file=game-special-key=configure-pod-container/configmap/game.properties
将产生以下 ConfigMap:
kubectl get configmaps game-config-3 -o yaml
输出类似以下内容:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:54:22Z
name: game-config-3
namespace: default
resourceVersion: "530"
uid: 05f8da22-d671-11e5-8cd0-68f728db1985
data:
game-special-key: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
根据字面值创建 ConfigMap
你可以将 kubectl create configmap
与 --from-literal
参数一起使用, 通过命令行定义文字值:
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
你可以传入多个键值对。命令行中提供的每对键值在 ConfigMap 的 data
部分中均表示为单独的条目。
kubectl get configmaps special-config -o yaml
输出类似以下内容:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: special-config
namespace: default
resourceVersion: "651"
uid: dadce046-d673-11e5-8cd0-68f728db1985
data:
special.how: very
special.type: charm
基于生成器创建 ConfigMap
自 1.14 开始,kubectl
开始支持 kustomization.yaml
。 你还可以基于生成器(Generators)创建 ConfigMap,然后将其应用于 API 服务器上创建对象。 生成器应在目录内的 kustomization.yaml
中指定。
基于文件生成 ConfigMap
例如,要基于 configure-pod-container/configmap/game.properties
文件生成一个 ConfigMap:
# 创建包含 ConfigMapGenerator 的 kustomization.yaml 文件
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-4
files:
- configure-pod-container/configmap/game.properties
EOF
应用(Apply)kustomization 目录创建 ConfigMap 对象:
kubectl apply -k .
configmap/game-config-4-m9dm2f92bt created
你可以检查 ConfigMap 被创建如下:
kubectl get configmap
NAME DATA AGE
game-config-4-m9dm2f92bt 1 37s
kubectl describe configmaps/game-config-4-m9dm2f92bt
Name: game-config-4-m9dm2f92bt
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","data":{"game.properties":"enemies=aliens\nlives=3\nenemies.cheat=true\nenemies.cheat.level=noGoodRotten\nsecret.code.p...
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
Events: <none>
请注意,生成的 ConfigMap 名称具有通过对内容进行散列而附加的后缀, 这样可以确保每次修改内容时都会生成新的 ConfigMap。
定义从文件生成 ConfigMap 时要使用的键
在 ConfigMap 生成器中,你可以定义一个非文件名的键名。 例如,从 configure-pod-container/configmap/game.properties
文件生成 ConfigMap, 但使用 game-special-key
作为键名:
# 创建包含 ConfigMapGenerator 的 kustomization.yaml 文件
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-5
files:
- game-special-key=configure-pod-container/configmap/game.properties
EOF
应用 Kustomization 目录创建 ConfigMap 对象。
kubectl apply -k .
configmap/game-config-5-m67dt67794 created
基于字面值生成 ConfigMap
要基于字符串 special.type=charm
和 special.how=very
生成 ConfigMap, 可以在 kustomization.yaml
中配置 ConfigMap 生成器:
# 创建带有 ConfigMapGenerator 的 kustomization.yaml 文件
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: special-config-2
literals:
- special.how=very
- special.type=charm
EOF
应用 Kustomization 目录创建 ConfigMap 对象。
kubectl apply -k .
configmap/special-config-2-c92b5mmcf2 created
使用 ConfigMap 数据定义容器环境变量
使用单个 ConfigMap 中的数据定义容器环境变量
- 在 ConfigMap 中将环境变量定义为键值对:
- 将 ConfigMap 中定义的
special.how
赋值给 Pod 规约中的 SPECIAL_LEVEL_KEY
环境变量。
kubectl create configmap special-config --from-literal=special.how=very
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
# 定义环境变量
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
# ConfigMap 包含你要赋给 SPECIAL_LEVEL_KEY 的值
name: special-config
# 指定与取值相关的键名
key: special.how
restartPolicy: Never
创建 Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-single-configmap-env-variable.yaml
现在,Pod 的输出包含环境变量 SPECIAL_LEVEL_KEY=very
。
使用来自多个 ConfigMap 的数据定义容器环境变量
- 与前面的示例一样,首先创建 ConfigMap。
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
创建 ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmaps.yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: env-config
key: log_level
restartPolicy: Never
创建 Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-multiple-configmap-env-variable.yaml
现在,Pod 的输出包含环境变量 SPECIAL_LEVEL_KEY=very
和 LOG_LEVEL=INFO
。
将 ConfigMap 中的所有键值对配置为容器环境变量
Note: Kubernetes v1.6 和更高版本支持此功能。
- 创建一个包含多个键值对的 ConfigMap。
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
创建 ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
envFrom
将所有 ConfigMap 的数据定义为容器环境变量,ConfigMap 中的键成为 Pod 中的环境变量名称。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
创建 Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-envFrom.yaml
现在,Pod 的输出包含环境变量 SPECIAL_LEVEL=very
和 SPECIAL_TYPE=charm
。
在 Pod 命令中使用 ConfigMap 定义的环境变量
你可以使用 $(VAR_NAME)
Kubernetes 替换语法在容器的 command
和 args
属性中使用 ConfigMap 定义的环境变量。
例如,以下 Pod 规约
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/echo", "$(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_TYPE
restartPolicy: Never
通过运行下面命令创建 Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-env-var-valueFrom.yaml
在 test-container
容器中产生以下输出:
very charm
将 ConfigMap 数据添加到一个卷中
如基于文件创建 ConfigMap 中所述,当你使用 --from-file
创建 ConfigMap 时,文件名成为存储在 ConfigMap 的 data
部分中的键, 文件内容成为键对应的值。
本节中的示例引用了一个名为 'special-config' 的 ConfigMap,如下所示:
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
创建 ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
使用存储在 ConfigMap 中的数据填充卷
在 Pod 规约的 volumes
部分下添加 ConfigMap 名称。 这会将 ConfigMap 数据添加到 volumeMounts.mountPath
所指定的目录 (在本例中为 /etc/config
)。 command
部分列出了名称与 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/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
# 提供包含要添加到容器中的文件的 ConfigMap 的名称
name: special-config
restartPolicy: Never
创建 Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume.yaml
Pod 运行时,命令 ls /etc/config/
产生下面的输出:
SPECIAL_LEVEL
SPECIAL_TYPE
Caution: 如果在
/etc/config/
目录中有一些文件,这些文件将被删除。
Note: 文本数据会展现为 UTF-8 字符编码的文件。如果使用其他字符编码, 可以使用
binaryData
。
将 ConfigMap 数据添加到卷中的特定路径
使用 path
字段为特定的 ConfigMap 项目指定预期的文件路径。 在这里,ConfigMap 中键 SPECIAL_LEVEL
的内容将挂载在 config-volume
卷中 /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
创建Pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume-specific-key.yaml
当 Pod 运行时,命令 cat /etc/config/keys
产生以下输出:
very
Caution: 如前,
/etc/config/
目录中所有先前的文件都将被删除。
映射键到指定路径并设置文件访问权限
你可以将指定键名投射到特定目录,也可以逐个文件地设定访问权限。
可选的引用
ConfigMap 引用可以被标记为 “optional(可选的)”。如果所引用的 ConfigMap 不存在, 则所挂载的卷将会是空的。如果所引用的 ConfigMap 确实存在,但是所引用的主键不存在, 则在挂载点下对应的路径也会不存在。
挂载的 ConfigMap 将自动更新
当某个已被挂载的 ConfigMap 被更新,所投射的内容最终也会被更新。 对于 Pod 已经启动之后所引用的、可选的 ConfigMap 才出现的情形, 这一动态更新现象也是适用的。
kubelet
在每次周期性同步时都会检查已挂载的 ConfigMap 是否是最新的。 但是,它使用其本地的基于 TTL 的缓存来获取 ConfigMap 的当前值。 因此,从更新 ConfigMap 到将新键映射到 Pod 的总延迟可能与 kubelet 同步周期(默认 1 分钟) + ConfigMap 在 kubelet 中缓存的 TTL (默认 1 分钟)一样长。 你可以通过更新 Pod 的某个注解来触发立即更新。
Note: 使用 ConfigMap 作为 subPath 的数据卷将不会收到 ConfigMap 更新。
了解 ConfigMap 和 Pod
ConfigMap API 资源将配置数据存储为键值对。 数据可以在 Pod 中使用,也可以用来提供系统组件(如控制器)的配置。 ConfigMap 与 Secret 类似, 但是提供的是一种处理不含敏感信息的字符串的方法。 用户和系统组件都可以在 ConfigMap 中存储配置数据。
Note: ConfigMap 应该引用属性文件,而不是替换它们。可以将 ConfigMap 理解为类似于 Linux
/etc
目录及其内容的东西。例如,如果你基于 ConfigMap 创建 Kubernetes 卷,则 ConfigMap 中的每个数据项都由该数据卷中的某个独立的文件表示。
ConfigMap 的 data
字段包含配置数据。如下例所示,它可以简单 (如用 --from-literal
的单个属性定义)或复杂 (如用 --from-file
的配置文件或 JSON blob定义)。
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: example-config
namespace: default
data:
# 使用 --from-literal 定义的简单属性
example.property.1: hello
example.property.2: world
# 使用 --from-file 定义复杂属性的例子
example.property.file: |-
property.1=value-1
property.2=value-2
property.3=value-3
限制
- 在 Pod 规约中引用某个 ConfigMap 之前,必须先创建它(除非将 ConfigMap 标记为 “optional(可选)”)。如果引用的 ConfigMap 不存在,则 Pod 将不会启动。 同样,引用 ConfigMap 中不存在的主键也会令 Pod 无法启动。
- 如果你使用
envFrom
来基于 ConfigMap 定义环境变量,那么无效的键将被忽略。 Pod 可以被启动,但无效名称将被记录在事件日志中(InvalidVariableNames
)。 日志消息列出了每个被跳过的键。例如:
kubectl get events
输出与此类似:
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE
0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames {kubelet, 127.0.0.1} Keys [1badkey, 2alsobad] from the EnvFrom configMap default/myconfig were skipped since they are considered invalid environment variable names.
更多建议: