ConfigMap-Secret与配置管理
1. ConfigMap
非敏感配置,键值对存储。
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: frontend
data:
API_URL: "https://api.example.com"
LOG_LEVEL: "info"
config.json: |
{
"feature": { "newUI": true }
}
nginx.conf: |
server {
listen 80;
...
}
1.1 用法 1:环境变量
spec:
containers:
- name: web
envFrom:
- configMapRef:
name: app-config
# 或单条
env:
- name: API_URL
valueFrom:
configMapKeyRef:
name: app-config
key: API_URL
1.2 用法 2:文件挂载
spec:
volumes:
- name: config
configMap:
name: app-config
containers:
- name: web
volumeMounts:
- name: config
mountPath: /etc/app
readOnly: true
容器内 /etc/app/config.json、/etc/app/nginx.conf 即配置内容。
1.3 热更新
ConfigMap 改了 → 挂载文件会自动更新(约 1 分钟内)。但环境变量不会更新(容器启动时注入)。应用要么重启,要么 watch 文件变化。
强制重启 Deployment 重新读:
kubectl rollout restart deployment/web
或加注解触发:
spec:
template:
metadata:
annotations:
configHash: "${CONFIG_SHA}" # CI 计算 ConfigMap hash 注入
2. Secret
敏感数据。注意:Secret 默认只是 base64 编码,不是加密。任何能读 Secret 的人都能看到原文。
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
password: c2VjcmV0MTIz # echo -n 'secret123' | base64
stringData: # 写明文,K8s 自动 base64
username: admin
2.1 类型
| type | 用途 |
|---|---|
| Opaque | 通用 |
| kubernetes.io/dockerconfigjson | docker registry 凭证 |
| kubernetes.io/tls | TLS 证书 |
| kubernetes.io/service-account-token | SA token |
2.2 镜像拉取凭证
kubectl create secret docker-registry regcred \
--docker-server=ghcr.io \
--docker-username=USER \
--docker-password=TOKEN
spec:
imagePullSecrets:
- name: regcred
containers: [...]
2.3 TLS 证书
kubectl create secret tls my-tls \
--cert=fullchain.pem \
--key=privkey.pem
Ingress 用 secretName: my-tls。
3. Secret 真正加密
3.1 etcd 加密
apiserver 启动时加 --encryption-provider-config:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources: [secrets]
providers:
- aescbc:
keys:
- name: key1
secret: <base64 32 字节>
- identity: {}
云托管集群(EKS、ACK)控制台一键开启。
3.2 sealed-secrets
加密后可以提交到 git:
# 安装控制器
helm install sealed-secrets sealed-secrets/sealed-secrets
# 加密
echo -n 'mypassword' | kubectl create secret generic db --dry-run=client \
--from-file=password=/dev/stdin -o yaml | \
kubeseal --controller-namespace=kube-system -o yaml > db-sealed.yaml
db-sealed.yaml 是密文,提交 git 安全。集群内 controller 解密成普通 Secret。
3.3 external-secrets-operator
把外部密钥管理(Vault、AWS Secrets Manager、阿里 KMS)同步到 K8s Secret:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-secret
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-store
kind: SecretStore
target:
name: db-secret
data:
- secretKey: password
remoteRef:
key: prod/db
property: password
生产推荐方案。
4. 配置组织模式
4.1 多环境
每个环境独立 ns + 各自的 ConfigMap/Secret:
frontend-dev ConfigMap: app-config (dev values)
frontend-prod ConfigMap: app-config (prod values)
Helm 模板化(见后续模块)。
4.2 公共 + 专用
envFrom:
- configMapRef:
name: common-config
- configMapRef:
name: app-specific-config
- secretRef:
name: db-secret
4.3 不可变 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-v2
immutable: true
data: ...
不可变后无法修改(要改建新版本 + 改 Deployment 引用)。性能更好(kubelet 不 watch),且防误改。
5. 故障排查
# 看 ConfigMap
kubectl get cm app-config -o yaml
kubectl describe cm app-config
# 看 Secret(看不到明文)
kubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d
# 看 Pod 内实际看到的
kubectl exec <pod> -- env
kubectl exec <pod> -- cat /etc/app/config.json
# Pod 起不来 - configmap not found
kubectl describe pod <pod>
# Events: configmap "x" not found → 检查 ns、名字
6. 常见反模式
- Secret 提交 git(明文):从 git history 找回,灾难
- base64 ≠ 加密:以为编码就安全
- 配置写死 Dockerfile:换环境要重新构建镜像
- ConfigMap 改了不重启 Deployment:环境变量没更新(文件挂载会更新)
- 多环境共享一个 ConfigMap:污染
- 大量小 ConfigMap:管理混乱,整合到大 ConfigMap
- 不用 immutable:误改导致全量重启
- 生产 ConfigMap 直接 kubectl edit:无审计、无回滚。走 GitOps