Kubernetes v1.34: 使用 Init 容器定义应用环境变量

Kubernetes 通常使用 ConfigMap 和 Secret 来设置环境变量, 这会引入额外的 API 调用和复杂性。例如,你需要分别管理工作负载的 Pod 和它们的配置, 同时还要确保配置和工作负载 Pod 的有序更新。

另外,你可能在使用一个供应商提供的、需要环境变量(例如许可证密钥或一次性令牌)的容器, 但你又不想对这些变量进行硬编码,或者仅仅为了完成工作而挂载卷。

如果你正面对这种情况,现在有一种新的(Alpha)方式来实现。只要你在集群中启用了 EnvFiles 特性门控, 你就可以告诉 kubelet 从一个卷中加载容器的环境变量(此卷必须是容器所属的 Pod)。 这个特性门控允许你直接从 emptyDir 卷中的文件加载环境变量,而不需要将该文件实际挂载到容器中。 这是一个简单而优雅的解决方案,可以应对一些出乎意料的常见问题。

特性概述

从核心上来说,这个特性允许你将容器指向一个文件,该文件由 initContainer 生成, 然后让 Kubernetes 解析该文件以设置你的环境变量。此文件位于一个 emptyDir 卷中(这是一种临时存储空间,只要 Pod 存在就会保留),你的主容器不需要挂载此卷。 kubelet 会在容器启动时读取文件并注入这些变量。

工作原理

这里有一个简单的例子:

apiVersion: v1
kind: Pod
spec:
  initContainers:
  - name: generate-config
    image: busybox
    command: ['sh', '-c', 'echo "CONFIG_VAR=HELLO" > /config/config.env']
    volumeMounts:
    - name: config-volume
      mountPath: /config
  containers:
  - name: app-container
    image: gcr.io/distroless/static
    env:
    - name: CONFIG_VAR
      valueFrom:
        fileKeyRef:
          path: config.env
          volumeName: config-volume
          key: CONFIG_VAR
  volumes:
  - name: config-volume
    emptyDir: {}

使用这种方法非常简单。你在 Pod 规约中使用 fileKeyRef 字段定义环境变量, 此字段告诉 Kubernetes 去哪里找到文件以及要提取哪个键。 此文件本身类似于 .env 语法的标准格式(即 KEY=VALUE), 并且(至少在这个 Alpha 阶段)你必须确保它被写入到一个 emptyDir 卷中。 其他类型的卷在此特性中不受支持。至少有一个 Init 容器必须挂载该 emptyDir 卷(以写入文件), 但主容器不需要挂载它——它在启动时就能直接获取这些变量。

关于安全性

虽然此特性支持处理密钥或令牌等敏感数据,但需要注意它的实现依赖于挂载到 Pod 的 emptyDir 卷。 具有节点文件系统访问权限的操作人员因此可以通过 Pod 目录路径轻易获取这些敏感数据。

如果使用此特性存储密钥或令牌等敏感数据,确保你的集群安全策略能够有效保护节点免受未经授权的访问, 以防止机密信息泄露。

总结

此特性将消除如今使用的许多复杂变通方法,简化应用编写,并为更多使用场景打开大门。 Kubernetes 保持灵活性,欢迎反馈。请告诉我们你是如何使用这个特性的,或者此特性还缺少什么。