K8s 环境变量 全维度详解
1. 基础认知
1.1. 核心作用
环境变量是向容器注入配置、元数据、标识信息的标准方式,容器内所有进程均可读取,解耦镜像与运行配置,实现镜像一次构建、多环境运行。
1.2. 生效范围
- 定义在
spec.containers[].env/envFrom,容器级别配置; - 同 Pod 不同容器可配置不同环境变量,互不干扰;
- 环境变量在容器启动时一次性注入,运行期间默认不会动态更新。
1.3. 两大配置方式
env:逐条定义单个环境变量,灵活精准;envFrom:批量导入 ConfigMap / Secret 中所有键值,适合大批量配置。
2. 环境变量五大来源(分类+示例)
K8s 环境变量共分为 5 种来源,从简单到高阶依次说明,包含完整 YAML、语法规则、使用场景。
2.1. 直接字面量(value)
最基础用法,硬编码键值对,静态固定值。
2.1.1. 语法
env:
- name: 变量名 # 容器内读取的变量名,大小写敏感
value: 变量值 # 纯字符串,数字/布尔也写为字符串
2.1.2. 完整示例
apiVersion: v1
kind: Pod
metadata:
name: env-value-demo
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo $APP_NAME $APP_ENV"]
env:
- name: APP_NAME
value: "order-service"
- name: APP_ENV
value: "production"
2.1.3. 特点
- 优点:简单直观;
- 缺点:配置硬编码,改值需要重建 Pod,不适合敏感配置、大量配置。
2.2. 引用 Pod/节点元数据(fieldRef)
从 K8s 资源对象中动态提取元数据注入环境变量,比如 Pod 名称、IP、命名空间、节点名等。
底层依赖 valueFrom.fieldRef。
2.2.1. 常用字段(生产高频)
| fieldPath | 说明 |
| metadata.name | Pod 名称 |
| metadata.namespace | Pod 所在命名空间 |
| metadata.uid | Pod 唯一ID |
| status.podIP | Pod 内网IP |
| status.hostIP | 宿主机节点IP |
| spec.nodeName | 节点名称 |
2.2.2. 示例
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo PodName: $POD_NAME, PodIP: $POD_IP"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
2.2.3. 适用场景
- 应用日志打印 Pod 标识、IP、节点信息,方便排查;
- 服务自注册时上报自身实例信息。
2.3. 引用容器资源配置(resourceFieldRef)
动态注入当前容器的 CPU/内存 requests、limits 配置,底层 valueFrom.resourceFieldRef。
2.3.1. 支持资源
limits.cpu/requests.cpulimits.memory/requests.memory- 高阶:
hugepages-2Mi大页内存等
2.3.2. 示例
containers:
- name: app
image: busybox
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
command: ["sh", "-c", "echo CPU_LIMIT: $CPU_LIMIT, MEM_REQ: $MEM_REQ"]
env:
- name: CPU_LIMIT
valueFrom:
resourceFieldRef:
containerName: app # 当前容器名,多容器Pod必须指定
resource: limits.cpu
- name: MEM_REQ
valueFrom:
resourceFieldRef:
containerName: app
resource: requests.memory
2.3.3. 特点
- 单位保留 K8s 原生单位(m、Mi、Gi);
- 适合应用动态感知自身资源配额,做内部限流、堆内存自适应(如 Java JVM 参数)。
2.4. 引用 ConfigMap 配置
将 ConfigMap 中的单个 Key 映射为环境变量,区分「单键引用」和「全量导入」。
2.4.1. 前置:创建 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: default
data:
db.host: 10.0.0.10
db.port: 3306
log.level: info
2.4.2. 方式1:单独引用某个 Key
精准选取指定配置项,推荐精细化使用。
spec:
containers:
- name: app
image: busybox
env:
# 引用 configMap 单个键
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config # ConfigMap 名称
key: db.host # ConfigMap 内的 key
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: app-config
key: db.port
2.4.3. 方式2:批量导入所有键
一次性把 ConfigMap 所有 key=value 转为环境变量,适合配置项较多场景。
spec:
containers:
- name: app
image: busybox
# 批量导入
envFrom:
- configMapRef:
name: app-config
容器内变量名 = ConfigMap 的 key,示例中变量名为 db.host。
2.5. 引用 Secret 密钥
用法和 ConfigMap 完全一致,专门存放密码、密钥、令牌等敏感数据。
Secret 数据底层会 Base64 编码,K8s 注入容器时自动解码,容器内明文读取。
2.5.1. 前置:创建 Secret
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
db.username: YWRtaW4= # base64 编码:admin
db.password: MTIzNDU2 # base64 编码:123456
2.5.2. 方式1:单键引用
containers:
- name: app
image: busybox
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: app-secret
key: db.username
- name: DB_PWD
valueFrom:
secretKeyRef:
name: app-secret
key: db.password
2.5.3. 方式2:批量导入(envFrom)
containers:
- name: app
image: busybox
envFrom:
- secretRef:
name: app-secret
3. 关键高级特性
3.1. 可选引用(optional)
默认情况下:如果引用的 ConfigMap/Secret 不存在、或指定 Key 缺失,Pod 会启动失败。
通过 optional: true 设置为可选,缺失时不报错、该变量不注入。
3.1.1. 示例(可选引用)
env:
- name: EXT_CONFIG
valueFrom:
configMapKeyRef:
name: not-exist-cm
key: ext.key
optional: true # 配置不存在也正常启动
3.2. 环境变量相互引用 / 变量嵌套
K8s 支持后定义的变量引用前面已定义的变量,实现拼接、组合。
规则:按 YAML 书写顺序解析,只能向前引用,不能向后。
3.2.1. 示例:变量拼接
env:
- name: DB_HOST
value: "10.0.0.10"
- name: DB_PORT
value: "3306"
# 引用上面两个变量拼接连接串
- name: DB_URL
value: "mysql://$(DB_HOST):$(DB_PORT)"
3.3. 变量名规范
- 变量名由字母、数字、下划线组成,不能以数字开头;
- 不建议使用
.、-等特殊字符(部分编程语言不兼容); - 系统预留变量(如
PATH、HOME)谨慎覆盖。
3.4. 环境变量更新机制(重点坑点)
- 静态注入特性
env/envFrom方式注入的变量,仅在容器启动时加载一次。
- 修改 ConfigMap / Secret → 已运行的 Pod 环境变量不会自动更新;
- 必须重建 Pod 或滚动更新 Deployment 才能生效。
- 补充:ConfigMap/Secret 挂载为文件时
以volume方式挂载的配置文件,K8s 会定时热更新(默认几秒~一分钟),和环境变量行为不同。
4. 配置优先级(变量冲突覆盖规则)
当多个来源定义同名环境变量时,遵循固定优先级(从高到低):
env字面量(value)env各类valueFrom(fieldRef / configMapKeyRef / secretKeyRef)envFrom批量导入(configMapRef / secretRef)
总结:逐条 env 优先级 > 批量 envFrom;前面定义的变量会被后面同名变量覆盖。
示例:同名变量冲突
env:
# 优先级低
- name: APP_ENV
value: "test"
# 优先级高,覆盖上面的值
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: app-config
key: env
5. env 与 envFrom 选型 & 最佳实践
5.1. 选型建议
| 场景 | 推荐方案 |
| 少量固定配置、简单标识 | env + value 字面量 |
| 注入 Pod/节点元数据 | env + fieldRef |
| 注入资源配额 | env + resourceFieldRef |
| 少量配置项、需要精细化管控 | env + configMapKeyRef / secretKeyRef |
| 大量配置项、整体导入 | envFrom + configMapRef / secretRef |
| 敏感密码、令牌 | 必须使用 Secret,禁止明文 value |
5.2. 生产规范
- 禁止明文存放敏感信息账号、密码、密钥、Token 一律存入 Secret,不用
value硬编码。 - 区分环境
开发/测试/生产使用不同 ConfigMap/Secret,通过名称区分,不修改 Pod 模板。 - 优先单键引用,少用 envFrom 全量导入
全量导入会把所有 Key 都注入容器,容易泄露多余配置,权限最小化原则推荐按需引用 Key。 - 配合 optional 做容错非核心配置开启
optional: true,避免因配置缺失导致 Pod 大面积启动失败。 - 动态配置场景补充
如需配置热更新(不重启 Pod):
- 方案1:ConfigMap/Secret 挂载为 Volume,应用监听文件变化;
- 方案2:对接 Nacos/Apollo 等配置中心。
6. 常见问题 & 排障
问题1:Pod 启动失败,提示 configmap/secret not found
原因:引用的 ConfigMap/Secret 不存在,或 Key 名称写错。
解决:
- 检查资源是否存在:
kubectl get configmap/secret - 核对
name和key拼写 - 非核心配置添加
optional: true
问题2:修改 ConfigMap 后,容器内环境变量不变
原因:环境变量启动时一次性注入,不支持热更新。
解决:重建 Pod / 触发 Deployment 滚动更新。
问题3:Secret 密码在容器内读取乱码/为空
原因:Secret 的 data 字段必须是 Base64 编码字符串;
解决:
# 快速生成 base64 编码
echo -n "你的密码" | base64
问题4:变量引用不生效($(XXX) 原样输出)
原因:容器启动命令不是 shell 环境,无法解析变量语法。
解决:使用 shell 包装命令:
command: ["sh", "-c", "echo $(DB_HOST)"]
7. 综合完整示例(整合所有用法)
apiVersion: v1
kind: Pod
metadata:
name: env-all-demo
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo 所有环境变量; env"]
resources:
requests:
cpu: 100m
memory: 128Mi
# 1. 逐条环境变量
env:
# 字面量
- name: APP_NAME
value: "payment"
# Pod 元数据
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
# 资源配置
- name: MEM_LIMIT
valueFrom:
resourceFieldRef:
containerName: app
resource: limits.memory
# 引用 ConfigMap 单键
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: log.level
optional: true
# 引用 Secret 单键
- name: DB_PASS
valueFrom:
secretKeyRef:
name: app-secret
key: db.password
# 变量拼接
- name: FULL_URL
value: "service-$(APP_NAME).svc.cluster.local"
# 2. 批量导入(全量 ConfigMap + Secret)
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secret
8. 高频面试题
- K8s 环境变量有哪几种来源?
答:字面量、Pod/节点元数据(fieldRef)、资源配额(resourceFieldRef)、ConfigMap、Secret。 - 修改 ConfigMap 后,Pod 内环境变量为什么不更新?
答:环境变量在容器启动时一次性注入,运行期不会热更新;需重建 Pod 生效。挂载为文件形式会自动更新。 - **引用不存在的 ConfigMap/Secret 会发生什么?如何容错?**答:默认 Pod 启动失败;添加
optional: true可实现容错,配置缺失时变量不注入、Pod 正常启动。 - env 和 envFrom 区别、优先级?
答:env 逐条定义,envFrom 批量导入;env 优先级高于 envFrom,同名变量会被覆盖。 - Secret 存密码,容器内是明文吗?安全吗?
答:Secret 底层 Base64 编码(非加密),注入容器后自动解码为明文;适合集群内基础保密,高敏感数据建议搭配外部密钥管理服务。
关联文档
- Pod 生命周期钩子(Hook)完整详解 — Pod 生命周期管理
- K8s 安全上下文(SecurityContext)全解 — 容器安全配置
- K8s 高阶配置全解 — 高阶配置总览