ToolkitX
知识库工具箱

ConfigMap 与 Secret

配置管理、环境变量、敏感数据

20min·进阶

01. ConfigMap——配置管理

把配置硬编码在镜像里是个坏习惯——换个环境就要重新打镜像。ConfigMap 把配置从镜像里抽出来,运行时以环境变量或文件形式注入 Pod。 ConfigMap 存键值对,键是配置项名,值是配置内容。可以存简单的 key=value,也可以存整个配置文件(Nginx 配置、Java properties 等)。大小限制 1MB。 使用方式: 1. 环境变量——把 ConfigMap 的键值对注入为容器的环境变量 2. 挂载为文件——把 ConfigMap 挂载到容器里某个目录,每个键是一个文件 3. 命令行参数——通过 env 注入后再传给命令 ConfigMap 更新后,环境变量的方式不会自动更新(Pod 要重建)。挂载文件的方式会延迟自动更新(kubelet 定期同步)。
bash
# 从字面值创建
kubectl create configmap app-config \
  --from-literal=DB_HOST=db-service \
  --from-literal=DB_PORT=5432

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

# YAML 方式
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DB_HOST: "db-service"
  DB_PORT: "5432"
  app.properties: |
    server.port=8080
    logging.level=INFO
ConfigMap 里可以存一个完整的配置文件——用竖线加缩进(YAML 多行字符串语法),然后把整个 ConfigMap 挂载为文件。

02. Secret——敏感数据管理

Secret 跟 ConfigMap 类似,但专门存敏感信息——密码、Token、证书、SSH Key。数据以 Base64 编码存储(注意不是加密!只是编码,任何人都能解码)。 Secret 类型: Opaque——通用类型,就是你存的任意键值对 kubernetes.io/tls——TLS 证书和私钥 kubernetes.io/dockerconfigjson——Docker registry 的登录凭证 kubernetes.io/basic-auth——用户名密码 创建后使用方法跟 ConfigMap 一样:环境变量注入或文件挂载。Secret 在 etcd 里默认不加密,生产环境建议开 etcd 加密或者用外部密钥管理服务(Vault、Sealed Secrets)。
bash
# 创建 Secret
kubectl create secret generic db-secret \
  --from-literal=username=admin \
  --from-literal=password='MyP@ssw0rd'

# TLS Secret
kubectl create secret tls my-tls \
  --cert=cert.pem --key=key.pem

# YAML 方式
data:
  username: YWRtaW4=    # base64 编码的 admin
  password: TXlQQHNzdzByZA==

# 使用 Secret(Pod YAML 里)
env:
- name: DB_PASSWORD
  valueFrom:
    secretKeyRef:
      name: db-secret
      key: password
Secret 的 Base64 只是编码不是加密!任何能 kubectl get secret 的人都能解码。要真正的加密用 Sealed Secrets 或 Vault。

03. ConfigMap 和 Secret 的更新机制

ConfigMap 和 Secret 更新后,Pod 里的值不会立刻生效: 环境变量方式:只有在 Pod 启动时读取。改了 ConfigMap,Pod 的环境变量还是旧值。必须重建 Pod。 文件挂载方式:kubelet 定期同步(默认约 60 秒),会把最新的值更新到容器里的文件。但应用需要自己检测文件变化并重载配置(如 nginx -s reload)。 如果应用不支持热重载文件,更新配置的麻烦流程就是:改 ConfigMap → 重启 Pod。 还有一种方式:用 deployment 的 annotation 记录 ConfigMap 的 hash,hash 变了自动触发滚动更新。这是比较优雅的自动更新方案。
yaml
# 滚动更新时触发 Pod 重建
# Deployment YAML 的 template.metadata.annotations 里加
annotations:
  checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}

04. 环境变量注入与 Pod 配置最佳实践

给容器注入配置的最佳实践: 1. 非敏感的简单配置(数据库地址、端口)→ ConfigMap 挂为环境变量 2. 配置文件(nginx.conf、Java properties)→ ConfigMap 挂载为文件 3. 密码、Token、证书 → Secret 挂载为文件(比环境变量更安全) 4. 配置验证 → 在容器启动脚本里检查必需的环境变量是否都设了 5. 合理使用默认值——没设时有回退方案,不崩 环境变量的优先级(从高到低):容器直接 env > Secret envFrom > ConfigMap envFrom。如果有同名环境变量,高优先级的覆盖低优先级的。
yaml
# Pod——同时使用 ConfigMap 和 Secret
spec:
  containers:
  - name: app
    image: myapp:latest
    envFrom:
    - configMapRef:
        name: app-config
    - secretRef:
        name: db-secret
    env:
    - name: NODE_ENV
      value: "production"
    volumeMounts:
    - name: nginx-config
      mountPath: /etc/nginx/conf.d
  volumes:
  - name: nginx-config
    configMap:
      name: nginx-config
envFrom 会把这个 ConfigMap 或 Secret 的所有键值对注入为环境变量。一行搞定,比逐个 env valueFrom 方便。

05. Helm Chart——K8s 的包管理器

如果每个环境都手写一套 YAML 文件,维护起来会很痛苦。Helm 是 K8s 的包管理器——把一组 K8s YAML 模板化,用 values.yaml 来定制每个环境的配置。 Helm Chart 的结构: Chart.yaml——chart 的元数据(名称、版本、依赖)。 values.yaml——默认的配置值。 templates/——K8s 资源模板(Deployment、Service、ConfigMap 等),用 Go 模板语法嵌入式地引用 values。 安装 chart:helm install my-app ./chart -f values-prod.yaml。-f 可以覆盖默认的 values。 升级:helm upgrade my-app ./chart --set image.tag=v2.0。用 --set 快速覆盖单个值。 Helm 的模板函数库很丰富:default(兜底值)、quote(加引号)、indent(缩进)、toYaml(转 YAML)。在 templates 里用 .Values.xxx 引用 values.yaml 的值。
yaml
# Chart.yaml
apiVersion: v2
name: my-app
version: 1.0.0
appVersion: "2.0.0"

# values.yaml
replicas: 3
image:
  repository: myapp
  tag: latest
service:
  port: 80
  type: ClusterIP
resources:
  limits:
    cpu: 500m
    memory: 256Mi

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
spec:
  replicas: {{ .Values.replicas }}
  template:
    spec:
      containers:
      - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        resources:
          {{- toYaml .Values.resources | nindent 10 }}
Helm 的 lookup 函数可以从已存在的 K8s 资源里取信息(如共享的 Secret),避免在 values.yaml 里重复写相同配置。

知识测验

1/5正确 0

ConfigMap 和 Secret 的主要区别?

下一节

部署策略

下一节