ConfigMap 与 Secret
ConfigMap 与 Secret
为什么需要配置管理
应用程序通常需要配置信息:
- 数据库连接地址
- API 密钥
- 功能开关
- 环境相关配置
问题:如何管理这些配置?
❌ 不好的做法:
- 硬编码在代码中
- 打包在镜像中
✅ 好的做法:
- 配置与代码分离
- 使用 ConfigMap 和 Secret
ConfigMap - 配置数据
ConfigMap 用于存储非敏感的配置数据。
创建 ConfigMap
方法一:命令行(键值对)
kubectl create configmap app-config \
--from-literal=database.host=mysql.example.com \
--from-literal=database.port=3306 \
--from-literal=log.level=info
方法二:从文件创建
# 创建配置文件
cat > app.properties <<EOF
database.host=mysql.example.com
database.port=3306
log.level=info
max.connections=100
EOF
# 创建 ConfigMap
kubectl create configmap app-config --from-file=app.properties
方法三:从目录创建
# 创建多个配置文件
mkdir config
echo "host=mysql.example.com" > config/database.conf
echo "level=info" > config/logging.conf
# 从目录创建
kubectl create configmap app-config --from-file=config/
方法四:YAML 定义
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database.host: "mysql.example.com"
database.port: "3306"
log.level: "info"
app.properties: |
server.port=8080
server.name=myapp
feature.flags=enable-cache,enable-metrics
使用 ConfigMap
1. 环境变量方式
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
containers:
- name: app
image: myapp:v1
env:
# 单个键值
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database.host
# 导入所有键值
envFrom:
- configMapRef:
name: app-config
2. 挂载为文件
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
containers:
- name: app
image: myapp:v1
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config
容器内文件结构:
/etc/config/
├── database.host (内容: mysql.example.com)
├── database.port (内容: 3306)
└── log.level (内容: info)
3. 挂载特定键
volumes:
- name: config-volume
configMap:
name: app-config
items:
- key: app.properties
path: application.properties
结果:
/etc/config/application.properties
Secret - 敏感数据
Secret 用于存储敏感数据(密码、令牌、密钥等)。
Secret 类型
- Opaque:通用类型(默认)
- kubernetes.io/dockerconfigjson:Docker 镜像仓库凭证
- kubernetes.io/tls:TLS 证书
- kubernetes.io/service-account-token:ServiceAccount 令牌
创建 Secret
方法一:命令行
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password=P@ssw0rd123
方法二:从文件
echo -n 'admin' > username.txt
echo -n 'P@ssw0rd123' > password.txt
kubectl create secret generic db-secret \
--from-file=username=username.txt \
--from-file=password=password.txt
方法三:YAML 定义
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4= # base64 编码的 "admin"
password: UEBzc3cwcmQxMjM= # base64 编码的 "P@ssw0rd123"
Base64 编码/解码:
# 编码
echo -n 'admin' | base64
# 输出: YWRtaW4=
# 解码
echo 'YWRtaW4=' | base64 -d
# 输出: admin
方法四:stringData(明文)
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
stringData:
username: admin
password: P@ssw0rd123
使用 Secret
1. 环境变量方式
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
containers:
- name: app
image: myapp:v1
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
2. 挂载为文件
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
containers:
- name: app
image: myapp:v1
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-secret
容器内文件:
/etc/secrets/
├── username (内容: admin)
└── password (内容: P@ssw0rd123)
Docker 镜像拉取凭证
创建镜像拉取 Secret
kubectl create secret docker-registry regcred \
--docker-server=<registry-url> \
--docker-username=<username> \
--docker-password=<password> \
--docker-email=<email>
示例:
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=myuser \
--docker-password=mypassword \
--docker-email=user@example.com
使用镜像拉取 Secret
apiVersion: v1
kind: Pod
metadata:
name: private-app
spec:
containers:
- name: app
image: registry.example.com/myapp:v1
imagePullSecrets:
- name: regcred
TLS 证书 Secret
kubectl create secret tls tls-secret \
--cert=path/to/tls.crt \
--key=path/to/tls.key
在 Ingress 中使用:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webapp-ingress
spec:
tls:
- hosts:
- example.com
secretName: tls-secret
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webapp
port:
number: 80
实战示例
完整的应用配置
# ConfigMap - 应用配置
apiVersion: v1
kind: ConfigMap
metadata:
name: webapp-config
data:
app.env: "production"
log.level: "info"
server.port: "8080"
config.yaml: |
server:
port: 8080
host: 0.0.0.0
database:
max_connections: 100
timeout: 30s
cache:
enabled: true
ttl: 3600
---
# Secret - 敏感配置
apiVersion: v1
kind: Secret
metadata:
name: webapp-secret
type: Opaque
stringData:
db.username: "admin"
db.password: "SecureP@ssw0rd"
api.key: "sk-1234567890abcdef"
---
# Deployment - 使用配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: myapp:v1
ports:
- containerPort: 8080
env:
# 从 ConfigMap 加载
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: webapp-config
key: app.env
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: webapp-config
key: log.level
# 从 Secret 加载
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: webapp-secret
key: db.username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: webapp-secret
key: db.password
- name: API_KEY
valueFrom:
secretKeyRef:
name: webapp-secret
key: api.key
volumeMounts:
# 挂载配置文件
- name: config
mountPath: /etc/config
# 挂载密钥文件
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: config
configMap:
name: webapp-config
items:
- key: config.yaml
path: config.yaml
- name: secrets
secret:
secretName: webapp-secret
应用和测试
# 应用配置
kubectl apply -f webapp-full.yaml
# 查看 ConfigMap
kubectl get configmap webapp-config
kubectl describe configmap webapp-config
# 查看 Secret
kubectl get secret webapp-secret
kubectl describe secret webapp-secret
# 查看 Pod 环境变量
kubectl exec -it <pod-name> -- env | grep -E 'APP_ENV|DB_'
# 查看挂载的配置文件
kubectl exec -it <pod-name> -- cat /etc/config/config.yaml
# 查看挂载的密钥文件
kubectl exec -it <pod-name> -- cat /etc/secrets/db.username
更新配置
更新 ConfigMap
# 方法一:编辑
kubectl edit configmap app-config
# 方法二:重新应用
kubectl apply -f configmap.yaml
# 方法三:patch
kubectl patch configmap app-config -p '{"data":{"log.level":"debug"}}'
配置更新生效
环境变量方式:需要重启 Pod
kubectl rollout restart deployment webapp
挂载文件方式:自动更新(延迟 1-2 分钟)
应用需要实现配置热加载才能自动生效。
常用命令
# ConfigMap
kubectl create configmap <name> --from-literal=key=value
kubectl create configmap <name> --from-file=<file>
kubectl get configmap
kubectl describe configmap <name>
kubectl edit configmap <name>
kubectl delete configmap <name>
# Secret
kubectl create secret generic <name> --from-literal=key=value
kubectl create secret generic <name> --from-file=<file>
kubectl get secret
kubectl describe secret <name>
kubectl get secret <name> -o yaml
kubectl delete secret <name>
# 查看 Secret 内容
kubectl get secret <name> -o jsonpath='{.data.password}' | base64 -d
最佳实践
1. 配置与敏感信息分离
# ConfigMap - 非敏感配置
data:
database.host: "mysql.example.com"
database.port: "3306"
# Secret - 敏感配置
data:
database.username: "..."
database.password: "..."
2. 使用有意义的名称
metadata:
name: webapp-config # 好
# name: config1 # 不好
3. 配置版本化管理
metadata:
name: webapp-config-v2
labels:
version: v2
4. 不要在 Secret 中存储大文件
Secret 有大小限制(1MB),不适合存储大文件。
5. 限制 Secret 访问权限
使用 RBAC 控制 Secret 访问:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["db-secret"]
verbs: ["get"]
6. 考虑使用外部密钥管理
生产环境可以使用:
- HashiCorp Vault
- AWS Secrets Manager
- Azure Key Vault
- Google Secret Manager
小结
ConfigMap 和 Secret 是 Kubernetes 中管理配置的核心资源:
ConfigMap:
- 存储非敏感配置
- 支持键值对、文件、多行文本
- 可以环境变量或文件方式使用
Secret:
- 存储敏感数据
- Base64 编码(非加密)
- 支持多种类型
- 应限制访问权限
关键原则:
- 配置与代码分离
- 敏感信息使用 Secret
- 版本化管理
- 使用 RBAC 控制访问
下一章我们将学习 Volume 存储卷,实现数据持久化。