--- tags: [kubernetes, configmap, secret, configuration-management] create time: 2026-05-18 00:30 --- # K8s 配置管理 — ConfigMap 与 Secret ## 概述 K8s 提供两种原生的配置注入机制:**ConfigMap**(普通配置)和 **Secret**(敏感信息)。理解它们的区别、注入方式和生效时机,是编写可维护 K8s manifest 的基础。更多安全方案(外部密钥管理)参见 [[../03-CICD与GitOps/04-安全与发布策略]]。 ## ConfigMap — 非敏感配置注入 ### 基本用法 ```yaml apiVersion: v1 kind: ConfigMap metadata: name: order-service-config namespace: production data: # ========== 环境变量风格 ========== DATABASE_HOST: "mysql.production.svc.cluster.local" DATABASE_PORT: "3306" LOG_LEVEL: "info" MAX_CONNECTIONS: "100" # ========== 文件风格 (挂载为 volume) ========== application.yaml: | server: port: 8080 spring: datasource: url: jdbc:mysql://${DATABASE_HOST}:${DATABASE_PORT}/orders pool-size: ${MAX_CONNECTIONS} logging: level: root: ${LOG_LEVEL} ``` ### 两种注入方式 ```yaml spec: containers: - name: order-service # 方式一:环境变量注入(简单直接) env: - name: DATABASE_HOST valueFrom: configMapKeyRef: name: order-service-config key: DATABASE_HOST # 方式二:volume 挂载配置文件(适合完整配置文件) volumeMounts: - name: config-volume mountPath: /etc/app/config/application.yaml subPath: application.yaml volumes: - name: config-volume configMap: name: order-service-config ``` > [!tip] 热更新 vs 重建 Pod > > - 通过 **环境变量** 注入的配置需要重建 Pod 才能生效 > - 通过 **volume 挂载** 的 ConfigMap 在配置变更后,Pod 内文件会在约 1 分钟内自动更新(前提是应用本身支持配置热加载,如 Spring Cloud Context 的 `@RefreshScope`) ## Secret — 敏感信息存储 ### 基本用法 ```yaml apiVersion: v1 kind: Secret metadata: name: order-service-secrets namespace: production type: Opaque data: # Base64 编码(注意:这不是加密!只是编码) DB_PASSWORD: cGFzc3dvcmQxMjM= API_KEY: bXktc2VjcmV0LWFwaS1rZXk= # 或者用 stringData(明文写入,K8s 自动编码) --- apiVersion: v1 kind: Secret metadata: name: order-service-secrets-v2 type: Opaque stringData: DB_PASSWORD: password123 # K8s 自动转为 base64 API_KEY: my-secret-api-key ``` **使用 Secret 的方式:** ```yaml # 方式一:作为环境变量注入 env: - name: DB_PASSWORD valueFrom: secretKeyRef: name: order-service-secrets key: DB_PASSWORD # 方式二:挂载为卷中的文件(更安全,避免暴露在 ps 输出中) volumeMounts: - name: secrets-volume readOnly: true mountPath: /etc/secrets defaultMode: 0400 volumes: - name: secrets-volume secret: secretName: order-service-secrets ``` > [!warning] Secret 的安全性边界 > > K8s Secret 默认以 **base64 编码** 存储在 etcd 中,任何人都可以解码。**Base64 ≠ 加密**。生产环境应启用以下至少一项: > > 1. **etcd 加密** — 开启 K8s EncryptionConfiguration,使 etcd 存储密文 > 2. **外部密钥管理** — Sealed Secrets、External Secrets Operator 对接 AWS Secrets Manager / HashiCorp Vault > 3. **RBAC 严格管控** — 限制谁可以读取 Secret 资源 ### ConfigMap vs Secret 对比 | 维度 | ConfigMap | Secret | |------|-----------|--------| | **用途** | 普通配置(URL、端口等) | 敏感信息(密码、Token、证书) | | **存储格式** | UTF-8 字符串 | Base64 编码 | | **挂载路径** | `/etc/config/...` | `/etc/secrets/...` | | **大小限制** | 1 MiB | 1 MiB | | **安全建议** | 正常 RBAC | 必须启用 etcd 加密或外置密钥管理 | ## 补充:动态配置重载实战 对于需要频繁变更的配置(如功能开关、灰度比例),可以通过 sidecar 模式实现自动重载: ```yaml spec: containers: - name: app image: myapp:latest volumeMounts: - name: config-volume mountPath: /etc/app/config readOnly: true - name: reload-sidecar # Watch 配置变更并发送 SIGUSR1 image: busybox:latest command: ["sh", "-c"] args: - | LAST_MD5="" while true; do CURR_MD5=$(md5sum /etc/config/application.yaml | awk '{print $1}') if [ "$CURR_MD5" != "$LAST_MD5" ]; then kill -USR1 1 # 通知主进程重新加载配置 LAST_MD5="$CURR_MD5" fi sleep 5 done volumeMounts: - name: config-volume mountPath: /etc/config readOnly: true volumes: - name: config-volume configMap: name: order-service-config - name: shared-config emptyDir: {} ``` > [!note] sidecar 模式的权衡 > > 优点:无需重启 Pod 即可热更新配置;缺点:增加了资源消耗和维护复杂度。Spring Boot 项目建议使用 Actuator `/refresh` 端点替代手动信号方案。 ## 关联笔记 - [[../01-核心概念与Deployment]] — ConfigMap 在 Deployment 中的标准引用方式 - [[../03-CICD与GitOps/04-安全与发布策略]] — 企业级 Secret 管理方案选型 - [[../hhs/MS/02-服务治理/07-配置管理]] — 微服务级别的配置中心方案(Nacos / Apollo / Consul)