LabHub
学习 学习路径 课程

CKAD — Kubernetes 应用开发者

用 ConfigMap 与 Secret 注入配置

在 LabHub 中继续学习

目标

区分并使用让同一镜像在不同环境中以不同方式运行的四种注入路径(全部环境变量、单个环境变量、文件卷、subPath 文件),并能在字段层面处理 Secret 与 ConfigMap 的差异。

为什么重要

配置注入在实际工作中最容易引发事故的问题通常是“更新是否会生效”。通过环境变量注入的值只在进程启动时读取一次,因此即使修改 ConfigMap,在重新创建 Pod 之前也绝不会改变。通过卷注入的文件会由 kubelet 定期更新,但使用 subPath 挂载的单个文件是例外,不会更新。如果不了解这三种行为差异,就会把时间全耗在“配置明明改了,为什么没有生效”上。

defaultMode 也常在实际工作中出问题。挂载 Secret 时默认权限为 0644,同一节点上的其他进程也可能读取。对于 TLS 密钥等敏感文件,应将权限收紧到 0400。在 YAML 中,不加引号写 0400 会按八进制解释;但如果只写 400,就会按十进制 400 读取,最终得到不正确的权限。

immutable: true 不是安全功能,而是性能功能。为了监视已挂载 ConfigMap/Secret 的变化,kubelet 会不断访问 API 服务器;设为 immutable 后便会停止监视。在数千个 Pod 的规模下,可以显著降低 apiserver 负载。

步骤

  1. 创建命名空间 ckad-config,并在其中通过字面量创建 ConfigMap app-config。键值为 APP_MODE=productionLOG_LEVEL=info
  2. 创建目录 /root/ckad-config,在文件 /root/ckad-config/app.properties 中写入一行 timeout=30,然后用该文件创建 ConfigMap app-props(键名为 app.properties)。
  3. 创建 Pod cfg-env。镜像为 busybox:1.36command: ["/bin/sh","-c","sleep 3600"]。通过 envFrom 注入整个 app-config,并另外在 env 中以 LOG 为变量名引用 app-configLOG_LEVEL 键。
  4. 创建 Secret db-secret。类型为 generic(Opaque),键值为 DB_USER=appuserDB_PASSWORD=s3cr3t
  5. 创建 Pod secret-consumer。镜像为 busybox:1.36command: ["/bin/sh","-c","sleep 3600"]。让环境变量 DB_PASSWORDdb-secretDB_PASSWORD 键获取值;同时将同一个 Secret 作为卷 dbcreds 挂载到 /etc/db,并将 defaultMode 设为 0400
  6. 创建 Pod cfg-vol。镜像为 nginx:1.27。将 ConfigMap app-props 作为卷 props 挂载两次:一次把整个目录挂载到 /etc/app,另一次使用 subPath: app.properties 挂载到 /opt/app/app.properties
  7. 创建 ConfigMap feature-flags,键为 NEW_UI=on,并设置 immutable: true。创建 Pod optional-cm(镜像 busybox:1.36command: ["/bin/sh","-c","sleep 3600"]),引用不存在的 ConfigMap maybe-config 作为 envFrom,并设置 optional: true
  8. 创建 Deployment web-config。副本数 2,标签 app=web-config,镜像 nginx:1.27。在 envFrom 中同时加入 app-config(configMapRef)和 db-secret(secretRef),并将 ConfigMap app-props 作为卷 props 挂载到 /etc/app

参考

通过字面量创建 ConfigMap

创建命名空间 ckad-config,并在其中通过字面量创建 ConfigMap app-config。键值为 APP_MODE=productionLOG_LEVEL=info

可以为 kubectl create configmap 多次提供 --from-literal=키=값。先创建命名空间,并且不要漏掉 -n

从文件创建 ConfigMap

创建目录 /root/ckad-config,在文件 /root/ckad-config/app.properties 中写入一行 timeout=30,然后用该文件创建 ConfigMap app-props(键名为 app.properties)。

使用 --from-file=경로 时,文件名会成为键,文件的全部内容会成为值。如需更改键名,请使用 --from-file=키이름=경로 形式。

同时使用 envFrom 和 configMapKeyRef

创建 Pod cfg-env。镜像为 busybox:1.36command: ["/bin/sh","-c","sleep 3600"]。通过 envFrom 注入整个 app-config,并另外在 env 中以 LOG 为变量名引用 app-configLOG_LEVEL 键。

envFrom[].configMapRef 会将所有键原样作为变量名,而 env[].valueFrom.configMapKeyRef 会选取一个键,并以不同的名称注入。两种方式可以在同一个容器中同时使用。

创建 Secret 并检查编码

创建 Secret db-secret。类型为 generic(Opaque),键值为 DB_USER=appuserDB_PASSWORD=s3cr3t

kubectl create secret generic--from-literal 值会自动进行 base64 编码。直接编写 YAML 时,如需填入明文,请不要使用 data,而应使用 stringData

同时将 Secret 注入环境变量和文件

创建 Pod secret-consumer。镜像为 busybox:1.36command: ["/bin/sh","-c","sleep 3600"]。让环境变量 DB_PASSWORDdb-secretDB_PASSWORD 键获取值;同时将同一个 Secret 作为卷 dbcreds 挂载到 /etc/db,并将 defaultMode 设为 0400

环境变量使用 env[].valueFrom.secretKeyRef,文件使用 volumes[].secret.secretName 加卷挂载。文件权限通过卷一侧的 defaultMode 指定;在 YAML 中很容易漏掉八进制数前面的 0,请注意。

ConfigMap 卷与 subPath

创建 Pod cfg-vol。镜像为 nginx:1.27。将 ConfigMap app-props 作为卷 props 挂载两次:一次把整个目录挂载到 /etc/app,另一次使用 subPath: app.properties 挂载到 /opt/app/app.properties

挂载整个目录会遮蔽该目录原有的内容。如果只想覆盖一个文件,请在 volumeMounts[].subPath 中填写键名。通过 subPath 挂载的文件不会随 ConfigMap 的修改而更新。

optional 引用与 immutable ConfigMap

创建 ConfigMap feature-flags,键为 NEW_UI=on,并设置 immutable: true。创建 Pod optional-cm(镜像 busybox:1.36command: ["/bin/sh","-c","sleep 3600"]),引用不存在的 ConfigMap maybe-config 作为 envFrom,并设置 optional: true

immutable: true 是 ConfigMap 规范的顶层字段(不在数据内部)。若要让 Pod 在引用不存在的 ConfigMap 时仍能启动,请在引用一侧设置 optional: true

综合:在 Deployment 中同时使用三种配置

创建 Deployment web-config。副本数 2,标签 app=web-config,镜像 nginx:1.27。在 envFrom 中同时加入 app-config(configMapRef)和 db-secret(secretRef),并将 ConfigMap app-props 作为卷 props 挂载到 /etc/app

在一个 Deployment 中使用前面创建的两个 ConfigMap 和一个 Secret。envFrom 数组可以并列放入 configMapRefsecretRef。也不要忘记卷挂载。