6.1 ConfigMap与Secret:把配置从镜像里解耦


6.1 ConfigMap 与 Secret:把配置从镜像里解耦

ConfigMap 存放非敏感的配置数据(键值对或整份文件),Secret 存放敏感数据(密码、令牌、证书),两者都是独立的资源对象,可被 Pod 以环境变量或文件挂载两种方式引用。配置外置让同一镜像跑遍所有环境,敏感数据脱离镜像与声明进入受控通道。

1.2 节的 YAML 里有一行 APP_MODE=production,那是配置的雏形,也是最后残留的"环境信息写进声明"的痕迹。本节把它彻底外置:普通配置进 ConfigMap,敏感数据进 Secret,再以两条注入路径送进容器。这一步做完,orders-api 的声明才真正做到"一套声明、环境无关"。

把配置从镜像里搬出来

先看 ConfigMap 的两种内容形态——键值与文件,实践中文件形态更常见(应用天然读配置文件):

apiVersion: v1 kind: ConfigMap metadata: name: orders-config namespace: production data: APP_MODE: "production" # 键值形态:适合少量开关 LOG_LEVEL: "info" app.properties: | # 文件形态:整份配置文件 timeout_ms=3000 max_retry=3 feature.new_checkout=true

Secret 的写法结构相同,data 里的值要 Base64 编码;更省事的是 stringData 字段,写明文、提交时自动编码:

# 用命令行快速创建一个凭据型 Secret(明文输入,自动编码入库) kubectl create secret generic db-creds -n production \ --from-literal=username=orders_app \ --from-literal=password='S3cure!Pass' # secret/db-creds created kubectl get secret db-creds -n production -o jsonpath='{.data.password}' | base64 -d # S3cure!Pass # 取回可见:Base64 只是编码,不是加密

最后一行输出就是本节最重要的安全认知:任何有读取权限的人都能瞬间还原 Secret。Secret 与 ConfigMap 的区别不是保密强度,而是语义与管控通道——它让敏感数据可以被单独授权(RBAC 按 resource 细分)、单独审计、单独轮换。真正的防线是三道:RBAC 把 read 权限收到最小集合;etcd 开启静态加密让账本落盘密文;传输全程 TLS。把 Secret 当保险箱,不如把它当成"贴了封条的信封"。

两条注入路径的取舍

配置写好了,怎么进容器?两条路径各有脾气:

spec: template: spec: containers: - name: orders-api image: orders-api:1.4.2 envFrom: - configMapRef: name: orders-config # 路径一:整包注入为环境变量 env: - name: DB_PASSWORD valueFrom: secretKeyRef: # 单键注入:凭据走 Secret name: db-creds key: password volumeMounts: - name: config-vol # 路径二:挂载为配置文件 mountPath: /etc/orders readOnly: true volumes: - name: config-vol configMap: name: orders-config # app.properties 会出现在 /etc/orders/

两条路径的分水岭是生效时机:环境变量在容器启动时一次性注入,此后改 ConfigMap 不会影响已运行的容器;文件挂载则由 kubelet 周期性刷新(约一分钟内),应用重读文件即可拿到新配置(是否重读是应用自己的事)。因此:启动期就要用的简单变量走环境变量;希望不重启就能调整的走文件挂载,且应用要支持配置热加载。

对比项 环境变量注入 文件挂载注入
生效方式 容器启动时一次性 kubelet 滚动刷新(约一分钟)
适合内容 少量开关、地址类 整份配置文件、结构化内容
更新代价 需重启或滚动替换 应用重读文件即可
排查方式 exec 进容器 env 查看 直接 cat 挂载文件

⚠️ 常见坑:环境变量注入后改了 ConfigMap,以为应用会自动感知。实际毫无动静,还常常怀疑"集群没更新"。判定规则就一条:环境变量不热更,文件挂载才滚动。需要立即生效的场景,用滚动重启(改一个无害注解触发换防)配合文件挂载。

案例:一次数据库地址切换的全流程

背景:数据库要迁移到新实例,地址与凭据都要换,应用不允许长时间停机。

操作

# 第一步:更新 ConfigMap 中的地址(走文件挂载的那个键) kubectl edit configmap orders-config -n production # data.app.properties 中 timeout 与地址更新 # 第二步:确认新值已经刷新到容器内(约一分钟后) kubectl exec -n production deploy/orders-api -- cat /etc/orders/app.properties # timeout_ms=3000 # db_host=db-new.internal # 新值已在文件里 # 第三步:凭据属环境变量路径,必须滚动替换才能生效 kubectl rollout restart deployment/orders-api -n production # deployment.apps/orders-api restarted kubectl rollout status deployment/orders-api -n production # deployment "orders-api" successfully rolled out

结果:配置文件部分一分钟内自动生效;凭据部分通过 4.2 节的滚动换防逐副本更新,全程服务不中断。

解读:两类配置走了两条生效路径,恰好演示了取舍表的全部内容。值得点名的还有声明结构:凭据轮换只动了 Secret 与滚动动作,镜像与 Deployment 模板没变——配置对象的独立性让"换密码"不再是一次发布。另外,新凭据应当先在 Secret 里就位、再滚动应用,顺序反了会出现新 Pod 读不到键的空窗。

变式:多环境同构部署时,为每个空间各建一套同名 ConfigMap 与 Secret,Deployment 声明保持一份零改动(引用按空间就近解析);更严格的密钥治理会接外部密钥管理服务,让 Secret 只做集群内的投递通道。TLS 证书场景则用 tls 类型的 Secret,5.2 节 Ingress 的 secretName 引用的正是它。

💡 关键直觉:ConfigMap 与 Secret 也是资源对象,同样可以被版本库管理、被 Watch 广播、被 RBAC 管控——配置变更从此有了与代码变更同等的可追溯性。

本节要点回顾

  • 两种内容形态:键值适合开关,文件形态适合整份配置;stringData 免去手动编码;
  • Secret 是编码不是加密:防线在 RBAC、etcd 静态加密与传输 TLS 三道,语义管控才是它的本分;
  • 注入路径看生效时机:环境变量启动期一次定终身,文件挂载一分钟级滚动刷新;
  • 凭据轮换走滚动:改 Secret 后滚动重启让环境变量重新注入,顺序先数据后滚动;
  • 配置即资源:外置的配置可版本化、可审计、可按环境复制,这是声明式体系的完整闭环。

配置的补给线通了,下一节铺设存储的补给线:从随 Pod 消亡的临时卷,到"声明需求、系统供给"的 PVC 申领制度——4.3 节 StatefulSet 卷模板里的伏笔在此兑现。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U