Kubernetes
是一个广泛使用的容器编排平台,它提供了一系列的组件和核心概念来帮助用户管理容器化的应用程序。在 Kubernetes 中,ConfigMap 和 Secret 是两个重要的概念,它们用于管理应用程序的配置信息和敏感信息。在本文中,我们将深入介绍 Kubernetes 中的 ConfigMap
和 Secret
,并演示如何使用命令行和 YAML 文件创建它们。我们还将通过一个实际的应用程序场景来演示如何使用 ConfigMap 和 Secret 来管理应用程序的配置和敏感信息。本文适合 Kubernetes 初学者和使用者,希望能够帮助读者更好地理解和使用 ConfigMap 和 Secret。
ConfigMap:用于存储应用程序的配置信息,例如环境变量、配置文件等。 可以通过挂载到 Pod 中的卷或环境变量的方式使用。
使用 kubectl create configmap
命令基于目录、 文件或者字符串来创建 ConfigMap
可以使用 kubectl create configmap
基于同一目录中的多个文件创建 ConfigMap。 当你基于目录来创建 ConfigMap 时,kubectl 识别目录下基本名可以作为合法键名的文件, 并将这些文件打包到新的 ConfigMap 中。普通文件之外的所有目录项都会被忽略 (例如:子目录、符号链接、设备、管道等等)。
#1. 基于目录创建 ConfigMap
mkdir -p configure-pod-container/configmap/
# 准备game.properties 和 ui.properties 文件
# 将示例文件下载到 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
kubectl create configmap game-config --from-file=configure-pod-container/configmap/ -n test
kubectl get cm -n test
kubectl describe cm game-config -n test
kubectl get configmaps game-config -o yaml -n test
可以使用 kubectl create configmap
基于单个文件或多个文件创建 ConfigMap。
# 基于文件创建 ConfigMap
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties
kubectl describe configmaps game-config-2
#可以多次使用 --from-file 参数,从多个数据源创建 ConfigMap。
kubectl create configmap game-config-3 --from-file=configure-pod-container/configmap/game.properties --from-file=configure-pod-container/configmap/ui.properties
kubectl describe configmaps game-config-3
使用 --from-env-file
选项从环境文件创建 ConfigMap
Env 文件包含环境变量列表。其中适用以下语法规则:
VAR=VAL
格式。#
开头的行(即注释)将被忽略。# 将示例文件下载到 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
#
kubectl create configmap game-config-env-file \
--from-env-file=configure-pod-container/configmap/game-env-file.properties -n test
kubectl get configmap game-config-env-file -n test -o yaml
从 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
在使用 --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 -n test
kubectl get configmaps game-config-3 -n test -o yaml
可以将 kubectl create configmap
与 --from-literal
参数一起使用, 通过命令行定义文字值。
可以传入多个键值对。命令行中提供的每对键值在 ConfigMap 的 data 部分中均表示为单独的条目。
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm -n test
kubectl get configmaps special-config -n test -o yaml
Secret:用于存储敏感信息,例如密码、证书等。Secret 提供了一种安全地存储和传输敏感信息的方式,可以通过挂载到 Pod 中的卷或环境变量的方式使用。
Secret有三种类型:
echo -n 'admin' > ./username.txt
echo -n '1f2d1e2e67df' > ./password.txt
# 从文件创建
kubectl create secret generic user-pass-secret --from-file=./username.txt --from-file=./password.txt -n test
kubectl get secret -n test
kubectl describe secrets/user-pass-secret -n test
# 通过yaml文件方式查看
kubectl get secrets/user-pass-secret -n test -o yaml
# 删除secret
kubectl delete secrets/user-pass-secret -n test
echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
echo 'YWRtaW4=' | base64 --decode
kubectl create secret generic db-user-pass \
--from-literal=username=admin \
--from-literal=password='123456' \
-n test
kubectl get secret -n test
kubectl get secrets/db-user-pass -n test -o yaml
如果密码中包含特殊字符需要转码(例如 $、*、\、!),请使用 \
进行转码
需要先将字符串进行base64编码
echo -n 'admin' | base64
echo -n '123456' | base64
apiVersion: v1
kind: Secret
metadata:
name: mysecret
namespace: test
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
执行kubectl apply -f secret.yaml
命令创建。
如果并不想先将用户名和密码转换为 base64 编码之后再创建 Secret,则,可以通过定义 stringData
实现:
data 字段用来存储 base64 编码的任意数据。 提供 stringData 字段是为了方便,它允许 Secret 使用未编码的字符串。 data 和 stringData 的键必须由字母、数字、-、_ 或 . 组成。
apiVersion: v1
kind: Secret
metadata:
name: mysecret
namespace: test
type: Opaque
stringData:
username: admin
password: '123456'
执行命令 kubectl apply -f secret.yaml
创建。
但是此时在元数据信息 annotation 中可以看到 password 的明文:
kubectl get secret mysecret -o yaml -n test
创建ConfigMap
# 创建一个ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: test
data:
special.how: very
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: test
data:
log_level: INFO
创建Pod yaml文件,在spec.containers
层级下添加env
属性,
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
namespace: test
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
#可以使用 $(VAR_NAME) Kubernetes 替换语法在容器的 command 和 args 属性中使用 ConfigMap 定义的环境变量
command: [ "/bin/echo", "$(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
# 定义环境变量
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
# ConfigMap 包含你要赋给 SPECIAL_LEVEL_KEY 的值
name: special-config
# 指定与取值相关的键名
key: special.how
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: env-config
key: log_level
restartPolicy: Never
进入容器内部执行echo $SPECIAL_LEVEL_KEY
命令
使用 envFrom
将所有 ConfigMap 的数据定义为容器环境变量,ConfigMap 中的键成为 Pod 中的环境变量名称。
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: test
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
---
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
namespace: test
spec:
containers:
- name: test-container
image: nginx
envFrom:
- configMapRef:
name: special-config
restartPolicy: Never
在 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: registry.k8s.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
还可以使用 path 字段为特定的 ConfigMap 项目指定预期的文件路径。 在这里,ConfigMap 中键 SPECIAL_LEVEL 的内容将挂载在 config-volume 卷中 /etc/config/keys 文件中:
当某个已被挂载的 ConfigMap 被更新,所投射的内容最终也会被更新。 对于 Pod 已经启动之后所引用的、可选的 ConfigMap 才出现的情形, 这一动态更新现象也是适用的。
kubelet 在每次周期性同步时都会检查已挂载的 ConfigMap 是否是最新的。 但是,它使用其本地的基于 TTL 的缓存来获取 ConfigMap 的当前值。 因此,从更新 ConfigMap 到将新键映射到 Pod 的总延迟可能等于 kubelet 同步周期 (默认 1 分钟) + ConfigMap 在 kubelet 中缓存的 TTL(默认 1 分钟)。
注意:使用 ConfigMap 作为subPath
的数据卷将不会收到 ConfigMap 更新。
Secret与ConfigMap用法相同
apiVersion: v1
kind: Pod
metadata:
name: pod-secret
spec:
containers:
- name: pod-with-secret
image: nginx
volumeMounts:
- name: my-secret
mountPath: "/etc/secret"
readOnly: true
volumes:
- name: my-secret
secret:
secretName: password
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
enemies=aliens
lives=3
allowed="true"
color=purple
textmode=true
how=fairlyNice