第7章:配置、Secret和ConfigMap(Configuration, Secrets, and ConfigMaps)
一、导读
1.1 本章学习目标
将配置与镜像解耦是容器化最佳实践。本章讲解 Kubernetes 的两种核心配置资源:ConfigMap(非敏感配置)和 Secret(敏感数据)。你将学习配置的三种注入方式、热更新机制、以及 Secret 的安全注意事项。
本章的核心学习目标包括:
- 掌握 ConfigMap 的创建和使用:存储非敏感配置数据。
- 掌握 Secret 的创建和使用:存储密码、Token、证书等敏感数据。
- 理解三种配置注入方式:环境变量、命令行参数、Volume 挂载。
- 理解配置热更新:哪些方式支持自动更新,哪些需要重启。
- 了解 Secret 的安全增强:加密存储、RBAC 控制、外部 Secret 管理。
- 掌握最佳实践:配置管理的设计原则。
1.2 为什么本章如此重要
将配置硬编码在镜像中是反模式——同一个镜像需要在不同环境(开发、测试、生产)中使用不同的配置。Kubernetes 的 ConfigMap 和 Secret 将配置从镜像中解耦,使得同一个镜像可以在不同环境中运行。
Secret 的安全管理更是生产环境的重中之重。数据库密码、API Key、TLS 证书等敏感数据需要加密存储、严格访问控制。理解 Secret 的工作原理和安全限制,是保障系统安全的基础。
1.3 核心问题引导
ConfigMap 和 Secret 有什么区别?为什么需要分开?
环境变量注入和 Volume 挂载注入各有什么优缺点?
ConfigMap 更新后,使用环境变量注入的 Pod 能自动获取新值吗?
Secret 的 Base64 编码是加密吗?如何增强 Secret 的安全性?
如何在 Git 中安全地存储 Secret?
二、核心概念详解
2.1 ConfigMap
ConfigMap 存储非敏感的配置数据,以键值对形式保存。
2.1.1 创建 ConfigMap
# 从字面量创建
kubectl create configmap app-config \
--from-literal=DATABASE_URL=postgres://db:5432/myapp \
--from-literal=LOG_LEVEL=info
# 从文件创建
kubectl create configmap nginx-config \
--from-file=nginx.conf=/path/to/nginx.conf
# 从 env 文件创建
kubectl create configmap app-env --from-env-file=config.env# YAML 定义
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_URL: "postgres://db:5432/myapp"
LOG_LEVEL: "info"
CACHE_TTL: "300"
config.yaml: |
server:
port: 8080
timeout: 30s
cache:
ttl: 300s
max_size: 10002.1.2 在 Pod 中使用 ConfigMap
方式一:环境变量
spec:
containers:
- name: app
image: myapp:1.0
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_URL
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL# 注入所有键值对
spec:
containers:
- name: app
envFrom:
- configMapRef:
name: app-config方式二:Volume 挂载
spec:
containers:
- name: app
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config
# 每个 key 变成一个文件,value 变成文件内容
# /etc/config/DATABASE_URL 内容为 "postgres://db:5432/myapp"
# /etc/config/config.yaml 内容为 YAML 配置# 挂载特定 key 到特定路径
spec:
containers:
- name: app
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: config-volume
configMap:
name: nginx-config
items:
- key: nginx.conf
path: nginx.conf方式三:命令行参数
spec:
containers:
- name: app
image: myapp:1.0
command: ["python", "app.py"]
args:
- "--log-level"
- "$(LOG_LEVEL)"
- "--cache-ttl"
- "$(CACHE_TTL)"
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL2.2 Secret
Secret 存储敏感数据,与 ConfigMap 类似但有一些安全增强。
2.2.1 创建 Secret
# 从字面量创建
kubectl create secret generic db-secret \
--from-literal=DB_PASSWORD=password123 \
--from-literal=DB_USER=admin
# 创建 TLS Secret
kubectl create secret tls tls-secret \
--cert=tls.crt \
--key=tls.key
# 创建 Docker Registry Secret
kubectl create secret docker-registry registry-secret \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=passapiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
DB_PASSWORD: cGFzc3dvcmQxMjM= # base64 编码
DB_USER: YWRtaW4= # base64 编码
stringData:
API_KEY: "sk-abc123" # 明文,K8s 自动 base64 编码注意:Base64 不是加密!任何人都可以解码。Secret 的安全性依赖于:
- etcd 的加密(需要配置 encryption at rest)
- RBAC 控制访问权限
- 网络隔离
2.2.2 在 Pod 中使用 Secret
spec:
containers:
- name: app
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: DB_PASSWORD
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-secret
defaultMode: 0400 # 只读权限2.2.3 Secret 类型
- Opaque:通用类型(默认)
- kubernetes.io/tls:TLS 证书
- kubernetes.io/dockerconfigjson:Docker Registry 认证
- kubernetes.io/service-account-token:ServiceAccount Token
- kubernetes.io/basic-auth:Basic 认证
2.3 配置热更新
2.3.1 更新行为对比
| 注入方式 | ConfigMap 更新后 | Secret 更新后 |
|---|---|---|
| 环境变量 | 不更新(需重启 Pod) | 不更新(需重启 Pod) |
| Volume 挂载 | 自动更新(有延迟) | 自动更新(有延迟) |
| 命令行参数 | 不更新(需重启 Pod) | 不更新(需重启 Pod) |
Volume 挂载方式的更新延迟:kubelet 定期同步(默认1分钟),更新不是实时的。
2.3.2 触发滚动更新
# 更新 ConfigMap 后手动触发滚动更新
kubectl rollout restart deployment/my-app
# 使用 annotation 自动触发
kubectl patch deployment my-app -p \
'{"spec":{"template":{"metadata":{"annotations":{"configmap-version":"'$(date +%s)'"}}}}}'2.4 Secret 安全增强
2.4.1 etcd 加密
# /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
containers:
- command:
- --encryption-provider-config=/etc/kubernetes/encryption-config.yaml# encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-key>
- identity: {} # 回退到不加密2.4.2 RBAC 控制
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
namespace: default
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: secret-reader-binding
subjects:
- kind: ServiceAccount
name: my-app
roleRef:
kind: Role
name: secret-reader
apiGroup: rbac.authorization.k8s.io2.4.3 外部 Secret 管理
- Sealed Secrets:加密 Secret 后可以安全存储到 Git
- Vault:HashiCorp Vault 集成
- External Secrets Operator:从外部 Secret 管理系统同步到 K8s
# Sealed Secret 示例
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: db-secret
spec:
encryptedData:
DB_PASSWORD: AgBy3...(加密后的数据)
DB_USER: AgCx7...三、实战案例
3.1 完整的多环境配置
# configmap-dev.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_URL: "postgres://dev-db:5432/myapp_dev"
LOG_LEVEL: "debug"
CACHE_TTL: "60"
---
# configmap-prod.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_URL: "postgres://prod-db:5432/myapp_prod"
LOG_LEVEL: "warn"
CACHE_TTL: "600"# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: myapp:1.0
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_URL
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: DB_PASSWORD# 开发环境
kubectl apply -f configmap-dev.yaml -n development
kubectl apply -f deployment.yaml -n development
# 生产环境
kubectl apply -f configmap-prod.yaml -n production
kubectl apply -f deployment.yaml -n production四、本章小结
ConfigMap 存储非敏感配置,Secret 存储敏感数据。
三种注入方式:环境变量(简单但不热更新)、Volume 挂载(支持热更新)、命令行参数。
Secret 的 Base64 不是加密,需要配合 etcd 加密和 RBAC 控制。
外部 Secret 管理工具(Sealed Secrets、Vault)可以安全地将 Secret 存储到 Git。
配置与镜像解耦是容器化最佳实践,同一个镜像可以在不同环境运行。
五、思考与练习
思考题
为什么环境变量方式不支持热更新?Volume 挂载方式为什么支持?
如果 ConfigMap 不存在,Pod 能启动吗?如果 Secret 不存在呢?
如何实现 ConfigMap 更新后自动重启 Pod?有哪些方案?
Sealed Secrets 的加密原理是什么?为什么可以安全存储到 Git?
在多团队共享集群时,如何防止团队 A 读取团队 B 的 Secret?
练习题
创建 ConfigMap 和 Secret,分别通过环境变量和 Volume 挂载注入到 Pod。
更新 ConfigMap,观察 Volume 挂载方式的自动更新行为。
使用 Sealed Secrets 加密 Secret 并存储到 Git。
配置 RBAC 限制某个 ServiceAccount 只能访问特定的 Secret。