Repository Reading Site
ConfigMap 与 Secret — 配置与敏感信息管理
一个 nginx 镜像可能在 dev 连 `postgres-dev`,在 prod 连 `postgres-prod`。如果配置写死在镜像里,每个环境要构建不同的镜像。 K8s 的理念是:**镜像不变,配置外置**。同一个镜像 + 不同的 ConfigMap = 不同环境的行为。 --- `data` 下的每个 key-value 就是一条配置。 **特点
ConfigMap 与 Secret — 配置与敏感信息管理
为什么不把配置写死在镜像里?
一个 nginx 镜像可能在 dev 连 postgres-dev,在 prod 连 postgres-prod。如果配置写死在镜像里,每个环境要构建不同的镜像。
K8s 的理念是:镜像不变,配置外置。同一个镜像 + 不同的 ConfigMap = 不同环境的行为。
ConfigMap — 非敏感配置
创建方式
# 方式一:从字面值
kubectl -n dev create configmap app-config \
--from-literal=APP_ENV=development \
--from-literal=LOG_LEVEL=debug \
--from-literal=DB_HOST=postgres.dev.svc.cluster.local
# 方式二:从文件
kubectl -n dev create configmap nginx-conf --from-file=nginx.conf
# 方式三:从 YAML
kubectl apply -f configmap.yaml
我们创建的 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: dev
data:
APP_ENV: development
DB_HOST: postgres.dev.svc.cluster.local
LOG_LEVEL: debug
data 下的每个 key-value 就是一条配置。
两种使用方式
1. 作为环境变量注入
spec:
containers:
- name: app
env:
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: APP_ENV
# 或者一次性注入所有 key:
envFrom:
- configMapRef:
name: app-config
特点: Pod 启动时读取一次,之后不会自动更新。修改 ConfigMap 后必须重启 Pod。
2. 挂载为文件
spec:
containers:
- name: app
volumeMounts:
- name: config-vol
mountPath: /etc/config
volumes:
- name: config-vol
configMap:
name: app-config
挂载后目录结构:
/etc/config/
├── APP_ENV → 内容: development
├── DB_HOST → 内容: postgres.dev.svc.cluster.local
└── LOG_LEVEL → 内容: debug
特点: 修改 ConfigMap 后,文件内容会自动更新(约 30-60 秒延迟)。但应用进程不一定会重新读取文件——需要应用自己支持 watch 配置文件变化,或者用 sidecar 触发 reload。
面试重点
Q: ConfigMap 更新后 Pod 能感知吗?
| 使用方式 | 自动更新? | 原因 |
|---|---|---|
| 环境变量 | 不能 | 环境变量在进程启动时注入,之后不变 |
| Volume 挂载 | 能 | kubelet 定期同步挂载内容 |
| subPath 挂载 | 不能 | subPath 是静态绑定,不参与更新 |
Q: Immutable ConfigMap 是什么?
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
immutable: true # 设置后不可修改,也不可取消
data:
APP_ENV: production
好处:大规模集群中,kubelet 不需要持续 watch 不可变的 ConfigMap,减轻 API Server 压力。
Secret — 敏感信息(密码、证书、Token)
和 ConfigMap 的区别
| 特性 | ConfigMap | Secret |
|---|---|---|
| 用途 | 普通配置 | 密码、证书、Token |
| 存储 | etcd 明文 | etcd base64(默认不加密!) |
| 传输 | 不加密 | TLS 传输 |
| 内存 | 可用磁盘存储 | tmpfs(内存挂载,不写磁盘) |
| 大小限制 | 1MB | 1MB |
创建
kubectl -n dev create secret generic db-creds \
--from-literal=username=admin \
--from-literal=password=SuperSecret123
查看
# 看到的是 base64 编码(不是加密!)
$ kubectl -n dev get secret db-creds -o jsonpath="{.data}"
{"password":"U3VwZXJTZWNyZXQxMjM=","username":"YWRtaW4="}
# 解码
$ echo "U3VwZXJTZWNyZXQxMjM=" | base64 -d
SuperSecret123
关键安全认知
base64 不是加密,只是编码。 任何人拿到 Secret 的 YAML 都能解码出原文。
Secret 的安全性依赖:
- RBAC — 限制谁能
getSecret - etcd 加密 — 配置 EncryptionConfiguration 对 etcd 中的 Secret 做 AES 加密(Phase 3 练习)
- 传输加密 — API Server 和 kubelet 之间走 TLS
- tmpfs 挂载 — Secret 挂载到 Pod 时用内存文件系统,不落盘
使用方式(同 ConfigMap)
# 环境变量
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-creds
key: password
# Volume 挂载
volumes:
- name: db-creds-vol
secret:
secretName: db-creds
Secret 的类型
| 类型 | 用途 |
|---|---|
Opaque |
默认,任意 key-value |
kubernetes.io/tls |
TLS 证书(tls.crt + tls.key) |
kubernetes.io/dockerconfigjson |
Docker Registry 认证 |
kubernetes.io/service-account-token |
ServiceAccount Token |
面试深度题
Q: 生产环境如何安全管理 Secret?
- etcd 加密 — EncryptionConfiguration + AES-CBC
- External Secrets Operator — 从 AWS Secrets Manager / Vault 同步
- Sealed Secrets — 加密后可安全存入 Git(GitOps 场景)
- RBAC 最小权限 — 只有需要的 ServiceAccount 能读 Secret
- 审计日志 — 记录谁访问了 Secret
实验验证总结
| 操作 | 结果 |
|---|---|
| 创建 ConfigMap | app-config 含 APP_ENV, LOG_LEVEL, DB_HOST |
| 创建 Secret | db-creds 含 username, password(base64 编码) |
| 解码 Secret | echo <base64> | base64 -d 可直接还原明文 |