189 lines
5.3 KiB
Markdown
189 lines
5.3 KiB
Markdown
---
|
||
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)
|