ConfigMap与Secret管理
约 1372 字大约 5 分钟
kubernetesconfigmapsecret
2025-06-12
ConfigMap 和 Secret 是 Kubernetes 中管理配置和敏感数据的核心资源。正确使用它们可以实现配置与代码的分离,提升应用的可移植性和安全性。
ConfigMap 概述
创建 ConfigMap
从字面值创建
kubectl create configmap app-config \
--from-literal=DATABASE_HOST=mysql.default.svc \
--from-literal=DATABASE_PORT=3306 \
--from-literal=LOG_LEVEL=info从文件创建
# 从单个文件
kubectl create configmap nginx-config --from-file=nginx.conf
# 从目录(目录下所有文件都会成为 key)
kubectl create configmap app-configs --from-file=config/
# 指定 key 名
kubectl create configmap app-config --from-file=application.yaml=config/prod.yamlYAML 声明式定义
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: default
data:
# 简单键值对
DATABASE_HOST: "mysql.default.svc"
DATABASE_PORT: "3306"
LOG_LEVEL: "info"
# 多行配置文件
application.yaml: |
server:
port: 8080
shutdown: graceful
spring:
datasource:
url: jdbc:mysql://${DATABASE_HOST}:${DATABASE_PORT}/mydb
hikari:
maximum-pool-size: 20
logging:
level:
root: INFO
com.example: DEBUG
# Nginx 配置文件
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
}
}使用 ConfigMap
作为环境变量
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:1.0
env:
# 引用单个 key
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOST
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_PORT
optional: true # 如果 key 不存在不会报错
envFrom:
# 引用全部 key(批量注入)
- configMapRef:
name: app-config
prefix: APP_ # 可选前缀: APP_DATABASE_HOST挂载为文件卷
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.25
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d
readOnly: true
- name: app-config-volume
mountPath: /app/config/application.yaml
subPath: application.yaml # 只挂载单个文件,不覆盖目录
volumes:
- name: config-volume
configMap:
name: nginx-config
items: # 选择性挂载
- key: nginx.conf
path: default.conf # 文件名映射
mode: 0644 # 文件权限
- name: app-config-volume
configMap:
name: app-config热更新行为
以文件卷方式挂载的 ConfigMap 支持热更新(通常 kubelet 同步周期约 60 秒),但有例外:
- subPath 挂载不会自动更新
- 环境变量注入不会自动更新(需重启 Pod)
- immutable ConfigMap 不可更新
不可变 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: static-config
immutable: true # 设置后不可修改,只能删除重建
data:
VERSION: "2.1.0"
FEATURE_FLAGS: '{"newUI": true, "darkMode": false}'不可变 ConfigMap 的优势:
- 防止意外修改导致应用异常
- 减少 API Server 的 Watch 负载(大规模集群显著)
- 明确配置变更需要显式重建
Secret 类型
创建 Secret
# Opaque 类型
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password='S3cur3P@ss!'
# TLS 类型
kubectl create secret tls app-tls \
--cert=tls.crt --key=tls.key
# Docker 仓库凭据
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=pass \
--docker-email=user@example.comYAML 定义
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
# base64 编码(注意:base64 不是加密!)
username: YWRtaW4= # echo -n 'admin' | base64
password: UzNjdXIzUEBzcyE= # echo -n 'S3cur3P@ss!' | base64
---
# 使用 stringData 可直接写明文(创建时自动 base64 编码)
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
stringData:
api-key: "ak_live_xxxxxxxxxxxxx"
database-url: "postgresql://user:pass@db:5432/mydb"使用 Secret
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
template:
spec:
containers:
- name: app
image: myapp:1.0
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: app-secrets
defaultMode: 0400 # 限制文件权限
imagePullSecrets:
- name: regcred # 镜像拉取凭据Encryption at Rest(静态加密)
默认情况下 Secret 以 base64 存储在 etcd 中(不是加密)。需要配置静态加密:
# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {} # 回退:不加密(用于读取旧数据)# 在 kube-apiserver 中启用
# --encryption-provider-config=/etc/kubernetes/encryption-config.yaml
# 加密所有已有 Secret
kubectl get secrets --all-namespaces -o json | kubectl replace -f -External Secrets Operator
External Secrets Operator(ESO)将外部密钥管理系统(AWS Secrets Manager、HashiCorp Vault、Azure Key Vault 等)中的密钥同步为 Kubernetes Secret:
# 配置 Secret Store
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: aws-secrets-manager
spec:
provider:
aws:
service: SecretsManager
region: us-east-1
auth:
jwt:
serviceAccountRef:
name: external-secrets-sa
namespace: external-secrets
---
# 定义 External Secret
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: app-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: app-secrets # 创建的 K8s Secret 名称
creationPolicy: Owner
data:
- secretKey: database-url
remoteRef:
key: prod/app/database
property: url
- secretKey: api-key
remoteRef:
key: prod/app/api-keys
property: primarySealed Secrets
Sealed Secrets 允许将加密后的 Secret 安全地存储在 Git 仓库中(GitOps 友好):
# 安装 kubeseal CLI
# 加密 Secret
kubectl create secret generic my-secret \
--from-literal=password=supersecret \
--dry-run=client -o yaml | \
kubeseal --format yaml > sealed-secret.yaml# 生成的 SealedSecret(可安全提交到 Git)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: my-secret
namespace: default
spec:
encryptedData:
password: AgBy3i4OJSWK+PiTySYZZA9rO... # 加密后的数据
template:
metadata:
name: my-secret
namespace: default
type: Opaque最佳实践
- 永远不要将 Secret 明文提交到 Git,使用 Sealed Secrets 或 External Secrets
- 启用 etcd 静态加密,防止 etcd 数据泄露
- 使用 RBAC 限制 Secret 访问,最小权限原则
- 优先使用文件挂载而非环境变量,因为环境变量可能被子进程继承或出现在日志中
- 使用 immutable ConfigMap/Secret 防止意外修改
- 为 Secret 设置严格的文件权限(如
defaultMode: 0400) - 定期轮换密钥,配合 External Secrets 的
refreshInterval自动同步
贡献者
更新日志
2026/3/14 13:09
查看所有更新日志
9f6c2-feat: organize wiki content and refresh site setup于