K8s 系列 | 第 7 天:ConfigMap 与 Secret:配置管理最佳实践


tags:
– Kubernetes
– K8s系列
– DevOps
– ConfigMap
– Secret
– 配置管理


K8s 系列 | 第 7 天:ConfigMap 与 Secret:配置管理最佳实践

第 7/30 天 | 上一篇我们学习了 Namespace 与资源配额,今天来深入探讨 K8s 中配置管理的两大核心对象:ConfigMap 与 Secret。


一、引言

在微服务架构中,应用配置与代码分离是一项基本原则。Kubernetes 提供了ConfigMapSecret 两种资源对象,分别用于管理非敏感配置和敏感数据(密码、API 密钥、证书等)。

为什么需要它们?

  • 避免将配置硬编码到容器镜像中
  • 支持多环境(开发/测试/生产)配置复用
  • 配置变更无需重建镜像,滚动更新即可生效
  • 敏感数据加密与权限控制

二、ConfigMap —— 非敏感配置管理

2.1 什么是 ConfigMap?

ConfigMap 是 K8s 中用于存储非敏感键值对配置的 API 对象。它支持四种数据来源:

来源类型 说明
字面量(literal) 直接在 CLI 中指定 key=value
文件(file) 从本地文件读取内容
目录(directory) 批量加载目录下所有文件
YAML 清单 声明式定义

2.2 创建 ConfigMap

方式一:字面量创建

# 创建包含两个键值对的 ConfigMap
kubectl create configmap app-config 
  --from-literal=APP_ENV=production 
  --from-literal=APP_LOG_LEVEL=info

方式二:从文件创建

# 从配置文件创建
kubectl create configmap nginx-config 
  --from-file=nginx.conf

# 指定 key 名称(默认为文件名)
kubectl create configmap app-properties 
  --from-file=application.properties=./prod-app.properties

方式三:YAML 声明式创建

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: default
data:
  APP_ENV: "production"
  APP_LOG_LEVEL: "info"
  nginx.conf: |
    server {
      listen 80;
      server_name example.com;
      location / {
        proxy_pass http://backend:8080;
      }
    }

2.3 使用 ConfigMap

Pod 可以通过环境变量挂载卷两种方式使用 ConfigMap。

方式一:环境变量注入

apiVersion: v1
kind: Pod
metadata:
  name: configmap-env-demo
spec:
  containers:
    - name: app
      image: nginx:1.25
      envFrom:
        - configMapRef:
            name: app-config     # 注入全部键值对
      env:
        - name: DATABASE_URL     # 注入单个键
          valueFrom:
            configMapKeyRef:
              name: db-config
              key: DATABASE_URL

方式二:挂载为卷文件

apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume-demo
spec:
  containers:
    - name: app
      image: nginx:1.25
      volumeMounts:
        - name: config
          mountPath: /etc/nginx/conf.d
          readOnly: true
  volumes:
    - name: config
      configMap:
        name: nginx-config

⚠️ 注意:通过 subPath 挂载单个文件时,ConfigMap 更新后文件不会自动同步。全量挂载目录则自动同步(延迟约 2~3 分钟)。


三、Secret —— 敏感数据管理

3.1 什么是 Secret?

Secret 用于存储敏感数据(密码、Token、SSH 密钥等),其值以 Base64 编码存储。K8s 默认开启了静态加密,并在 etcd 中加密保存。

Secret 类型 用途
Opaque 通用敏感数据(默认)
kubernetes.io/service-account-token ServiceAccount Token
kubernetes.io/dockerconfigjson 私有镜像仓库认证
kubernetes.io/tls TLS 证书与密钥
bootstrap.kubernetes.io/token 集群引导令牌

3.2 创建 Secret

方式一:命令式创建

# 通用 Secret
kubectl create secret generic db-credentials 
  --from-literal=DB_USER=admin 
  --from-literal=DB_PASSWORD='MyP@ssw0rd!'

# TLS 证书
kubectl create secret tls tls-secret 
  --cert=tls.crt 
  --key=tls.key

# 镜像仓库认证
kubectl create secret docker-registry regcred 
  --docker-server=https://index.docker.io/v1/ 
  --docker-username=myuser 
  --docker-password=mypassword 
  --docker-email=user@example.com

方式二:YAML 声明式创建

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  DB_USER: YWRtaW4=              # echo -n "admin" | base64
  DB_PASSWORD: TXlQQHNzdzByZCE=  # echo -n "MyP@ssw0rd!" | base64
---
apiVersion: v1
kind: Secret
metadata:
  name: tls-secret
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS1CRUdJTi...     # Base64 编码的证书
  tls.key: LS0tLS1CRUdJTi...     # Base64 编码的私钥

⚠️ 安全提示:生产环境中不要将 Secret 的明文直接写入 YAML 文件然后提交到 Git。应使用 SealedSecretExternal Secrets OperatorVault 等工具管理。

3.3 使用 Secret

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-demo
spec:
  containers:
    - name: app
      image: myapp:latest
      envFrom:
        - secretRef:
            name: db-credentials
      volumeMounts:
        - name: tls
          mountPath: /etc/ssl/certs
          readOnly: true
  volumes:
    - name: tls
      secret:
        secretName: tls-secret
  imagePullSecrets:
    - name: regcred     # 拉取私有镜像时使用

四、配置管理最佳实践

4.1 Immutable ConfigMap/Secret

K8s v1.21+ 支持将 ConfigMap/Secret 标记为 immutable(不可变),大幅降低 API Server 负载并提升性能。

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
immutable: true      # 标记为不可变
data:
  APP_ENV: production

标记 immutable 后,只能删除重建,不能原地更新。适合启动后不会变化的配置。

4.2 配置热更新策略

更新方式 ConfigMap 更新生效 推荐场景
环境变量注入 ❌ 需重启 Pod 启动后不变的配置
挂载卷(全量) ✅ 自动同步(~2-3min) 频繁变动的配置
挂载卷(subPath) ❌ 不自动同步 单个文件挂载
Sidecar 重载 ✅ 自行控制 需要精确重载时机

4.3 敏感数据生产建议

  1. 不要将明文 Secret 提交到 Git——使用 git-secrets.gitignore 过滤
  2. 使用 SealedSecret 加密后再提交到 Git:
    bash
    kubeseal --format yaml < db-secret.yaml > sealed-db-secret.yaml
  3. 生产环境部署 External Secrets OperatorVault Agent Sidecar,从外部 KMS 同步 Secret
  4. 启用 K8s 静态加密(v1.13+ 默认开启)并审计 etcd 访问
  5. 为每个环境(dev/staging/prod)使用独立的 Secret,避免跨环境泄露

4.4 完整的生产实践示例

下面是一个结合 ConfigMap、Secret、Deployment 的完整示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: production
data:
  APP_NAME: "myapp"
  APP_ENV: "production"
  APP_LOG_LEVEL: "warn"
---
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
  namespace: production
type: Opaque
data:
  DB_PASSWORD: TXlQYXNzd29yZDIwMjY=
  API_KEY: c2stcHJvZC1hcGkta2V5LTEyMzQ1Njc4OTA=
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: myapp:1.24.0
          ports:
            - containerPort: 8080
          envFrom:
            - configMapRef:
                name: app-config
            - secretRef:
                name: app-secrets
          volumeMounts:
            - name: config-files
              mountPath: /etc/myapp
              readOnly: true
      volumes:
        - name: config-files
          configMap:
            name: app-config-files
      imagePullSecrets:
        - name: regcred

五、常见问题与排查

5.1 ConfigMap/Secret 找不到

# 检查是否存在
kubectl get configmap -n <namespace>
kubectl get secret -n <namespace>

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

# 常见报错:找不到 ConfigMap/Secret
# Error: configmap "xxx" not found
# → 检查 namespace、名称拼写、是否已在同一命名空间

5.2 Secret Base64 解码查看

# 查看 Secret 的 Base64 值
kubectl get secret db-credentials -o jsonpath='{.data.DB_PASSWORD}'

# 解码获取明文(⚠️ 安全风险,仅调试用)
kubectl get secret db-credentials -o jsonpath='{.data.DB_PASSWORD}' | base64 -d

5.3 配置更新后没有生效

排查步骤:

# 1. 确认 ConfigMap 是否更新
kubectl describe configmap nginx-config

# 2. 检查 Pod 中文件内容
kubectl exec <pod-name> -- cat /etc/nginx/conf.d/default.conf

# 3. 重启 Deployment 强制加载新配置
kubectl rollout restart deployment myapp

六、总结

对比项 ConfigMap Secret
存储内容 非敏感配置(文本、配置文件) 敏感数据(密码、证书、Token)
编码方式 明文 Base64 编码
大小限制 1MB(etcd 限制) 1MB(etcd 限制)
自动加密 ✅(静态加密)
immutable ✅ v1.21+ ✅ v1.21+
推荐场景 环境变量、配置文件 密码、API 密钥、TLS 证书

掌握 ConfigMap 与 Secret 是 K8s 配置管理的基石,也是将应用从开发环境优雅迁移到生产环境的关键一步。


📖 下期预告

第 8 天:Volume 与 PersistentVolume:存储抽象层的核心机制

我们将深入 K8s 存储体系,学习 Pod 卷、PV、PVC 的概念与实战,解决容器存储的”有状态”难题。

🔗 系列目录:[K8s 系列 30 天从入门到生产运维](https://www.stellardata.top/tag/k8s系列/)

🏷️ 标签#Kubernetes #K8s系列 #DevOps #ConfigMap #Secret #配置管理 #云原生

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容