Kubernetes ConfigMap 使用指南

Kubernetes ConfigMap 使用指南

什麼是 ConfigMap?

Kubernetes ConfigMap 是一個 API 物件,用於存儲非敏感的配置資料,以鍵值對的形式存在。ConfigMap 允許您將配置從容器映像中分離出來,使應用程式更具可移植性和靈活性。

ConfigMap 的主要功能:

  • 配置分離:將應用程式配置與程式碼分離
  • 環境管理:支援不同環境的配置管理
  • 動態更新:支援運行時配置更新
  • 多種掛載方式:可作為環境變數、檔案或目錄掛載

為什麼使用 ConfigMap?

相較於將配置硬編碼在應用程式中,ConfigMap 提供了更好的配置管理方式:

  1. 靈活性:無需重新構建映像就能改變配置
  2. 可重用性:同一個 ConfigMap 可被多個 Pod 使用
  3. 版本控制:配置變更可以被追蹤和管理
  4. 環境一致性:確保不同環境使用正確的配置

ConfigMap 基本配置

基本 ConfigMap 範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: ConfigMap
metadata:
name: dockertest-config
namespace: dockertest-namespace
labels:
app: dockertest
data:
# 應用程式配置
CUSTOM_VALUE: "configmap_version"
LOG_LEVEL: "INFO"
MAX_CONNECTIONS: "100"
FEATURE_ENABLED: "true"

# 資料庫配置
DB_HOST: "database.example.com"
DB_PORT: "5432"
DB_NAME: "myapp"

# 快取配置
REDIS_HOST: "redis.example.com"
REDIS_PORT: "6379"

包含檔案內容的 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
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-files
namespace: dockertest-namespace
data:
# 配置檔案內容
application.properties: |
app.name=MyApplication
app.version=1.0.0
server.port=8080
logging.level.root=INFO

nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
}

# JSON 格式配置
config.json: |
{
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp"
},
"features": {
"enableLogging": true,
"maxRetries": 3
}
}

在 Pod 中使用 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
apiVersion: apps/v1
kind: Deployment
metadata:
name: dockertest-deployment
namespace: dockertest-namespace
spec:
replicas: 1
selector:
matchLabels:
app: dockertest
template:
metadata:
labels:
app: dockertest
spec:
containers:
- name: dockertest
image: docker.io/pcion123/tinydocker:0.0.10
env:
# 引用整個 ConfigMap
- name: CUSTOM_VALUE
valueFrom:
configMapKeyRef:
name: dockertest-config
key: CUSTOM_VALUE
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: dockertest-config
key: LOG_LEVEL
# 引用多個鍵值
envFrom:
- configMapRef:
name: dockertest-config

方法二:作為檔案掛載

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
apiVersion: apps/v1
kind: Deployment
metadata:
name: dockertest-deployment
namespace: dockertest-namespace
spec:
replicas: 1
selector:
matchLabels:
app: dockertest
template:
metadata:
labels:
app: dockertest
spec:
containers:
- name: dockertest
image: docker.io/pcion123/tinydocker:0.0.10
volumeMounts:
# 掛載整個 ConfigMap 為目錄
- name: config-volume
mountPath: /etc/config
# 掛載特定檔案到指定位置
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: config-volume
configMap:
name: dockertest-config
- name: nginx-config
configMap:
name: dockertest-config
items:
- key: nginx.conf
path: nginx.conf

方法三:混合使用

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
40
41
42
43
44
45
46
47
48
49
50
51
52
apiVersion: apps/v1
kind: Deployment
metadata:
name: dockertest-deployment
namespace: dockertest-namespace
spec:
replicas: 1
selector:
matchLabels:
app: dockertest
template:
metadata:
labels:
app: dockertest
spec:
containers:
- name: dockertest
image: docker.io/pcion123/tinydocker:0.0.10
env:
# 引用整個 ConfigMap
- name: CUSTOM_VALUE
valueFrom:
configMapKeyRef:
name: dockertest-config
key: CUSTOM_VALUE
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: dockertest-config
key: LOG_LEVEL
# 引用多個鍵值
envFrom:
- configMapRef:
name: dockertest-config
volumeMounts:
# 掛載整個 ConfigMap 為目錄
- name: config-volume
mountPath: /etc/config
# 掛載特定檔案到指定位置
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: config-volume
configMap:
name: dockertest-config
- name: nginx-config
configMap:
name: dockertest-config
items:
- key: nginx.conf
path: nginx.conf

建立和管理 ConfigMap

使用 kubectl 指令建立

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 從字面值建立
kubectl create configmap my-config \
--from-literal=key1=value1 \
--from-literal=key2=value2 \
-n dockertest-namespace

# 從檔案建立
kubectl create configmap file-config \
--from-file=application.properties \
--from-file=config.json \
-n dockertest-namespace

# 從目錄建立
kubectl create configmap dir-config \
--from-file=./config-directory/ \
-n dockertest-namespace

# 從環境檔案建立
kubectl create configmap env-config \
--from-env-file=.env \
-n dockertest-namespace

管理指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看 ConfigMap 列表
kubectl get configmaps -n dockertest-namespace

# 查看 ConfigMap 詳細內容
kubectl describe configmap dockertest-config -n dockertest-namespace

# 查看 ConfigMap 的 YAML 格式
kubectl get configmap dockertest-config -n dockertest-namespace -o yaml

# 編輯 ConfigMap
kubectl edit configmap dockertest-config -n dockertest-namespace

# 刪除 ConfigMap
kubectl delete configmap dockertest-config -n dockertest-namespace

更新 ConfigMap

1
2
3
4
5
6
7
8
9
# 方法一:重新應用 YAML 檔案
kubectl apply -f configmap.yaml

# 方法二:使用 patch 更新特定鍵值
kubectl patch configmap dockertest-config -n dockertest-namespace \
--type merge -p '{"data":{"NEW_KEY":"new_value"}}'

# 方法三:替換整個 ConfigMap
kubectl replace -f updated-configmap.yaml

實際應用範例

範例一:Spring Boot 應用程式配置

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
40
41
42
43
apiVersion: v1
kind: ConfigMap
metadata:
name: spring-app-config
namespace: dockertest-namespace
data:
# Spring Boot 配置
SPRING_PROFILES_ACTIVE: "production"
SERVER_PORT: "8080"
LOGGING_LEVEL_ROOT: "INFO"
LOGGING_LEVEL_COM_EXAMPLE: "DEBUG"

# 資料庫配置
SPRING_DATASOURCE_URL: "jdbc:postgresql://db:5432/myapp"
SPRING_DATASOURCE_USERNAME: "appuser"
SPRING_DATASOURCE_DRIVERCLASSNAME: "org.postgresql.Driver"

# JVM 配置
JAVA_OPTS: "-Xmx512m -Xms256m -Djava.awt.headless=true"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-app
namespace: dockertest-namespace
spec:
replicas: 2
selector:
matchLabels:
app: spring-app
template:
metadata:
labels:
app: spring-app
spec:
containers:
- name: spring-app
image: docker.io/pcion123/tinydocker:0.0.10
envFrom:
- configMapRef:
name: spring-app-config
ports:
- containerPort: 8080

範例二:多環境配置管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 開發環境 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-dev
namespace: development
data:
ENVIRONMENT: "development"
LOG_LEVEL: "DEBUG"
DB_HOST: "dev-database"
CACHE_ENABLED: "false"
---
# 生產環境 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-prod
namespace: production
data:
ENVIRONMENT: "production"
LOG_LEVEL: "WARN"
DB_HOST: "prod-database"
CACHE_ENABLED: "true"

最佳實務建議

配置管理

  1. 命名規範:使用清晰、一致的 ConfigMap 命名
  2. 環境分離:為不同環境建立獨立的 ConfigMap
  3. 版本控制:將 ConfigMap 定義納入版本控制系統
  4. 文檔記錄:詳細記錄每個配置項的用途和格式

安全性考量

  1. 敏感資料:將密碼等敏感資料存儲在 Secret 中,而非 ConfigMap
  2. 存取控制:使用 RBAC 控制 ConfigMap 的存取權限
  3. 最小權限:只授予應用程式所需的最小配置存取權限
  4. 定期審核:定期檢查和清理不再使用的 ConfigMap

效能和可靠性

  1. 大小限制:單個 ConfigMap 不應超過 1MB
  2. 變更影響:了解 ConfigMap 變更對運行中 Pod 的影響
  3. 自動重啟:考慮使用工具自動重啟使用更新配置的 Pod
  4. 配置驗證:在應用配置前驗證配置的正確性

監控和維護

  1. 配置追蹤:追蹤配置變更的歷史和影響
  2. 健康檢查:確保應用程式能正確讀取和使用配置
  3. 備份策略:定期備份重要的 ConfigMap
  4. 清理策略:定期清理不再使用的 ConfigMap

疑難排解

常見問題

1. Pod 無法讀取 ConfigMap

1
2
3
4
5
6
7
8
# 檢查 ConfigMap 是否存在
kubectl get configmap dockertest-config -n dockertest-namespace

# 檢查 Pod 配置
kubectl describe pod <pod-name> -n dockertest-namespace

# 查看 Pod 日誌
kubectl logs <pod-name> -n dockertest-namespace

2. 配置更新後 Pod 未重啟

1
2
3
4
5
# 手動重啟 Deployment
kubectl rollout restart deployment dockertest-deployment -n dockertest-namespace

# 查看重啟狀態
kubectl rollout status deployment dockertest-deployment -n dockertest-namespace

3. 環境變數未正確載入

1
2
3
4
5
# 進入 Pod 檢查環境變數
kubectl exec -it <pod-name> -n dockertest-namespace -- env | grep CUSTOM_VALUE

# 檢查 ConfigMap 內容
kubectl get configmap dockertest-config -n dockertest-namespace -o yaml

透過正確使用 ConfigMap,您可以實現靈活的配置管理,讓應用程式更容易在不同環境間移植和部署,同時保持配置的一致性和可維護性。