目录
前言:为什么需要 K8s 配置管理?
一、为什么需要 ConfigMap 和 Secret?
二、ConfigMap:非敏感配置的管理工具
1. 什么是 ConfigMap?
2. 实战:创建 ConfigMap 的 4 种方式
① 基于目录创建(多文件批量导入)
② 基于单个文件创建(指定 key 名)
③ 基于 ENV 文件创建(key=value 格式)
④ 基于命令行键值对创建(少量配置)
3. 实战:在 Pod 中使用 ConfigMap
① 作为环境变量注入
② 作为文件挂载
③ 高级技巧:自定义文件名和权限
④ 解决挂载覆盖问题:SubPath
4. ConfigMap 的使用限制
三、Secret:敏感信息的安全管理
1. 实战:创建 Secret 的 2 种方式
① 用命令行从文件创建
② 用 YAML 文件创建(手动编码)
2. 在 Pod 中使用 Secret
① 作为文件挂载(推荐,支持动态更新)
② 作为环境变量
3. 解码 Secret
四、总结
在传统应用中,配置文件常存在本地或代码仓库,容器化后因节点不固定、镜像与配置耦合,修改配置需重新构建镜像,十分繁琐。
Kubernetes 通过ConfigMap(非敏感配置)和Secret(敏感配置)解决这一问题,实现配置与镜像解耦,提升灵活性与安全性。
在容器化部署中,配置文件如果打包进镜像,改配置就得重新构建镜像,非常麻烦;而且密码、令牌等敏感信息明文存放也存在安全风险。
Kubernetes 的ConfigMap和Secret就是为解决这些问题而生的:
ConfigMap 是 Kubernetes 中用于存储非加密配置数据的键值对资源,数据存在 etcd 中,可作为环境变量、命令行参数或文件挂载到 Pod。
核心优势:
适合有多个配置文件的场景,比如应用的多个环境配置。
# 1. 创建测试目录和文件
mkdir /conf
echo "This is file01" > /conf/file01.conf
echo "This is file02" > /conf/file02.conf
# 2. 从目录创建ConfigMap
kubectl create configmap game-config-1 --from-file=/conf/
# 3. 查看结果(key默认是文件名)
kubectl get cm game-config-1 -o yaml
输出解析:
data:
file01.conf: "This is file01"
file02.conf: "This is file02"
目录下的每个文件会成为 ConfigMap 的一个键值对,文件名是 key,文件内容是 value。
代码解释:
- 先创建一个/conf目录,并在其中生成两个配置文件file01.conf和file02.conf。
- 使用kubectl create configmap命令,通过--from-file=/conf/指定从目录创建,K8s 会将目录下所有文件以 “文件名:文件内容” 的键值对形式存入 ConfigMap。
- 最后用kubectl get cm命令查看创建的 ConfigMap 详情,-o yaml表示以 YAML 格式输出。
如果想自定义 key 名称,而非使用默认文件名,可以用--from-file=<自定义key>=<文件路径>
。
# 1. 创建测试文件
echo "This is game config" > /conf/game.cfg
# 2. 自定义key创建ConfigMap
kubectl create configmap game-config-2 --from-file=app.conf=/conf/game.cfg
# 3. 查看结果
kubectl get cm game-config-2 -o yaml
代码解释:
先创建一个game.cfg文件并写入内容。
创建 ConfigMap 时,通过--from-file=app.conf=/conf/game.cfg自定义 key 为app.conf,值为game.cfg的文件内容。
查看结果时,能看到 ConfigMap 中以自定义的app.conf作为 key。
输出解析:
data:
app.conf: "This is game config" # key是自定义的app.conf
适合存储环境变量配置,直接导入key=value
格式的文件。
# 1. 创建ENV文件
cat << EOF > /conf/app-env.cfg
DB_HOST=mysql
DB_PORT=3306
EOF
# 2. 从ENV文件创建
kubectl create configmap app-env-config --from-env-file=/conf/app-env.cfg
# 3. 查看结果(直接解析为键值对)
kubectl get cm app-env-config -o yaml
代码解释:
- 用cat << EOF语法创建一个app-env.cfg文件,其中内容为key=value格式的环境变量配置。
- 通过--from-env-file参数从 ENV 文件创建 ConfigMap,K8s 会自动将文件中的key=value解析为 ConfigMap 的键值对。
输出解析:
data:
DB_HOST: "mysql"
DB_PORT: "3306"
适合配置项较少的场景,直接在命令行指定key=value
。
# 创建包含两个键值对的ConfigMap
kubectl create configmap spec-config --from-literal=log_level=info --from-literal=max_conn=100
# 查看结果
kubectl get cm spec-config -o yaml
代码解释:
- 使用--from-literal参数直接在命令行定义键值对,多个键值对可多次使用该参数。这里创建了log_level=info和max_conn=100两个配置项。
- 这种方式适合配置项较少的情况,无需创建额外文件。
输出解析:
data:
log_level: "info"
max_conn: "100"
适合需要通过环境变量读取配置的应用(如 Java 应用的spring.profiles.active
)。
# env-test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: env-test-pod
spec:
containers:
- name: test-container
image: busybox:v1
command: ["sh", "-c", "env"] # 输出环境变量
env:
# 单个环境变量(自定义变量名)
- name: LOG_LEVEL # 容器内的环境变量名
valueFrom:
configMapKeyRef:
name: spec-config # 引用的ConfigMap名称
key: log_level # 引用的key
# 批量注入所有键值对
envFrom:
- configMapRef:
name: app-env-config # 引用包含DB_HOST、DB_PORT的ConfigMap
restartPolicy: Never
部署并验证:
kubectl create -f env-test-pod.yaml
kubectl logs env-test-pod # 会输出LOG_LEVEL=info、DB_HOST=mysql等变量
配置解析:
valueFrom
:单独引用 ConfigMap 中的某个 key,可自定义环境变量名。envFrom
:批量导入 ConfigMap 的所有键值对,变量名与 key 一致。适合需要读取配置文件的应用(如 Nginx 的nginx.conf
)。
# file-mount-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: file-mount-pod
spec:
containers:
- name: test-container
image: nginx:1.7.9
volumeMounts:
- name: config-volume # 关联下面的卷名
mountPath: /etc/config # 挂载到容器的目录
volumes:
- name: config-volume
configMap:
name: game-config-1 # 引用的ConfigMap名称
部署并验证:
kubectl create -f file-mount-pod.yaml
kubectl exec -ti file-mount-pod -- ls /etc/config # 会看到file01.conf、file02.conf
配置解析:
/etc/config
目录下,文件内容为对应的 value3。如果需要修改挂载后的文件名或权限,可以通过items
配置:
volumes:
- name: config-volume
configMap:
name: game-config-1
items:
- key: file01.conf # ConfigMap中的key
path: app1.cfg # 挂载后的文件名
mode: 0644 # 文件权限(八进制)
- key: file02.conf
path: app2.cfg
mode: 0755
直接挂载 ConfigMap 会覆盖容器内的目录(原目录文件会丢失),用subPath
可只挂载单个文件,不影响其他内容:
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/nginx.conf # 容器内的目标文件
subPath: nginx.conf # ConfigMap中对应的key(文件名)
适用场景:修改 Nginx 配置文件时,不覆盖/etc/nginx
目录下的其他文件。
Pending
)key
必须存在于 ConfigMap 中(否则 Pod 启动失败,状态为ContainerCreating
)default
下)Secret 用于存储密码、令牌等敏感信息,与 ConfigMap 用法类似,但数据会经过 Base64 编码(注意:编码不是加密,生产环境需配合集群加密配置)
适合从现有密钥文件(如 SSH 密钥)创建 Secret:
# 1. 创建存储敏感信息的文件
echo -n "admin" > ./username.txt # 用户名(-n避免换行)
echo -n "mypassword" > ./password.txt # 密码
# 2. 从文件创建Secret
kubectl create secret generic db-creds --from-file=./username.txt --from-file=./password.txt
查看结果:
kubectl get secret db-creds -o yaml # 数据会显示为Base64编码
适合直接定义敏感信息,需先手动 Base64 编码:
# 1. 对明文进行Base64编码
echo -n "admin" | base64 # 输出:YWRtaW4=
echo -n "mypassword" | base64 # 输出:bXlwYXNzd29yZA==
# 2. 创建YAML文件
cat << EOF > db-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque # 通用类型,存储键值对
data:
username: YWRtaW4= # 编码后的用户名
password: bXlwYXNzd29yZA== # 编码后的密码
EOF
# 3. 创建Secret
kubectl create -f db-secret.yaml
与 ConfigMap 完全一致,支持环境变量和文件挂载:
# secret-mount-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-mount-pod
spec:
containers:
- name: test-container
image: nginx:1.7.9
volumeMounts:
- name: secret-volume
mountPath: /etc/secret # 挂载目录(只读)
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-secret # 引用的Secret名称
验证:
kubectl create -f secret-mount-pod.yaml
kubectl exec -ti secret-mount-pod -- cat /etc/secret/username # 输出admin
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
查看 Secret 时数据是编码后的,可用以下命令解码:
# 1. 获取编码后的密码
kubectl get secret db-secret -o jsonpath='{.data.password}' # 输出bXlwYXNzd29yZA==
# 2. 解码
echo "bXlwYXNzd29yZA==" | base64 --decode # 输出mypassword
Kubernetes 的配置管理核心是解耦与安全: