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)
|