K8S - ConfigMap 与 Secret - 应用配置与敏感信息管理

一、引言

在 Kubernetes 集群中,应用通常需要依赖外部配置或敏感信息(如数据库连接字符串、API 密钥等)。直接将这些信息硬编码在容器镜像中既不灵活,也存在安全风险。为了解决这一问题,Kubernetes 提供了 ConfigMap和 Secret机制,实现配置与敏感信息的解耦管理。

二、原理

2.1 ConfigMap

ConfigMap 用于存储非敏感的配置信息,例如应用的环境变量、配置文件等。它支持多种数据格式,如键值对、完整的配置文件等。

核心能力:

• 以键值对方式存储配置信息。

• 可通过环境变量、命令参数、挂载文件等方式提供给 Pod。

• 允许动态更新,减少容器重启需求。

数据结构示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: default
data:
  APP_MODE: "production"
  LOG_LEVEL: "info"
  config.json: |
    {
      "cacheSize": 100,
      "retry": true
    }

2.2 Secret

Secret 用于存储敏感信息,例如密码、密钥和证书等。它与 ConfigMap 类似,但数据默认以 Base64 编码存储,并支持更严格的访问控制策略。

核心能力:

• 以 Base64 编码存储敏感信息。

• 通过环境变量或挂载文件的方式提供给 Pod。

• 支持 RBAC 访问控制,提升安全性。

数据结构示例:

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
  namespace: default
type: Opaque
data:
  username: dXNlcm5hbWU=  # "username"Base64 编码
  password: cGFzc3dvcmQ=  # "password"Base64 编码

三、实战示例

3.1 ConfigMap 管理环境变量

步骤 1:创建 ConfigMap,提供配置数据

方法1:直接创建 ConfigMap 资源

kubectl create configmap app-config \
  --namespace=config-demo \
  --from-literal=APP_ENV=production \
  --from-literal=APP_LOG_LEVEL=info \
  --from-file=config.json=config.json

方法2: 创建 app-config.yaml 并 通过apply 创建 ConfigMap 资源。

# app-config.yaml
apiVersion: v1           #  API 版本
kind: ConfigMap          # 声明资源类型为 ConfigMap
metadata:
  name: app-config       # ConfigMap 的名称
  namespace: config-demo # 所属命名空间,确保与使用方一致
data:
  APP_ENV: "production"             # 配置项:表示运行环境
  APP_LOG_LEVEL: "info"            # 配置项:日志级别
  config.json: |                   # 复杂数据:完整 JSON 配置文件
    {
      "cache_size": "100MB",
      "max_connections": 500
    }

• data字段支持键值对或多行文本(如配置文件)。

• 每个键在挂载时可以单独指定,也可以整体注入为文件。

kubectl apply -f app-config.yaml   # 创建 ConfigMap 资源

步骤 2:在pod 中使用 ConfigMap

通过环境变量和文件挂载使用 ConfigMap

# app-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: app-pod
  namespace: config-demo
spec:
  containers:
    - name: app-container
      image: nginx:alpine             # 使用轻量级 nginx 镜像

      env:  # 通过环境变量使用 ConfigMap
        - name: ENVIRONMENT           # 容器环境变量名 ENVIRONMENT
          valueFrom:                  # 从 ConfigMap 中注入值
            configMapKeyRef:
              name: app-config        # 引用名为 app-config 的 ConfigMap
              key: APP_ENV            # 取其中的 APP_ENV 键对应的值
              optional: true          # 若 APP_ENV 不存在,Pod 不报错,值为空

        - name: LOG_LEVEL             # 容器环境变量名 LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: APP_LOG_LEVEL
              optional: true          # 若 APP_LOG_LEVEL 不存在,Pod 不报错,值为空

      volumeMounts: # 通过挂载文件使用ConfigMap
        - name: config-volume         # 挂载名为 config-volume 的 Volume
          mountPath: /etc/app-config  # 挂载路径,作为配置文件目录

  volumes:    #  定义卷 
    - name: config-volume             # 定义一个名为 config-volume 的 Volume
      configMap:
        name: app-config              # 引用的 ConfigMap 名称
        items:
          - key: config.json          # 仅挂载 configMap 中的 config.json 键
            path: config.json         # 文件名为 config.json

参数关系说明:

• env.valueFrom.configMapKeyRef:单个键值注入为环境变量。

• volumes.configMap.items+ volumeMounts:以文件形式挂载部分或全部键。上例只挂载 key:config.json

• optional: true 提升部署容错性,避免因 ConfigMap 键缺失导致 Pod 启动失败。

提交pod 应用到集群

kubectl apply -f app-pod.yaml  # 提交 Pod 定义到集群

步骤 3:验证 ConfigMap 注入效果

1.验证环境变量注入

kubectl exec -n config-demo app-pod -- env | grep -E 'ENVIRONMENT|LOG_LEVEL'
# 输出:
# ENVIRONMENT=production
# LOG_LEVEL=info

验证目标:

• 确认 APP_ENV和 APP_LOG_LEVEL从 ConfigMap 成功注入为容器环境变量。

• 环境变量 ENVIRONMENT和 LOG_LEVEL的值与 ConfigMap 中定义的 APP_ENV和 APP_LOG_LEVEL一致。

2.验证配置文件挂载

# 查看挂载的配置文件内容

kubectl exec -n config-demo app-pod -- cat /etc/app-config/config.json

# 预期输出 config.json 内容:
# {
#   "cache_size": "100MB",
#   "max_connections": 500
# }

验证目标:

• 确认 config.json文件从 ConfigMap 挂载到容器路径 /etc/app-config/config.json。

• 文件内容与 ConfigMap 中定义的 JSON 完全一致(包括格式和缩进)。

总结:

1.ConfigMap → Volume → Pod 挂载路径的映射关系:

┌──────────────────────────────┐
│         ConfigMap            │
│  名称:app-config            │
│  键值:                      │
│    - config.json             │
└────────────┬─────────────────┘
             │ 引用
             ▼
┌──────────────────────────────┐
│           Volume             │
│  名称:config-volume         │
│  来源:ConfigMap: app-config │
│  items:                      │
│    - key: config.json        │
│      path: config.json       │
└────────────┬─────────────────┘
             │ 挂载
             ▼
┌──────────────────────────────┐
│            Pod               │
│  容器挂载目录:               │
│    /etc/app-config/config.json ←─ 映射到容器内的路径
└──────────────────────────────┘

说明:

• ConfigMap提供配置数据(如 config.json)。

• Volume引用 ConfigMap,并指定要挂载的键和目标文件名。

• Pod中的容器通过 volumeMounts把这个文件挂载到指定路径 /etc/app-config/config.json。

2.ConfigMap 到 Pod 的挂载映射关系

ConfigMap (app-config)               Pod (app-pod)
├── data                            ├── env
│   ├── APP_ENV → ENVIRONMENT       │   ├── ENVIRONMENT=production
│   └── APP_LOG_LEVEL → LOG_LEVEL   │   └── LOG_LEVEL=info
└── config.json                     └── volumeMounts
                                       └── /etc/app-config/config.json

3.关键参数对比表
在这里插入图片描述

3.2 Secret 管理敏感信息

步骤 1:创建 Secret

echo -n "db-password-123" | base64
# 输出:ZGItcGFzc3dvcmQtMTIz
# db-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
  namespace: config-demo
type: Opaque                      # 通用类型
data:
  password: ZGItcGFzc3dvcmQtMTIz  # Base64 编码后的密码

注意:

• data字段中的值必须是 Base64 编码后的字符串。

• Secret 在 Kubernetes 中并不会进行加密,而是防止明文暴露(如命令行显示),但仍建议结合 Kubernetes 的加密功能进一步增强安全性。

步骤 2:在 Pod 中使用 Secret

配置 db-pod.yaml文件,使 Pod 使用 Secret 数据,注入环境变量并将 Secret 挂载为文件:

apiVersion: v1
kind: Pod
metadata:
  name: db-pod
  namespace: config-demo
spec:
  containers:
    - name: db-client
      image: busybox
      command: ["sh", "-c", "sleep 3600"]  # 保持容器运行
      env:
        - name: DB_PASSWORD  # 设置环境变量
          valueFrom:
            secretKeyRef:
              name: db-secret  # 引用 Secret 名称
              key: password    # 指定 Secret 中的密码字段
      volumeMounts:
        - name: secret-volume
          mountPath: /etc/secrets  # 将 Secret 挂载到指定路径
          readOnly: true           # 只读挂载,增强安全性
  volumes:
    - name: secret-volume
      secret:
        secretName: db-secret    # 引用 Secret 名称

参数关系说明:

• env.valueFrom.secretKeyRef:将 Secret 中的值注入为环境变量,Kubernetes 会自动解码 Base64 值。

• volumes.secret.secretName:将 Secret 挂载到容器文件系统中作为文件。

步骤 3:验证

1.验证环境变量:

kubectl exec -n config-demo db-pod -- env | grep DB_PASSWORD
# 输出:DB_PASSWORD=db-password-123

2.验证文件挂载:

kubectl exec -n config-demo db-pod -- cat /etc/secrets/password
# 输出:db-password-123

3.验证 Secret 的内容:

kubectl get secret -n config-demo db-secret -o jsonpath='{.data.password}' | base64 -d

# 输出:db-password-123

总结:

1.Secret → Volume → Pod 挂载路径的映射关系

┌──────────────────────────────┐
│           Secret             │
│  名称:db-secret             │
│  键值:                      │
│    - password                │
└────────────┬─────────────────┘
             │ 引用
             ▼
┌──────────────────────────────┐
│           Volume             │
│  名称:secret-volume         │
│  来源:Secret: db-secret     │
└────────────┬─────────────────┘
             │ 挂载
             ▼
┌──────────────────────────────┐
│            Pod               │
│  容器挂载目录:               │
│    /etc/secrets/password ←─ 映射到容器内的路径
└──────────────────────────────┘

说明:

• Secret:提供敏感信息(如密码)存储在 Secret中。

• Volume:将 Secret挂载为文件,确保 Secret的值以文件形式提供给容器。

• Pod:通过 volumeMounts将文件挂载到容器内的指定路径,容器可以读取该文件来获取敏感数据。

2.Secret 到 Pod 的映射关系

Secret (db-secret)               Pod (db-pod)
├── data                         ├── env
│   ├── password → DB_PASSWORD   │   ├── DB_PASSWORD=db-password-123
└── secret                       └── volumeMounts
                                  └── /etc/secrets/password

总结:

1.通过环境变量传递:

• 通过 env.valueFrom.secretKeyRef把 Secret的内容注入到容器的环境变量中。这样,容器可以像普通环境变量一样使用 DB_PASSWORD(从 db-secret中提取)作为密码进行访问。

2.通过文件挂载传递:

• 使用 volumes.secret.secretName把 Secret的内容挂载为文件,并通过 volumeMounts将其挂载到容器的文件系统中。容器可以读取 /etc/secrets/password文件中的内容来获取密码。

3.比较 Secret 与 ConfigMap:

• ConfigMap:主要用于配置数据,通常是非敏感的文本数据(如 JSON、YAML 配置文件)。你可以选择将其通过环境变量传递或挂载文件的方式传递。

• Secret:用于存储敏感信息(如密码、密钥)。可以通过环境变量或文件的形式传递,但需要注意安全性,尤其是避免泄漏。

3.3 动态更新 ConfigMap

步骤 1:编辑 ConfigMap 内容

使用 kubectl edit命令修改 ConfigMap 的内容。这里,我们将 APP_LOG_LEVEL更新为 debug:

kubectl edit configmap -n config-demo app-config
在编辑器中,将 APP_LOG_LEVEL的值更改为 debug:

data:
  APP_ENV: "production"
  APP_LOG_LEVEL: "debug"  # 修改后的值
  config.json: |
    {
      "cache_size": "100MB",
      "max_connections": 500
    }

步骤 2:使变更生效

ConfigMap 更新后,需要使其变更生效。可以通过以下两种方法:

1.方法 1:重启 Pod

通过删除并重新创建 Pod,使其重新加载新的 ConfigMap:

kubectl delete pod -n config-demo app-pod && kubectl apply -f app-pod.yaml

2.方法 2:应用自身支持热加载

如果应用支持热加载(例如 nginx),则可以通过发送信号使应用重新加载配置:

kubectl exec -n config-demo app-pod -- nginx -s reload

步骤 3:验证更新

1.验证环境变量:

通过检查容器环境变量,确保新的日志级别已经生效:

kubectl exec -n config-demo app-pod -- env | grep LOG_LEVEL
# 输出:LOG_LEVEL=debug

这样,通过动态更新 ConfigMap,我们能够无缝地修改配置,并且通过 Pod 的重启或应用的热加载特性使变更生效。

四、结论

4.1 核心重点

1.ConfigMap 的核心价值

• 非敏感配置管理:支持环境变量注入、配置文件挂载,适用于动态配置(如日志级别、功能开关)。

• 动态更新能力:通过 Pod 重启或应用热加载实现配置更新,无需重建镜像。

最佳实践:

• 使用 optional: true避免因键缺失导致 Pod 启动失败。

• 通过 subPath挂载单个文件,防止目录覆盖。

2.Secret 的安全管理

敏感信息保护:默认 Base64 编码(非加密),需结合 Kubernetes 静态加密与 RBAC 策略。

生产级建议:

• 避免通过环境变量传递 Secret(可能被日志记录),优先使用文件挂载。

• 定期轮换敏感数据(如密码、Token)。

3.ConfigMap 与 Secret 的差异
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小马不敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值