深色模式
ConfigMap 与 Secret 配置管理
摘要:本文演示如何用 ConfigMap 管理应用配置、用 Secret 存放密码令牌,对比环境变量与文件挂载两种注入方式,并说明配置热更新的真实行为与 Secret 的安全边界。
适用环境
- 可用 K8s 集群 +
kubectl - 示例镜像:
nginx:alpine、busybox
操作步骤
一、创建 ConfigMap
命令行方式:
bash
kubectl create configmap app-config \
--from-literal=APP_ENV=prod \
--from-literal=LOG_LEVEL=info
kubectl create configmap nginx-conf --from-file=nginx.conf1
2
3
4
5
2
3
4
5
YAML 方式(推荐,可进版本库):
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "prod"
LOG_LEVEL: "info"
app.yaml: |
server:
port: 8080
timeout: 30s1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
二、创建 Secret
bash
kubectl create secret generic db-cred \
--from-literal=username=appuser \
--from-literal=password='ExamplePass123'
# 从文件创建(如 TLS 证书)
kubectl create secret tls web-tls --cert=server.crt --key=server.key
# 私有镜像仓库凭据
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user --docker-password=pass1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
YAML 方式需先 base64 编码(stringData 可写明文,更方便):
yaml
apiVersion: v1
kind: Secret
metadata:
name: db-cred
type: Opaque
stringData:
username: appuser
password: ExamplePass1231
2
3
4
5
6
7
8
2
3
4
5
6
7
8
三、注入方式一:单个环境变量
yaml
spec:
containers:
- name: app
image: nginx:alpine
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-cred
key: password1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
四、注入方式二:整体注入
yaml
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: db-cred1
2
3
4
5
2
3
4
5
五、注入方式三:挂载为文件(推荐)
yaml
spec:
containers:
- name: app
image: nginx:alpine
volumeMounts:
- name: cfg
mountPath: /etc/app
readOnly: true
- name: cred
mountPath: /etc/secret
readOnly: true
volumes:
- name: cfg
configMap:
name: app-config
- name: cred
secret:
secretName: db-cred
defaultMode: 04001
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
挂载后每个 key 变成一个文件,文件内容即 value。
建议
优先用文件挂载而非环境变量:改配置不必重建 Pod,且 kubectl exec 不会因 env 泄漏密钥。
六、热更新行为
修改 ConfigMap 后:
bash
kubectl edit configmap app-config1
- 文件挂载方式:kubelet 会在约 1 分钟内同步新内容到容器(有短暂延迟)。
- 环境变量方式:永远不会更新,必须重建 Pod。
注意
即使文件挂载更新了,多数应用不会自动重读配置。需要应用支持热加载,或手动 kubectl rollout restart deploy/<name> 触发滚动重启。
七、Secret 的安全边界
bash
kubectl get secret db-cred -o yaml # 看到的是 base64,不是加密
echo 'RXhhbXBsZVBhc3MxMjM=' | base64 -d # 一行命令还原明文1
2
2
危险
Secret 默认仅做了 base64 编码,不是加密。任何有 get secret 权限的人都能还原明文,etcd 里也是明文存储。生产必须开启 etcd 静态加密(EncryptionConfiguration),并配合 RBAC 严格限制读取权限。
验证
- [ ]
kubectl exec <pod> -- env | grep LOG_LEVEL能读到值 - [ ] 文件挂载方式下
kubectl exec <pod> -- ls /etc/app能看到配置文件 - [ ] 修改 ConfigMap 后,挂载的文件内容随之变化
- [ ]
kubectl describe secret db-cred不显示明文内容
常见坑
- Pod 启动报
CreateContainerConfigError:引用的 ConfigMap/Secret 名称或 key 不存在,用kubectl describe pod看事件。 - 改了配置不生效:用了环境变量注入,或应用不支持热加载。
- 以为 Secret 是加密的:见上文危险提示,必须开 etcd 加密。
- 挂载 ConfigMap 覆盖了整个目录:
mountPath指向已有内容的目录会把原内容全部遮蔽,要挂到子目录或用subPath。 - Secret 大小超限:etcd 对单个对象限制约 1MB,大文件不适合放 Secret。