应用程序通常需要配置信息(环境变量、配置文件)以及敏感数据(数据库密码、API 密钥)。Kubernetes 提供了 ConfigMap 和 Secret 两种资源来解耦配置与镜像,让应用配置可以动态更新,同时避免敏感信息泄露。本文将详细讲解两种资源的创建方式、如何挂载到 Pod、更新策略以及安全注意事项。

一、ConfigMap:非敏感配置存储
ConfigMap 用于存储键值对或配置文件,适合环境变量、命令行参数、非加密的配置文件等。

1.1 创建 ConfigMap
方式一:命令行创建

# 从字面值创建
kubectl create configmap app-config --from-literal=db.host=mysql --from-literal=db.port=3306

# 从文件创建(文件内容作为 value,文件名作为 key)
kubectl create configmap app-config --from-file=./app.properties

# 从目录创建(目录下每个文件作为一个 key)
kubectl create configmap app-config --from-file=./configs/

方式二:YAML 文件定义

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  db.host: mysql
  db.port: "3306"
  app.properties: |
    key1=value1
    key2=value2

1.2 在 Pod 中使用 ConfigMap
作为环境变量注入

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: app
    image: busybox
    command: ["/bin/sh", "-c", "env && sleep 3600"]
    env:
    - name: DB_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: db.host
    - name: DB_PORT
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: db.port
    envFrom:
    - configMapRef:
        name: app-config   # 将 ConfigMap 中所有键值对作为环境变量
作为文件挂载(Volume)
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: config-vol
      mountPath: /etc/config
  volumes:
  - name: config-vol
    configMap:
      name: app-config

挂载后,/etc/config 目录下会生成文件:db.host、db.port、app.properties,内容即对应值。

注意:挂载的 ConfigMap 更新后,Pod 内的文件也会更新(但有些应用需要重启才能加载新配置)。

二、Secret:敏感数据存储
Secret 类似 ConfigMap,但用于存储 base64 编码的敏感数据(默认非加密,只是编码)。Kubernetes 可以对 etcd 中的 Secret 启用加密(需配置)。

2.1 创建 Secret
方式一:命令行创建

# 从字面值
kubectl create secret generic db-secret --from-literal=password=123456

# 从文件
kubectl create secret generic db-secret --from-file=./password.txt

# 创建 TLS Secret(用于 Ingress)
kubectl create secret tls example-tls --cert=path/to/tls.crt --key=path/to/tls.key

方式二:YAML 定义

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  password: MTIzNDU2   # base64 编码后的值(echo -n "123456" | base64)

2.2 在 Pod 中使用 Secret
作为环境变量注入

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: app
    image: busybox
    command: ["/bin/sh", "-c", "echo $DB_PASSWORD && sleep 3600"]
    env:
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: password

作为文件挂载(Volume)

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: secret-vol
      mountPath: /etc/secrets
      readOnly: true
  volumes:
  - name: secret-vol
    secret:
      secretName: db-secret

挂载后,Secret 中的每个 key 成为一个文件,文件内容为解码后的值(而非 base64)。默认权限 0644,可指定 defaultMode。

三、ConfigMap/Secret 更新与 Pod 热加载
通过环境变量注入的配置:Pod 启动后,修改 ConfigMap/Secret 不会影响已有的 Pod,需要重启 Pod。

通过 Volume 挂载的配置:kubelet 会定期同步(默认约 60 秒),文件内容会更新。但应用是否自动加载新配置取决于应用自身(如 Nginx 需要 reload,Spring Boot 的 @RefreshScope)。

强制重启 Pod 的方式:

手动删除并重建 Pod(对 Deployment 可通过滚动更新:kubectl rollout restart deployment )。

使用工具如 reloader(自动检测 ConfigMap 变更并触发滚动更新)。

四、SubPath 与部分挂载
如果只想挂载 ConfigMap/Secret 中的某个文件,而不是整个目录,可以使用 subPath:

volumeMounts:
- name: config-vol
  mountPath: /etc/nginx/conf.d/nginx.conf
  subPath: nginx.conf

此时卷必须只包含该文件(通常创建 ConfigMap 时只放一个 key)。

五、安全最佳实践
避免将 Secret 直接硬编码在 YAML 中:使用 kubectl create secret 或 Sealed Secrets。

启用 etcd 加密:编辑 apiserver 启动参数 --encryption-provider-config。

限制 Secret 访问权限:通过 RBAC 控制谁可以 get/delete Secret。

使用外部 Secret 管理工具:如 HashiCorp Vault、AWS Secrets Manager,通过 CSI 驱动或 sidecar 注入。

避免将 Secret 导出到日志:不要在应用代码中打印环境变量或文件内容。

六、实战:配置与密码注入示例

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-cfg
data:
  app.conf: |
    server.port=8080
    logging.level=INFO
---
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
data:
  api-key: dGVzdC1rZXk=   # 假设值 test-key
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: app
        image: myapp:latest
        env:
        - name: API_KEY
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: api-key
        volumeMounts:
        - name: cfg-vol
          mountPath: /etc/app
      volumes:
      - name: cfg-vol
        configMap:
          name: app-cfg

七、小结
ConfigMap 和 Secret 让配置与镜像分离,提高了应用的可移植性和安全性。环境变量适合简单配置,volume 挂载适合配置文件。注意 Secret 默认只编码不加密,生产环境应启用 etcd 加密或使用外部密钥管理。

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐