⚙️ 配置与密钥管理
📋 ConfigMap 基础
ConfigMap 用于将配置数据以键值对形式存储,供 Pod 使用。适合存储非敏感配置,如配置文件、环境变量等。
创建 ConfigMap
# 从字面量创建
kubectl create configmap app-config \
--from-literal=database.url=localhost:3306 \
--from-literal=database.name=mydb
# 从文件创建
kubectl create configmap app-config \
--from-file=config.yaml \
--from-file=nginx.conf
# 从目录创建(目录中所有文件成为键值对)
kubectl create configmap app-config \
--from-file=./config-dir/
# 查看 ConfigMap
kubectl get configmap app-config -o yaml
ConfigMap YAML 定义
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: default
data:
# 简单键值对
database.url: 'localhost:3306'
database.name: 'mydb'
log.level: 'info'
# 配置文件(多行文本)
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
# 属性文件
app.properties: |
app.name=MyApplication
app.version=1.0.0
app.debug=true
🔑 Secret 基础
Secret 用于存储敏感信息,如密码、Token、密钥等。与 ConfigMap 不同,Secret 数据以 base64 编码存储(并非加密)。
创建 Secret
# 从字面量创建
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password='S3cur3P@ss!'
# 从文件创建
kubectl create secret generic tls-secret \
--from-file=tls.crt=server.crt \
--from-file=tls.key=server.key
# 创建 Docker registry Secret(拉取私有镜像用)
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=admin \
--docker-password=password \
--docker-email=admin@example.com
Secret YAML 定义
apiVersion: v1
kind: Secret
metadata:
name: db-secret
namespace: default
type: Opaque
data:
# base64 编码的值
username: YWRtaW4= # admin
password: UDNhcjNQQHNzIQ== # S3cur3P@ss!
stringData: # 明文,kubectl 会自动编码
host: 'db.example.com'
port: '3306'
:::warning Secret 安全注意事项
- Base64 不是加密:任何人都可以解码
- etcd 默认不加密:需要启用 Encryption at Rest
- RBAC 控制访问:限制 Secret 的读取权限
- 使用外部密钥管理:生产环境推荐使用 Vault、AWS Secrets Manager 等 :::
🔄 使用配置:环境变量 vs 卷挂载
方式一:环境变量
apiVersion: v1
kind: Pod
metadata:
name: env-var-pod
spec:
containers:
- name: app
image: myapp:1.0
env:
# 单个键值对
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: app-config
key: database.url
# 从 Secret 读取
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
# 批量导入 ConfigMap 所有键值
- name: CONFIG_MAP_AS_ENV
valueFrom:
configMapRef:
name: app-config
# 批量导入 Secret 所有键值
- name: SECRET_AS_ENV
valueFrom:
secretRef:
name: db-secret
优点:
- 简单直接
- 适合简单配置
缺点:
- 修改后需要重启 Pod
- 无法通过
kubectl exec查看 - 可能泄露到日志、环境变量
方式二:卷挂载
apiVersion: v1
kind: Pod
metadata:
name: volume-mount-pod
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
# ConfigMap 作为卷
- name: config-volume
configMap:
name: app-config
items:
- key: nginx.conf
path: nginx.conf # 挂载为文件
# Secret 作为卷
- name: secret-volume
secret:
secretName: db-secret
defaultMode: 0400 # 文件权限
items:
- key: password
path: db-password
优点:
- 支持热更新(ConfigMap 修改后自动同步)
- 可以挂载为文件
- 权限控制更灵活
缺点:
- 需要应用支持读取文件
- Secret 卷内容仍明文存储(需启用 Encryption at Rest)
:::tip 选择建议
- 环境变量:适合简单、不常变的配置
- 卷挂载:适合配置文件、需要热更新的场景
- Secret:生产环境推荐使用外部密钥管理(Vault 等):::
🔐 外部密钥管理算子
生产环境不应将密钥存储在 Kubernetes Secret 中,而应使用外部密钥管理系统。
HashiCorp Vault
Vault 是企业级密钥管理工具,提供密钥轮换、审计日志、动态密钥等功能。
安装 Vault
# 使用 Helm 安装 Vault
helm repo add hashicorp https://helm.releases.hashicorp.com
helm install vault hashicorp/vault --set "server.dev.enabled=true"
# 初始化 Vault
kubectl exec -it vault-0 -- vault operator init
kubectl exec -it vault-0 -- vault operator unseal <key>
# 配置 Kubernetes 认证
kubectl exec -it vault-0 -- vault auth enable kubernetes
Vault Agent Injector
apiVersion: v1
kind: Pod
metadata:
name: vault-injector-demo
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/agent-inject-secret-database: 'secret/data/database'
vault.hashicorp.com/role: 'myapp'
vault.hashicorp.com/agent-inject-template-database: |
{{- with secret "secret/data/database" -}}
export DB_PASSWORD="{{ .Data.data.password }}"
{{- end -}}
spec:
containers:
- name: app
image: myapp:1.0
AWS Secrets Manager
使用 External Secrets Operator (ESO) 从 AWS Secrets Manager 同步密钥。
安装 External Secrets Operator
# 使用 Helm 安装 ESO
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets \
--namespace external-secrets-system --create-namespace
ESO 配置示例
# SecretStore 定义(连接到 AWS Secrets Manager)
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: aws-secretsmanager
spec:
provider:
aws:
service: SecretsManager
region: us-east-1
auth:
secretRef:
accessKeyID:
name: aws-credentials
key: access-key-id
secretAccessKey:
name: aws-credentials
key: secret-access-key
---
# ExternalSecret 定义(从 AWS 同步密钥)
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: 300s # 每 5 分钟同步一次
secretStoreRef:
name: aws-secretsmanager
kind: SecretStore
target:
name: db-secret # 生成的 Kubernetes Secret 名称
creationPolicy: Owner
data:
- secretKey: username
remoteRef:
key: prod/database
property: username
- secretKey: password
remoteRef:
key: prod/database
property: password
GCP Secret Manager
# SecretStore for GCP
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: gcp-secretmanager
spec:
provider:
gcpsm:
projectID: my-project-123
auth:
workloadIdentity:
clusterLocation: us-central1
clusterName: my-cluster
projectID: my-project-123
:::tip 外部密钥管理对比 | 工具 | 特点 | 适用场景 | |------|------|---------| | HashiCorp Vault | 功能最全,支持动态密钥 | 企业级,需要完整密钥生命周期管理 | | AWS Secrets Manager | 云原生,与 AWS 深度集成 | AWS 环境 | | GCP Secret Manager | 云原生,与 GCP 深度集成 | GCP 环境 | | Azure Key Vault | 云原生,与 Azure 深度集成 | Azure 环境 | | External Secrets Operator | 统一接口,支持多后端 | 混合云、多云平台 | :::
🌍 多环境配置管理
在生产实践中,通常需要管理多个环境(dev、staging、prod)的配置。
方案 1:命名空间隔离
# dev 命名空间
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: dev
data:
env: 'development'
database.url: 'dev-db.example.com:3306'
---
# prod 命名空间
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
env: 'production'
database.url: 'prod-db.example.com:3306'
方案 2:Kustomize 覆盖
├── base/
│ ├── configmap.yaml
│ ├── deployment.yaml
│ └── kustomization.yaml
└── overlays/
├── dev/
│ ├── configmap-patch.yaml
│ └── kustomization.yaml
└── prod/
├── configmap-patch.yaml
└── kustomization.yaml
base/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- configmap.yaml
- deployment.yaml
overlays/prod/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
patchesStrategicMerge:
- configmap-patch.yaml
overlays/prod/configmap-patch.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
env: 'production'
database.url: 'prod-db.example.com:3306'
方案 3:Helm Values 文件
├── charts/
│ └── myapp/
│ ├── Chart.yaml
│ ├── values.yaml
│ ├── values-dev.yaml
│ ├── values-staging.yaml
│ ├── values-prod.yaml
│ └── templates/
部署命令:
# 开发环境
helm install myapp ./charts/myapp -f values-dev.yaml
# 生产环境
helm install myapp ./charts/myapp -f values-prod.yaml
:::tip 多环境管理建议
- 开发/测试环境:使用 Kustomize 或 Helm
- 生产环境:使用 Helm + GitOps(ArgoCD/Flux)
- 密钥管理:使用 External Secrets Operator + 环境隔离
- 配置版本控制:将配置存储在 Git,使用 PR 审核 :::
🔒 Encryption at Rest
Kubernetes 支持对 etcd 中的 Secret 进行加密存储。
配置 Encryption Provider
# encryption-provider-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
- configmaps
providers:
- aescbc:
keys:
- name: key1
secret: c2VjcmV0LXBhc3NwaHJhc2UtZm9yLWVuY3J5cHRpb24K
- identity: {} # 允许明文读取(用于迁移)
启用加密:
# 修改 kube-apiserver 配置
vim /etc/kubernetes/manifests/kube-apiserver.yaml
# 添加参数
--encryption-provider-config=/etc/kubernetes/encryption-provider-config.yaml
# 重启 API Server
systemctl restart kubelet
验证加密:
# 查看 etcd 中的 Secret(应该是加密的)
ETCDCTL_API=3 etcdctl get /registry/secrets/default/db-secret
🛠️ 实用命令
# 查看 ConfigMap
kubectl get configmap
kubectl describe configmap <name>
kubectl get configmap <name> -o yaml
# 编辑 ConfigMap(会触发滚动更新)
kubectl edit configmap <name>
# 删除 ConfigMap
kubectl delete configmap <name>
# 查看 Secret(不显示值)
kubectl get secret
kubectl describe secret <name>
# 查看 Secret 值(需要解码)
kubectl get secret <name> -o jsonpath='{.data.password}' | base64 --decode
# 比较 ConfigMap 差异
kubectl diff -f configmap.yaml
# 批量导出 ConfigMap
kubectl get configmap -o yaml > all-configmaps.yaml
📚 最佳实践
- 分离配置与代码:配置文件不应打包在镜像中
- 使用版本控制:将 ConfigMap/Secret 定义存储在 Git
- 环境隔离:不同环境使用不同命名空间或配置
- 最小权限原则:使用 RBAC 限制 Secret 访问
- 启用加密存储:生产环境必须启用 Encryption at Rest
- 定期轮换密钥:使用 Vault 等工具自动化密钥轮换
- 审计密钥访问:记录谁访问了哪些密钥
- 使用外部密钥管理:生产环境避免使用 Kubernetes 原生 Secret