Kubernetes 中 ConfigMap 与 Secret 的深度解析

Kubernetes 中 ConfigMap 与 Secret 的深度解析

在 Kubernetes(K8s)的生态系统中,配置管理和敏感数据保护是应用部署的核心环节。ConfigMap 和 Secret 作为 Kubernetes 提供的核心资源,分别承担着非敏感配置数据和敏感数据的管理职责。本文将从理论知识、实践操作、限制分析及加密数据管理四个维度,全面解析 ConfigMap 和 Secret 的核心特性与应用方法。

ConfigMap 理论知识

定义与核心作用

ConfigMap 是 Kubernetes 中用于存储非敏感配置数据的 API 对象,它允许将应用程序的配置信息与容器镜像解耦,实现 "配置即代码" 的管理模式。通过 ConfigMap,开发者可以将配置数据(如应用参数、环境变量、配置文件等)集中管理,避免将配置硬编码到容器镜像或 Pod 定义中,从而提高配置的灵活性和可维护性。

数据结构

ConfigMap 的数据结构以键值对(key-value) 为核心,支持两种主要的数据形态:

  • 字面量键值对:直接定义的简单键值映射,适用于单个配置参数(如max_connections=100)。

  • 文件式数据:以文件内容作为值的键值对,键为文件名,值为文件内容(如app.conf: "log_level=info\nport=8080"),适用于配置文件类数据。

核心优势

  • 解耦配置与代码:配置数据独立于容器镜像,避免因配置变更重建镜像。

  • 环境隔离:通过不同命名空间的 ConfigMap,可实现开发、测试、生产环境的配置隔离。

  • 动态管理:部分场景下支持配置动态更新(如挂载为文件时),无需重启 Pod 即可生效。

  • 版本控制:Kubernetes 会记录 ConfigMap 的变更历史,支持回滚到历史版本。

ConfigMap 实践操作

创建 ConfigMap

Kubernetes 提供多种创建 ConfigMap 的方式,可根据配置数据的形态选择合适的方法。

1. 使用 --from-literal 创建

--from-literal用于直接定义单个或多个字面量键值对,适用于简单的配置参数。可以多次使用该参数定义多个键值对。

命令示例:

复制代码
kubectl create configmap app-config \
  --from-literal=log_level=info \
  --from-literal=max_connections=50 \
  --from-literal=timeout=30s

上述命令创建了名为app-config的 ConfigMap,包含log_level、max_connections和timeout三个键值对。通过kubectl describe configmap app-config可查看创建的 ConfigMap 详情。

2. 使用 --from-file 创建

--from-file用于从文件中读取数据创建 ConfigMap,键为文件名,值为文件内容。支持单个文件、多个文件及目录的方式。

  • 单个文件:指定单个文件路径,键默认为文件名,也可通过新键名=旧文件路径自定义键名(--from-file=newname=旧文件名字)。

示例:

复制代码
# 准备配置文件
echo "log_level=debug\nport=8080" > app.conf
# 以默认文件名作为键
kubectl create configmap app-file-config --from-file=app.conf
# 自定义键名
kubectl create configmap app-file-custom-key --from-file=app_config=app.conf
  • 多个文件:多次使用--from-file参数指定不同文件,可分别自定义键名。

示例:

复制代码
echo "db_host=mysql" > db.conf
echo "cache_host=redis" > cache.conf
kubectl create configmap multi-file-config \
  --from-file=database=db.conf \
  --from-file=cache=cache.conf
  • 目录:指定目录路径,Kubernetes 会将目录下所有文件(不含子目录)作为键值对添加到 ConfigMap 中。

示例:

复制代码
# 创建目录并添加文件
mkdir config-dir
echo "port=8080" > config-dir/server.conf
echo "timeout=30s" > config-dir/timeout.conf
# 从目录创建ConfigMap
kubectl create configmap dir-config --from-file=config-dir/
3. 使用 --from-env-file 创建

--from-env-file用于从环境变量文件(env 文件)中读取键值对创建 ConfigMap,文件中每一行需符合键=值格式,空行和注释行(#开头)会被忽略。

示例:

复制代码
# 准备env文件
cat > app.env << EOF
# 这是注释行
log_level=info
max_connections=100
timeout=30s
EOF
# 从env文件创建ConfigMap
kubectl create configmap env-file-config --from-env-file=app.env
4. 通过 YAML 配置文件创建

通过 YAML 定义复杂 ConfigMap,支持字面量和文件式数据混合定义:

复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-full-config
  namespace: default
data:
  # 字面量键值对
  environment: "production"
  # 文件式数据
  app.properties: |
    log_level=warn
    server_port=8080
  db.conf: "db_host=mysql\n db_port=3306"

通过kubectl apply -f configmap.yaml创建。

在 Pod 中使用 ConfigMap

ConfigMap 创建后,可通过环境变量、命令行参数或文件挂载三种方式在 Pod 中引用。

1. 作为环境变量使用
复制代码
apiVersion: v1
kind: Pod
metadata:
  name: configmap-env-demo
spec:
  containers:
  - name: demo-container
    image: nginx
    env:
    - name: LOG_LEVEL  # 环境变量名
      valueFrom:
        configMapKeyRef:
          name: app-config  # ConfigMap名称
          key: log_level   # 引用的键
    envFrom:
    - configMapRef:
        name: app-full-config  # 注入所有键值
2. 作为命令行参数使用
复制代码
spec:
  containers:
  - name: demo-container
    image: busybox
    env:
    - name: MAX_CONN
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: max_connections
    command: ["/bin/sh", "-c", "echo 'Max connections: $MAX_CONN'"]
3. 作为文件挂载使用
复制代码
spec:
  containers:
  - name: demo-container
    image: nginx
    volumeMounts:
    - name: config-volume  # 挂载卷名称
      mountPath: /etc/config  # 容器内挂载路径
  volumes:
  - name: config-volume  # 与挂载卷名称一致
    configMap:
      name: app-full-config  # 关联的ConfigMap名称
      items:  # 可选:指定挂载的键
      - key: app.properties
        path: app.conf  # 重命名文件
      - key: db.conf
        path: db/db.conf  # 挂载到子目录

动态更新特性

当 ConfigMap 被修改后:

  • 文件挂载方式:容器内挂载的文件内容会在约 1 分钟内自动更新(无需重启 Pod)。

  • 环境变量 / 命令行参数方式:配置不会自动更新,需重启 Pod 或重建容器才能生效。

ConfigMap 的限制

数据大小限制

单个 ConfigMap 的总数据大小不能超过 1MB,超过此限制会导致创建失败。

敏感数据风险

ConfigMap 中的数据以明文形式存储 在 etcd 中,且可通过kubectl get configmap直接查看,严禁存储敏感数据

命名空间隔离

ConfigMap 具有命名空间隔离性,仅能被同一命名空间内的 Pod 引用。

动态更新局限

环境变量和命令行参数引用的 ConfigMap 无法动态更新,必须重启 Pod 才能生效。

不可变性风险

默认情况下,ConfigMap 可被随时修改,建议通过设置immutable: true将其标记为不可变:

复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: immutable-config
immutable: true  # 启用不可变性
data:
  key: "value"

加密数据管理:Secret

对于密码、API 密钥、证书等敏感数据,Kubernetes 提供 Secret 资源进行加密管理。

Secret 的定义与核心作用

Secret 是 Kubernetes 中用于存储敏感配置数据的 API 对象,与 ConfigMap 结构类似,但增加了加密相关的安全特性。

Secret 的类型

类型 用途
Opaque 通用敏感数据(默认类型),存储任意键值对,值需经 base64 编码。
kubernetes.io/service-account-token 服务账户令牌,用于 Pod 与 API Server 的身份认证。
kubernetes.io/dockerconfigjson 存储 Docker 仓库的 JSON 格式认证配置,用于拉取私有镜像。
kubernetes.io/tls 存储 TLS 证书和私钥,键固定为tls.crt和tls.key。

创建 Secret

1. 从字面量创建
复制代码
kubectl create secret generic db-creds \
  --from-literal=username=admin \
  --from-literal=password=P@ssw0rd123
2. 从文件创建
复制代码
# 准备敏感文件
echo -n "admin" > username.txt
echo -n "P@ssw0rd123" > password.txt
kubectl create secret generic db-creds-file \
  --from-file=username=username.txt \
  --from-file=password=password.txt
3. 通过 YAML 创建

需先对敏感数据进行 base64 编码:

复制代码
echo -n "admin" | base64  # 输出:YWRtaW4=
echo -n "P@ssw0rd123" | base64  # 输出:UEBzc3cwcmQxMjM=

创建 YAML 文件:

复制代码
apiVersion: v1
kind: Secret
metadata:
  name: db-creds-yaml
type: Opaque
data:
  username: YWRtaW4=
  password: UEBzc3cwcmQxMjM=

在 Pod 中使用 Secret

1. 作为环境变量
复制代码
spec:
  containers:
  - name: app
    image: app-image
    env:
    - name: DB_USER
      valueFrom:
        secretKeyRef:
          name: db-creds
          key: username
    - name: DB_PASS
      valueFrom:
        secretKeyRef:
          name: db-creds
          key: password
2. 作为文件挂载
复制代码
spec:
  containers:
  - name: app
    image: app-image
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secrets
      readOnly: true  # 敏感文件建议设为只读
  volumes:
  - name: secret-volume
    secret:
      secretName: db-creds
3. 作为镜像拉取密钥
复制代码
spec:
  imagePullSecrets:
  - name: docker-creds  # 存储Docker认证信息的Secret名称
  containers:
  - name: private-app
    image: my-private-repo/app:v1

Secret 的安全性增强

1. 静态加密(EncryptionConfiguration)

启用 etcd 对 Secret 数据的加密存储:

复制代码
# encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources: ["secrets"]
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded-32-byte-key>
      - identity: {}
2. RBAC 权限控制

通过 RBAC 策略限制 Secret 的访问权限:

复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]
3. 不可变性设置

通过immutable: true防止 Secret 被意外修改:

复制代码
apiVersion: v1
kind: Secret
metadata:
  name: immutable-secret
immutable: true
data:
  key: "value"

总结

ConfigMap 和 Secret 分别解决了非敏感配置和敏感数据的管理问题。在实际应用中,需根据数据敏感性选择合适的资源类型,注意两者的限制,并结合不可变性、RBAC 权限、加密存储等特性,构建安全可靠的配置管理体系。

相关推荐
draymond71074 小时前
Dockerfile详解
运维·docker·容器
慌糖6 小时前
以微服务为基础搭建一套脚手架开始前的介绍
微服务·云原生·架构
ID_云泽6 小时前
多架构镜像整合全攻略:在Docker中实现单一镜像支持同时支持amd64和arm64架构
docker·容器·架构
kfepiza7 小时前
Dockerfile详解 笔记250801
docker·容器
37手游后端团队7 小时前
AI生成回流文案在《凡人修仙传:人界篇》应用
人工智能·后端·云原生
阿里云云原生8 小时前
LoongCollector:构建智能时代的数据采集新范式
云原生
云和数据.ChenGuang8 小时前
k8s-master03加入集群失败解决方法之一
java·容器·kubernetes
行星0088 小时前
centos7安装Docker
docker·容器
曾经的三心草9 小时前
微服务的编程测评系统8-题库管理-竞赛管理
微服务·云原生·架构