概念解析

ConfigMap和Secret是Kubernetes中用於管理配置數據和敏感信息的核心資源。它們允許將配置信息與容器鏡像分離,提高應用程序的可移植性和安全性。

ConfigMap概念

ConfigMap是一種API對象,用於存儲非機密性的鍵值對配置數據。它可以被Pod使用,作為環境變量、命令行參數或存儲卷文件的形式注入到容器中。

Secret概念

Secret是用於存儲敏感信息(如密碼、OAuth令牌和SSH密鑰)的Kubernetes對象。與ConfigMap類似,Secret也可以以環境變量或存儲卷的形式注入到Pod中,但提供了額外的安全保護措施。

核心區別

  1. 數據敏感性:ConfigMap用於非敏感配置,Secret用於敏感信息
  2. 存儲方式:Secret數據會被Base64編碼(但不是加密)
  3. 訪問控制:Secret有更嚴格的訪問控制機制
  4. 使用場景:ConfigMap用於一般配置,Secret用於密碼、令牌等

核心特性

ConfigMap特性

  1. 多種數據格式:支持鍵值對、文件內容等多種數據格式
  2. 靈活注入:可通過環境變量、存儲卷等方式注入Pod
  3. 動態更新:支持運行時更新配置(需要應用支持)
  4. 命名空間隔離:在命名空間內隔離配置數據

Secret特性

  1. 數據加密:數據在etcd中以Base64編碼存儲
  2. 訪問控制:支持RBAC權限控制
  3. 多種類型:支持generic、tls、docker-registry等類型
  4. 自動掛載:ServiceAccount自動掛載相關Secret

實踐教程

創建ConfigMap

# 從字面值創建
kubectl create configmap app-config --from-literal=database.host=localhost --from-literal=database.port=5432

# 從文件創建
echo -n "localhost" > db-host.txt
echo -n "5432" > db-port.txt
kubectl create configmap app-config --from-file=db-host.txt --from-file=db-port.txt

# 從配置文件創建
cat <<EOF > app.properties
database.host=localhost
database.port=5432
log.level=INFO
EOF
kubectl create configmap app-config --from-file=app.properties

創建Secret

# 從字面值創建
kubectl create secret generic db-secret --from-literal=username=admin --from-literal=password=secretpassword

# 從文件創建
echo -n "admin" > username.txt
echo -n "secretpassword" > password.txt
kubectl create secret generic db-secret --from-file=username.txt --from-file=password.txt

# 從TLS證書創建
kubectl create secret tls tls-secret --cert=path/to/cert.crt --key=path/to/key.key

在Pod中使用ConfigMap

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: app
    image: busybox
    command: ["/bin/sh", "-c", "echo Database Host: $DB_HOST; sleep 3600"]
    env:
    - name: DB_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: database.host
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: app-config

在Pod中使用Secret

apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
  - name: app
    image: busybox
    command: ["/bin/sh", "-c", "echo Username: $DB_USER; sleep 3600"]
    env:
    - name: DB_USER
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: username
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secret
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: db-secret

真實案例

案例:微服務配置管理平台

某公司在Kubernetes集羣中運行多個微服務,每個服務都有不同的配置需求。通過ConfigMap和Secret實現統一的配置管理:

# 數據庫配置ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: database-config
data:
  host: postgresql.db.svc.cluster.local
  port: "5432"
  name: myapp_db
  sslmode: require
---
# 應用配置ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  log.level: INFO
  cache.size: "1000"
  api.timeout: "30s"
  feature.flags: "enable-cache=true,enable-metrics=false"
---
# 數據庫憑證Secret
apiVersion: v1
kind: Secret
metadata:
  name: database-secret
type: Opaque
data:
  username: YWRtaW4=  # admin (base64)
  password: cGFzc3dvcmQxMjM=  # password123 (base64)
---
# API密鑰Secret
apiVersion: v1
kind: Secret
metadata:
  name: api-keys
type: Opaque
data:
  payment-api-key: cG9ydGFsX2tleV9zZWNyZXQ=  # portal_key_secret (base64)
  notification-token: bm90aWZpY2F0aW9uX3Rva2VuX3NlY3JldA==  # notification_token_secret (base64)
---
# 應用Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: app
        image: mycompany/web-app:1.0
        env:
        # 從ConfigMap注入數據庫配置
        - name: DB_HOST
          valueFrom:
            configMapKeyRef:
              name: database-config
              key: host
        - name: DB_PORT
          valueFrom:
            configMapKeyRef:
              name: database-config
              key: port
        # 從Secret注入數據庫憑證
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: database-secret
              key: username
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: database-secret
              key: password
        # 從ConfigMap注入應用配置
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: log.level
        volumeMounts:
        # 掛載配置文件
        - name: config-volume
          mountPath: /etc/app/config
          readOnly: true
        # 掛載密鑰文件
        - name: secret-volume
          mountPath: /etc/app/secrets
          readOnly: true
      volumes:
      - name: config-volume
        configMap:
          name: app-config
      - name: secret-volume
        secret:
          secretName: api-keys

這種配置管理方式的優勢:

  • 配置與代碼分離,提高安全性
  • 統一管理所有服務的配置
  • 支持不同環境的不同配置
  • 動態更新配置而無需重建鏡像

配置詳解

複雜ConfigMap配置

apiVersion: v1
kind: ConfigMap
metadata:
  name: complex-config
data:
  # 簡單鍵值對
  database.url: "postgresql://localhost:5432/mydb"
  
  # 多行配置
  application.yml: |
    server:
      port: 8080
    spring:
      datasource:
        url: ${DATABASE_URL}
        username: ${DATABASE_USER}
        
  # JSON配置
  app-settings.json: |
    {
      "cache": {
        "enabled": true,
        "ttl": 3600
      },
      "features": {
        "logging": true,
        "metrics": false
      }
    }
    
  # 環境變量文件
  env.properties: |
    LOG_LEVEL=DEBUG
    MAX_CONNECTIONS=100
    ENABLE_SSL=true

不同類型的Secret

# 通用Secret
apiVersion: v1
kind: Secret
metadata:
  name: generic-secret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

# TLS Secret
apiVersion: v1
kind: Secret
metadata:
  name: tls-secret
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNVakNDQWZHZ0F3SUJBZ0lKQU5hTmx...
  tls.key: LS0tLS1CRUdJTiBSU0EgUFJJV

# Docker Registry Secret
apiVersion: v1
kind: Secret
metadata:
  name: registry-secret
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJkb2NrZXJ1c2VyIiwicGFzc3dvcmQiOiJkb2NrZXJwYXNzd29yZCIsImF1dGgiOiJkb2NrZXJhdXRoIn19fQ==

Immutable ConfigMap和Secret

apiVersion: v1
kind: ConfigMap
metadata:
  name: immutable-config
immutable: true
data:
  key: value

故障排除

常見問題及解決方案

  1. ConfigMap/Secret未注入到Pod

    # 檢查ConfigMap/Secret是否存在
    kubectl get configmap <configmap-name>
    kubectl get secret <secret-name>
    
    # 檢查Pod配置
    kubectl describe pod <pod-name>
    
    # 檢查Pod日誌
    kubectl logs <pod-name>
    
  2. Base64編碼錯誤

    # 正確的Base64編碼方式
    echo -n "mypassword" | base64
    
    # 解碼驗證
    echo "bXlwYXNzd29yZA==" | base64 --decode
    
  3. 權限問題

    # 檢查RBAC權限
    kubectl auth can-i get secrets --namespace <namespace>
    
    # 檢查ServiceAccount
    kubectl describe serviceaccount <sa-name>
    
  4. 數據更新不生效

    # 檢查是否使用了Immutable配置
    kubectl get configmap <name> -o yaml
    
    # 檢查應用是否支持熱更新
    # 有些應用需要重啓才能讀取新配置
    

最佳實踐

  1. 命名規範

    • 使用有意義的名稱
    • 遵循命名空間隔離原則
    • 為不同環境使用不同的ConfigMap/Secret
  2. 數據管理

    • 敏感數據使用Secret,非敏感數據使用ConfigMap
    • 避免在配置中硬編碼敏感信息
    • 定期輪換密鑰和密碼
  3. 版本控制

    • 將ConfigMap/Secret定義保存在版本控制系統中
    • 使用標籤或註解記錄版本信息
    • 建立配置變更審批流程
  4. 安全考慮

    • 限制對Secret的訪問權限
    • 使用加密存儲敏感數據
    • 定期審計配置訪問日誌
  5. 監控和告警

    • 監控ConfigMap/Secret的變更
    • 設置配置異常告警
    • 建立配置備份機制

安全考慮

加密存儲敏感數據

apiVersion: v1
kind: Secret
metadata:
  name: encrypted-secret
type: Opaque
data:
  # 敏感數據應進行Base64編碼
  api-key: c2VjcmV0LWFwaS1rZXk=  # secret-api-key (base64)

使用RBAC控制訪問

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: config-reader
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-configs
  namespace: default
subjects:
- kind: User
  name: developer
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: config-reader
  apiGroup: rbac.authorization.k8s.io

啓用靜態加密

在kube-apiserver配置中啓用靜態加密:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aesgcm:
          keys:
            - name: key1
              secret: c2VjcmV0IGtleSBtdXN0IGJlIDMyIGJ5dGVzIGxvbmc=
      - identity: {}

命令速查

命令 描述
kubectl create configmap <name> --from-literal=<key>=<value> 從字面值創建ConfigMap
kubectl create secret generic <name> --from-literal=<key>=<value> 從字面值創建Secret
kubectl get configmaps 查看ConfigMap列表
kubectl get secrets 查看Secret列表
kubectl describe configmap <name> 查看ConfigMap詳細信息
kubectl describe secret <name> 查看Secret詳細信息
kubectl get configmap <name> -o yaml 以YAML格式查看ConfigMap
kubectl get secret <name> -o yaml 以YAML格式查看Secret
kubectl delete configmap <name> 刪除ConfigMap
kubectl delete secret <name> 刪除Secret

總結

ConfigMap和Secret是Kubernetes中管理配置和敏感信息的核心組件。通過本文檔的學習,你應該能夠:

  • 理解ConfigMap和Secret的概念和區別
  • 創建和管理ConfigMap和Secret
  • 在Pod中正確使用ConfigMap和Secret
  • 遵循配置管理的最佳實踐和安全考慮
  • 排查常見的配置管理問題

在下一文檔中,我們將學習PersistentVolume持久化存儲,它是管理有狀態應用數據的重要組件。