Kubernetes ConfigMap 与 Secret
Kubernetes ConfigMap 与 Secret 完全指南(适用于 Kubernetes v1.35)
文档说明
- 适用版本:Kubernetes v1.35.4
- 前置知识:了解 Pod、Deployment 的基本概念
- 目标:从零掌握 ConfigMap 和 Secret 的原理、配置与使用
第一章:为什么需要 ConfigMap 和 Secret?
在 Kubernetes 中,应用通常需要各种配置信息才能正常运行——数据库地址、日志级别、功能开关、密码等。如果把这些配置硬编码在容器镜像里:
- 修改配置需要重新构建镜像,流程繁琐
- 不同环境(开发/测试/生产)需要不同镜像,难以管理
- 敏感信息(密码、密钥)暴露在镜像中,存在严重安全风险
ConfigMap 和 Secret 正是为了解决这些问题而设计的——它们将配置信息与容器镜像解耦,让你可以在不重新构建镜像的情况下修改应用配置。
| 资源类型 | 用途 | 数据特点 |
|---|---|---|
| ConfigMap | 存储非敏感配置信息 | 明文存储 |
| Secret | 存储敏感信息(密码、Token、证书等) | Base64 编码存储 |
第二章:ConfigMap 详解
2.1 什么是 ConfigMap?
ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。Pod 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。
核心价值:ConfigMap 将你的环境配置信息和容器镜像解耦,便于应用配置的修改。
2.2 ConfigMap 的核心特性
| 特性 | 说明 |
|---|---|
| 存储方式 | 键值对(Key-Value) |
| 数据字段 | data(UTF-8 字符串)和 binaryData(Base64 编码的二进制数据) |
| 大小限制 | 每个 ConfigMap 最大 1 MiB |
| 用途 | 环境变量、配置文件挂载、命令行参数 |
| 不可变 | 支持设置 immutable: true,创建后不可修改 |
⚠️ 注意:ConfigMap 不提供保密或者加密功能。如果你想存储的数据是机密的,请使用 Secret。
2.3 ConfigMap YAML 示例
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: default
data:
# 简单键值对
LOG_LEVEL: "info"
DATABASE_HOST: "postgres-service.default.svc.cluster.local"
DATABASE_PORT: "5432"
FEATURE_NEW_UI: "true"
# 多行配置文件内容(使用 |)
app.properties: |
server.port=8080
server.timeout=30s
cache.enabled=true
# 配置文件内容(XML/JSON/YAML 格式均可)
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
}
}
字段说明:
| 字段 | 说明 |
|---|---|
apiVersion | 固定为 v1 |
kind | 固定为 ConfigMap |
metadata.name | ConfigMap 名称,必须是合法的 DNS 子域名 |
data | 存储配置数据,键名只能由字母、数字、-、_ 或 . 组成 |
2.4 创建 ConfigMap 的四种方式
方式一:从字面值创建
kubectl create configmap app-config \
--from-literal=LOG_LEVEL=info \
--from-literal=DATABASE_HOST=postgres-service
方式二:从文件创建
# 文件内容成为值,文件名成为键
kubectl create configmap app-config --from-file=./app.properties
# 指定键名
kubectl create configmap app-config --from-file=config=./app.properties
方式三:从目录创建
# 目录下每个文件成为一个键值对
kubectl create configmap app-config --from-file=./config-dir/
方式四:从 YAML 文件创建(推荐)
kubectl apply -f configmap.yaml
2.5 在 Pod 中使用 ConfigMap
方式一:作为环境变量注入
单个键注入:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-app
image: my-app:v1
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOST
批量注入所有键:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-app
image: my-app:v1
envFrom:
- configMapRef:
name: app-config # 注入所有键作为环境变量
方式二:作为文件挂载(Volume)
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-app
image: my-app:v1
volumeMounts:
- name: config-volume
mountPath: /etc/config # 挂载到容器内的路径
volumes:
- name: config-volume
configMap:
name: app-config # 引用 ConfigMap
挂载后的效果:ConfigMap 中的每个键(key)都会成为挂载目录下的一个文件,文件名就是键名,文件内容就是键值。
例如,上面的 ConfigMap 挂载到 /etc/config 后,会产生:
/etc/config/LOG_LEVEL→ 内容为info/etc/config/DATABASE_HOST→ 内容为postgres-service.default.svc.cluster.local/etc/config/app.properties→ 内容为多行配置文本
挂载特定键为单个文件:
volumes:
- name: config-volume
configMap:
name: app-config
items:
- key: app.properties
path: application.properties # 指定挂载后的文件名
2.6 不可变 ConfigMap(Immutable ConfigMap)
从 Kubernetes v1.19 开始,你可以将 ConfigMap 设置为不可变(Immutable) 。
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
immutable: true # 设置为不可变
data:
LOG_LEVEL: "info"
优点:
- 防止意外修改
- 提高性能(kube-apiserver 不再需要监视不可变对象的变化)
注意:一旦设置为不可变,无法修改或删除该 ConfigMap(除非删除整个对象)。
第三章:Secret 详解
3.1 什么是 Secret?
Secret 是 Kubernetes 中用于存储敏感信息的对象,如密码、OAuth 令牌、SSH 密钥、TLS 证书等。
核心价值:Secret 将敏感内容与 Pod 分离,避免在源代码或容器镜像中暴露机密信息。
3.2 Secret 与 ConfigMap 的核心区别
| 对比维度 | ConfigMap | Secret |
|---|---|---|
| 设计用途 | 非机密配置数据 | 敏感信息(密码、Token、证书) |
| 数据编码 | 明文(UTF-8 字符串) | Base64 编码 |
| 大小限制 | 1 MiB | 1 MiB(默认) |
| 静态加密 | 不支持 | 支持(需配置) |
| 适用场景 | 日志级别、端口号、功能开关 | 数据库密码、API 密钥、TLS 证书 |
3.3 Secret 的类型
| 类型 | 用途 |
|---|---|
Opaque | 通用类型,适用于大多数场景(密码、API 密钥等) |
kubernetes.io/tls | 存储 TLS 证书和私钥 |
kubernetes.io/dockerconfigjson | 存储 Docker 仓库认证信息 |
kubernetes.io/basic-auth | 存储基本认证凭据(用户名/密码) |
kubernetes.io/ssh-auth | 存储 SSH 认证凭据 |
kubernetes.io/service-account-token | 服务账户令牌(由 Kubernetes 自动创建) |
3.4 Secret YAML 示例
使用 data 字段(Base64 编码)
Step 1:对敏感数据进行 Base64 编码:
echo -n 'admin' | base64 # 输出:YWRtaW4=
echo -n 'MyP@ssw0rd' | base64 # 输出:TXlQQHNzdzByZA==
Step 2:编写 Secret YAML:
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: YWRtaW4= # Base64 编码后的 "admin"
password: TXlQQHNzdzByZA== # Base64 编码后的 "MyP@ssw0rd"
使用 stringData 字段(未编码,更便捷)
stringData 字段允许你直接写入未编码的字符串,Kubernetes 会在创建时自动进行 Base64 编码。
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
stringData:
username: admin # 直接写明文,自动编码
password: MyP@ssw0rd
config.yaml: | # 也可以存储整个配置文件
apiUrl: "https://api.example.com"
timeout: 30
⚠️ 注意:当你检索 Secret 数据时,返回的是编码后的值,而不是
stringData中提供的纯文本值。
3.5 创建 Secret 的三种方式
方式一:从字面值创建
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password=MyP@ssw0rd
方式二:从文件创建
# 文件内容成为值,文件名成为键
kubectl create secret generic db-credentials \
--from-file=./username.txt \
--from-file=./password.txt
方式三:从 YAML 文件创建(推荐)
kubectl apply -f secret.yaml
创建 TLS Secret:
kubectl create secret tls example-tls \
--cert=./tls.crt \
--key=./tls.key
3.6 在 Pod 中使用 Secret
方式一:作为环境变量注入
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-app
image: my-app:v1
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
批量注入所有键:
envFrom:
- secretRef:
name: db-credentials
方式二:作为文件挂载(Volume)
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-app
image: my-app:v1
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-credentials
挂载后的效果:Secret 中的每个键都会成为挂载目录下的一个文件。例如:
/etc/secrets/username→ 内容为admin/etc/secrets/password→ 内容为MyP@ssw0rd
挂载特定键并指定文件权限:
volumes:
- name: secret-volume
secret:
secretName: db-credentials
defaultMode: 0400 # 文件权限(只读)
items:
- key: username
path: db-user # 重命名文件
mode: 0600 # 单独指定权限
💡 推荐:使用卷挂载方式而非环境变量,因为环境变量可能在调试信息、日志中意外暴露。
3.7 Secret 的安全注意事项
⚠️ 重要安全警告:
-
默认情况下,Secret 未加密地存储在 etcd 中。任何拥有 API 访问权限的人都可以检索或修改 Secret,任何有权访问 etcd 的人也可以。
-
Secret 的 Base64 编码不是加密。它只是编码,不是加密。
-
授予对 Secret 的 list 访问权限,意味着允许获取 Secret 的内容。
-
如果一个用户可以创建使用某 Secret 的 Pod,则该用户也可以看到该 Secret 的值。
生产环境安全建议:
| 建议 | 说明 |
|---|---|
| 启用静态加密 | 配置 etcd 对 Secret 数据进行加密存储 |
| 最小权限访问 | 使用 RBAC 严格控制对 Secret 的访问权限 |
| 使用单独的命名空间 | 隔离不同团队/应用的 Secret 访问 |
| 使用短期 Secret | 尽量使用有效期短的凭证 |
| 保护 etcd 访问 | 仅允许集群管理员访问 etcd |
| etcd 通信加密 | 多个 etcd 实例之间配置加密的 SSL/TLS 通信 |
第四章:ConfigMap 与 Secret 的更新与生效机制
4.1 更新 ConfigMap/Secret 后,Pod 会怎样?
| 使用方式 | 更新后是否自动生效 | 说明 |
|---|---|---|
| 环境变量注入 | ❌ 不会生效 | 环境变量在 Pod 启动时已固定,需重启 Pod 才能生效 |
| 卷挂载(Volume) | ✅ 会自动更新 | 文件内容会更新,但应用进程不会自动重启 |
关键点:即使 ConfigMap/Secret 作为卷挂载的文件内容自动更新了,容器内的进程不会自动重启。如果你的应用需要重新加载配置,需要实现配置热加载机制(如发送
SIGHUP信号)或滚动重启 Pod。
4.2 如何触发 Pod 重启?
当 ConfigMap/Secret 更新后需要 Pod 重启时,常用方法:
方法一:使用滚动更新
kubectl rollout restart deployment/my-app
方法二:使用 Helm 的 --recreate-pods
helm upgrade my-app ./chart --recreate-pods
方法三:修改 Pod 注解(触发滚动更新)
在 Deployment 的 template 中添加一个会随 ConfigMap 变化而变化的注解:
spec:
template:
metadata:
annotations:
config-hash: "{{ .Values.configHash }}" # 随 ConfigMap 变化而变化
第五章:完整实战示例
5.1 场景:部署一个使用 ConfigMap 和 Secret 的 Web 应用
Step 1:创建 ConfigMap(应用配置)
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: web-app-config
data:
LOG_LEVEL: "info"
API_TIMEOUT: "30"
FEATURE_FLAG_DEBUG: "false"
app-settings.json: |
{
"cache": {
"enabled": true,
"ttl": 300
},
"rateLimit": {
"requestsPerSecond": 100
}
}
Step 2:创建 Secret(数据库密码)
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: web-app-secret
type: Opaque
stringData:
DB_PASSWORD: "SecurePassword123"
API_KEY: "sk-1234567890abcdef"
Step 3:部署应用并注入配置
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 2
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: app
image: my-web-app:v1
ports:
- containerPort: 8080
# 环境变量注入(ConfigMap + Secret)
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: web-app-config
key: LOG_LEVEL
- name: API_TIMEOUT
valueFrom:
configMapKeyRef:
name: web-app-config
key: API_TIMEOUT
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: web-app-secret
key: DB_PASSWORD
- name: API_KEY
valueFrom:
secretKeyRef:
name: web-app-secret
key: API_KEY
# 配置文件挂载(ConfigMap)
volumeMounts:
- name: config-volume
mountPath: /app/config
readOnly: true
# 敏感信息挂载(Secret)
- name: secret-volume
mountPath: /app/secrets
readOnly: true
volumes:
- name: config-volume
configMap:
name: web-app-config
- name: secret-volume
secret:
secretName: web-app-secret
defaultMode: 0400
Step 4:部署
kubectl apply -f configmap.yaml
kubectl apply -f secret.yaml
kubectl apply -f deployment.yaml
Step 5:验证
# 查看 ConfigMap
kubectl get configmap web-app-config
kubectl describe configmap web-app-config
# 查看 Secret(注意:值会以 Base64 显示)
kubectl get secret web-app-secret
kubectl describe secret web-app-secret
# 进入 Pod 验证挂载
kubectl exec -it <pod-name> -- cat /app/config/LOG_LEVEL
kubectl exec -it <pod-name> -- cat /app/secrets/DB_PASSWORD
第六章:最佳实践总结
6.1 ConfigMap 最佳实践
- ConfigMap 只用于非敏感数据:敏感信息请使用 Secret
- 注意 1 MiB 大小限制:大配置文件考虑使用存储卷或外部配置服务
- 使用
immutable保护关键配置:对于生产环境不应变更的配置,设置为不可变 - 配置与代码分离:不要在镜像中硬编码环境相关的配置
- 合理组织 ConfigMap:按功能或应用拆分,避免单个 ConfigMap 过大
6.2 Secret 最佳实践
- 启用 etcd 静态加密:生产环境必须配置
- 使用 RBAC 最小权限原则:严格限制谁可以访问 Secret
- 优先使用卷挂载而非环境变量:降低泄露风险
- 避免在日志或调试信息中暴露 Secret
- 使用短期凭证:尽可能使用有效期短的凭据
- 不要将 Secret 提交到 Git 仓库:使用
stringData时同样注意
6.3 通用最佳实践
| 实践 | 说明 |
|---|---|
| ConfigMap 和 Secret 必须在同一 Namespace | Pod 只能引用同 Namespace 的 ConfigMap/Secret |
| 先创建 ConfigMap/Secret,再创建 Pod | 否则 Pod 会因找不到配置而启动失败 |
| 使用有意义的命名 | 如 app-config、db-credentials,便于识别 |
| 版本管理 | 将 ConfigMap/Secret 的 YAML 文件纳入 Git 管理(Secret 需加密) |
| 监控和审计 | 监控 Secret 的访问,配置审计规则 |
附录:快速索引
| 需求 | 命令/配置 |
|---|---|
| 查看所有 ConfigMap | kubectl get configmap |
| 查看所有 Secret | kubectl get secret |
| 查看 ConfigMap 详情 | kubectl describe configmap <name> |
| 查看 Secret 详情(Base64) | kubectl describe secret <name> |
| 解码 Secret 值 | kubectl get secret <name> -o jsonpath='{.data.password}' | base64 -d |
| 创建 ConfigMap(字面值) | kubectl create configmap <name> --from-literal=key=value |
| 创建 Secret(字面值) | kubectl create secret generic <name> --from-literal=key=value |
| 创建 TLS Secret | kubectl create secret tls <name> --cert=./cert.crt --key=./key.key |
| 从 YAML 创建 | kubectl apply -f <file>.yaml |
| 删除 ConfigMap/Secret | kubectl delete configmap <name> / kubectl delete secret <name> |
| 触发 Pod 重启 | kubectl rollout restart deployment/<name> |
| 设置 ConfigMap 不可变 | immutable: true |
文档版本:v1.0
适用环境:Kubernetes v1.35+ /v1API
前置条件:已部署 Kubernetes 集群并配置kubectl
更多推荐
所有评论(0)