跳到主要内容

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/dockerconfigjsondocker registry 凭证
kubernetes.io/tlsTLS 证书
kubernetes.io/service-account-tokenSA 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

7. 延伸阅读