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 权限、加密存储等特性,构建安全可靠的配置管理体系。

相关推荐
有谁看见我的剑了?1 小时前
k8s-Sidecar容器学习
学习·容器·kubernetes
傻傻虎虎3 小时前
【Docker】容器端口暴露+镜像生成实战
java·docker·容器
Don't Look Down3 小时前
Rustdesk server docker-compose 一键搭建教程
运维·docker·容器
2201_761199044 小时前
7.k8s四层代理service
云原生·容器·kubernetes
Sweety丶╮7945 小时前
【Ansible】将文件部署到受管主机知识点
云原生·ansible
清风笑烟语9 小时前
Ubuntu 24.04 搭建k8s 1.33.4
linux·ubuntu·kubernetes
能不能别报错10 小时前
K8s学习笔记(二):Pod
笔记·学习·kubernetes
羑悻的小杀马特12 小时前
Docker 容器化部署核心实战:从镜像仓库管理、容器多参数运行到 Nginx 服务配置与正反向代理原理解析
nginx·docker·容器·镜像仓库
en-route13 小时前
Kubernetes Ingress:使用 Apache APISIX 进行外部流量路由
容器·kubernetes
qsqya13 小时前
ceph/daemon安装部署
ceph·云原生·eureka