Kubernetes ConfigMap 与直接使用环境变量的区别

Understanding the Differences Between Kubernetes ConfigMap and Direct Environment Variables

2025-11-08 14:58:15

在 Kubernetes 中,配置管理是一个重要的主题。我们可以通过 ConfigMap 和直接使用环境变量(env)两种方式来管理应用配置,但它们有着本质的区别和不同的使用场景。本文将深入分析这两种方式的区别,帮助开发者根据实际需求选择最合适的配置管理方式。

一、概述

1.1 两种配置方式

在 Kubernetes 中,为容器提供配置主要有两种方式:

  1. ConfigMap:Kubernetes 资源对象,用于存储非敏感配置数据
  2. 直接使用 env:在 Pod 或 Deployment 中直接定义环境变量

1.2 为什么需要了解区别?

  • 📋 配置管理:理解何时使用哪种方式
  • 📋 可维护性:选择更易维护的配置方式
  • 📋 可复用性:提高配置的复用性
  • 📋 安全性:正确区分敏感和非敏感配置

二、ConfigMap 详解

2.1 什么是 ConfigMap?

ConfigMap 是 Kubernetes 中的一个 API 对象,用于存储非敏感的配置数据,以键值对的形式存储。ConfigMap 允许将配置与容器镜像分离,使应用更加可移植和可配置。

2.2 ConfigMap 的特点

  • 独立资源:作为独立的 Kubernetes 资源存在
  • 可复用:可以被多个 Pod 引用
  • 动态更新:可以更新配置而不需要重建 Pod(取决于使用方式)
  • 版本管理:可以通过 GitOps 进行版本控制
  • 分离关注点:配置与代码分离

2.3 ConfigMap 的使用方式

方式 1:作为环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_host: "db.example.com"
database_port: "5432"
app_name: "my-app"
log_level: "info"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: app-config

方式 2:作为单个环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database_host

方式 3:作为文件挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config

2.4 ConfigMap 的创建方式

方式 1:使用 YAML 文件

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_host: "db.example.com"
database_port: "5432"
app.properties: |
server.port=8080
server.host=0.0.0.0
logging.level.root=INFO

方式 2:使用命令行

1
2
3
4
5
6
7
8
9
10
11
12
# 从字面量创建
kubectl create configmap app-config \
--from-literal=database_host=db.example.com \
--from-literal=database_port=5432

# 从文件创建
kubectl create configmap app-config \
--from-file=app.properties

# 从目录创建
kubectl create configmap app-config \
--from-file=config/

三、直接使用环境变量(env)

3.1 什么是直接使用 env?

直接在 Pod 或 Deployment 的 spec.containers[].env 中定义环境变量,这些变量是硬编码在 YAML 文件中的。

3.2 直接使用 env 的特点

  • 简单直接:配置简单,易于理解
  • 快速部署:不需要创建额外的资源
  • 不可复用:配置绑定在特定的 Pod/Deployment 中
  • 难以维护:配置分散在多个地方
  • 版本控制:配置与代码耦合

3.3 直接使用 env 的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
env:
- name: DATABASE_HOST
value: "db.example.com"
- name: DATABASE_PORT
value: "5432"
- name: APP_NAME
value: "my-app"
- name: LOG_LEVEL
value: "info"

四、核心区别对比

4.1 功能特性对比

特性 ConfigMap 直接使用 env
资源类型 独立的 Kubernetes 资源 Pod/Deployment 的一部分
可复用性 ✅ 可以被多个 Pod 引用 ❌ 绑定在特定 Pod 中
动态更新 ✅ 可以更新(取决于使用方式) ❌ 需要重建 Pod
版本管理 ✅ 独立版本控制 ⚠️ 与代码一起版本控制
配置分离 ✅ 配置与代码分离 ❌ 配置与代码耦合
文件支持 ✅ 支持文件挂载 ❌ 仅支持键值对
大小限制 1 MB 无明确限制(但受 Pod 限制)

4.2 使用场景对比

ConfigMap 适用场景

  1. 多环境配置:不同环境使用不同的 ConfigMap
  2. 配置共享:多个 Pod 需要相同的配置
  3. 配置文件:需要挂载配置文件到容器
  4. 配置更新:需要频繁更新配置而不重建 Pod
  5. GitOps:通过 Git 管理配置

直接使用 env 适用场景

  1. 简单应用:配置项少且不经常变化
  2. 一次性配置:特定 Pod 的独特配置
  3. 快速原型:开发和测试阶段
  4. 临时配置:不需要长期维护的配置

4.3 实际使用示例对比

场景:数据库连接配置

使用 ConfigMap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: database-config
data:
host: "db.example.com"
port: "5432"
database: "myapp"
pool_size: "10"
---
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: database-config

使用直接 env:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: my-app:latest
env:
- name: DB_HOST
value: "db.example.com"
- name: DB_PORT
value: "5432"
- name: DB_DATABASE
value: "myapp"
- name: DB_POOL_SIZE
value: "10"

4.4 多环境配置对比

使用 ConfigMap(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# configmap-dev.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: dev
data:
environment: "development"
api_url: "https://api-dev.example.com"
---
# configmap-prod.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: prod
data:
environment: "production"
api_url: "https://api.example.com"
---
# deployment.yaml(通用)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: app-config

优点:

  • ✅ 部署文件通用,只需切换 ConfigMap
  • ✅ 配置集中管理
  • ✅ 易于维护

使用直接 env(不推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# deployment-dev.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
env:
- name: ENVIRONMENT
value: "development"
- name: API_URL
value: "https://api-dev.example.com"
---
# deployment-prod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
env:
- name: ENVIRONMENT
value: "production"
- name: API_URL
value: "https://api.example.com"

缺点:

  • ❌ 需要维护多个部署文件
  • ❌ 配置分散,难以管理
  • ❌ 容易出错

五、ConfigMap 的高级用法

5.1 部分键值注入

只注入 ConfigMap 中的部分键值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database_host
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: log_level
# 其他环境变量直接定义
- name: APP_NAME
value: "my-app"

5.2 多个 ConfigMap 合并

从多个 ConfigMap 注入环境变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: database-config
- configMapRef:
name: app-config
- configMapRef:
name: logging-config

5.3 ConfigMap 作为文件挂载

将 ConfigMap 挂载为文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
app.properties: |
server.port=8080
server.host=0.0.0.0
database.host=db.example.com
database.port=5432
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-config

挂载后的文件结构:

1
2
/etc/config/
└── app.properties

5.4 ConfigMap 热更新

当 ConfigMap 更新时,挂载为文件的 ConfigMap 可以自动更新(取决于使用方式):

1
2
3
4
5
6
7
8
9
10
# 更新 ConfigMap
kubectl create configmap app-config \
--from-literal=database_host=new-host.example.com \
--dry-run=client -o yaml | kubectl apply -f -

# 如果使用 volumeMount,需要重启 Pod 才能生效
kubectl rollout restart deployment/app-deployment

# 如果使用 envFrom,需要重建 Pod
kubectl delete pod -l app=my-app

注意:

  • 使用 envFromvalueFrom 注入的环境变量不会自动更新
  • 使用 volumeMount 挂载的文件可能自动更新(取决于应用是否重新读取文件)

六、最佳实践

6.1 何时使用 ConfigMap

推荐使用 ConfigMap 的情况:

  1. 多环境部署:不同环境需要不同配置
  2. 配置共享:多个 Pod 需要相同配置
  3. 配置文件:需要挂载配置文件
  4. 配置更新:需要频繁更新配置
  5. 配置管理:通过 GitOps 管理配置
  6. 配置项较多:配置项超过 5-10 个

6.2 何时使用直接 env

可以使用直接 env 的情况:

  1. 简单应用:配置项少于 5 个
  2. 一次性配置:特定 Pod 的独特配置
  3. 开发测试:快速原型和测试
  4. 临时配置:不需要长期维护

6.3 配置管理建议

建议 1:使用 ConfigMap 管理应用配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 创建 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
# 应用配置
app_name: "my-app"
app_version: "1.0.0"
log_level: "info"

# 数据库配置
database_host: "db.example.com"
database_port: "5432"
database_name: "myapp"

# API 配置
api_timeout: "30"
api_retry_count: "3"

建议 2:使用 Secret 管理敏感信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Secret 用于敏感信息
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
stringData:
database_password: "secret-password"
api_key: "secret-api-key"
---
# ConfigMap 用于非敏感配置
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_host: "db.example.com"
database_port: "5432"

建议 3:环境变量命名规范

1
2
3
4
5
6
7
8
9
10
11
12
# 推荐:使用下划线分隔,全大写
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database_host

# 不推荐:使用驼峰命名
env:
- name: databaseHost
value: "db.example.com"

建议 4:配置分层管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 基础配置
apiVersion: v1
kind: ConfigMap
metadata:
name: base-config
data:
app_name: "my-app"
log_level: "info"
---
# 环境特定配置
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
data:
api_url: "https://api-dev.example.com"
database_host: "db-dev.example.com"
---
# 部署时合并使用
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: base-config
- configMapRef:
name: env-config

6.4 配置验证和测试

验证 ConfigMap 内容

1
2
3
4
5
6
7
8
# 查看 ConfigMap
kubectl get configmap app-config -o yaml

# 查看特定键的值
kubectl get configmap app-config -o jsonpath='{.data.database_host}'

# 验证 Pod 中的环境变量
kubectl exec <pod-name> -- env | grep DATABASE

测试配置更新

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 创建测试 Pod
kubectl run test-pod --image=busybox --rm -it -- sh

# 2. 在 Pod 中检查环境变量
env | grep DATABASE

# 3. 更新 ConfigMap
kubectl create configmap app-config \
--from-literal=database_host=new-host \
--dry-run=client -o yaml | kubectl apply -f -

# 4. 重启 Pod 验证更新
kubectl delete pod test-pod

七、常见问题和解决方案

7.1 ConfigMap 不存在

问题:

1
Error: configmap "app-config" not found

解决方案:

1
2
3
4
5
6
# 确保 ConfigMap 存在
kubectl get configmap app-config

# 如果不存在,创建它
kubectl create configmap app-config \
--from-literal=key=value

7.2 环境变量未注入

问题: Pod 启动后,环境变量不存在

排查步骤:

1
2
3
4
5
6
7
8
9
10
11
# 1. 检查 ConfigMap 是否存在
kubectl get configmap app-config

# 2. 检查 Deployment 配置
kubectl get deployment app-deployment -o yaml

# 3. 检查 Pod 中的环境变量
kubectl exec <pod-name> -- env

# 4. 检查 Pod 事件
kubectl describe pod <pod-name>

7.3 配置更新不生效

问题: 更新 ConfigMap 后,Pod 中的环境变量没有更新

原因:

  • 使用 envFromvalueFrom 注入的环境变量不会自动更新
  • 需要重建 Pod 才能生效

解决方案:

1
2
3
4
5
6
7
# 方式 1:重启 Deployment
kubectl rollout restart deployment/app-deployment

# 方式 2:删除 Pod(Deployment 会自动重建)
kubectl delete pod -l app=my-app

# 方式 3:使用 volumeMount(需要应用支持重新读取文件)

7.4 配置键冲突

问题: 多个 ConfigMap 中有相同的键

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 使用 prefix 避免冲突
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: database-config
prefix: DB_
- configMapRef:
name: app-config
prefix: APP_

7.5 ConfigMap 大小限制

问题: ConfigMap 大小超过 1 MB 限制

解决方案:

  1. 拆分 ConfigMap:将大配置拆分为多个 ConfigMap
  2. 使用文件挂载:将大文件挂载为文件而不是环境变量
  3. 使用外部配置服务:如 Consul、etcd 等

八、实际案例

8.1 案例 1:微服务配置管理

场景: 多个微服务需要共享数据库配置

使用 ConfigMap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 共享数据库配置
apiVersion: v1
kind: ConfigMap
metadata:
name: shared-database-config
data:
host: "db.example.com"
port: "5432"
pool_size: "10"
---
# 服务 A
apiVersion: apps/v1
kind: Deployment
metadata:
name: service-a
spec:
template:
spec:
containers:
- name: service-a
image: service-a:latest
envFrom:
- configMapRef:
name: shared-database-config
---
# 服务 B
apiVersion: apps/v1
kind: Deployment
metadata:
name: service-b
spec:
template:
spec:
containers:
- name: service-b
image: service-b:latest
envFrom:
- configMapRef:
name: shared-database-config

优点:

  • ✅ 配置集中管理
  • ✅ 修改一处,所有服务生效
  • ✅ 易于维护

8.2 案例 2:多环境部署

场景: 同一应用需要部署到开发、测试、生产环境

使用 ConfigMap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# configmap-dev.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: dev
data:
environment: "development"
api_url: "https://api-dev.example.com"
log_level: "debug"
---
# configmap-prod.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: prod
data:
environment: "production"
api_url: "https://api.example.com"
log_level: "info"
---
# deployment.yaml(通用)
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: app-config

部署命令:

1
2
3
4
5
6
7
# 部署到开发环境
kubectl apply -f configmap-dev.yaml -n dev
kubectl apply -f deployment.yaml -n dev

# 部署到生产环境
kubectl apply -f configmap-prod.yaml -n prod
kubectl apply -f deployment.yaml -n prod

8.3 案例 3:配置文件管理

场景: 应用需要读取配置文件

使用 ConfigMap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
application.yml: |
server:
port: 8080
host: 0.0.0.0
database:
host: db.example.com
port: 5432
logging:
level:
root: INFO
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
template:
spec:
containers:
- name: app
image: my-app:latest
volumeMounts:
- name: config-volume
mountPath: /app/config
volumes:
- name: config-volume
configMap:
name: app-config

九、总结

9.1 核心区别

方面 ConfigMap 直接使用 env
资源类型 独立资源对象 Pod 的一部分
可复用性 ✅ 高 ❌ 低
配置管理 ✅ 集中管理 ❌ 分散管理
多环境支持 ✅ 优秀 ❌ 困难
文件支持 ✅ 支持 ❌ 不支持
适用场景 生产环境、复杂应用 简单应用、开发测试

9.2 选择建议

使用 ConfigMap 当:

  • ✅ 需要多环境部署
  • ✅ 配置需要被多个 Pod 共享
  • ✅ 需要挂载配置文件
  • ✅ 配置项较多(>5 个)
  • ✅ 需要频繁更新配置

使用直接 env 当:

  • ✅ 简单应用,配置项少
  • ✅ 开发测试环境
  • ✅ 一次性或临时配置
  • ✅ 特定 Pod 的独特配置

9.3 最佳实践总结

  1. 生产环境优先使用 ConfigMap:提供更好的配置管理和可维护性
  2. 敏感信息使用 Secret:不要将密码、密钥等存储在 ConfigMap 中
  3. 配置分层管理:基础配置和环境配置分离
  4. 统一命名规范:使用一致的命名约定
  5. 配置验证:在部署前验证配置的正确性
  6. 版本控制:通过 GitOps 管理配置变更

9.4 关键要点

  • 📋 ConfigMap 是独立的 Kubernetes 资源,可以被多个 Pod 引用
  • 📋 直接使用 env 配置简单,但难以维护和复用
  • 📋 ConfigMap 支持文件挂载,直接 env 仅支持键值对
  • 📋 ConfigMap 更适合生产环境和复杂应用
  • 📋 敏感信息应使用 Secret,而不是 ConfigMap

相关参考