1. 概述

在软件开发中,将应用程序代码与其使用的数据解耦是一种最佳实践。这种做法使得应用可以在不同环境中迁移而无需修改代码,因为环境相关的配置信息被存储在代码之外。

一个非常典型的例子就是使用 环境变量环境变量存储了应用程序可以使用的数据,而不是硬编码在逻辑中

在本教程中,我们会介绍如何在 Docker 中使用 --env-file 传递环境变量,以及在 Kubernetes 中对应的实现方式,即 ConfigMapSecret


2. 在 Docker 中使用 --env-file

向 Docker 容器中注入环境变量的一个常见方式是使用 env-file它是一个文本文件,包含一系列键值对,代表环境变量。

我们可以通过任意文本编辑器创建这个文件,添加环境变量键值对,然后在容器启动时通过 --env-file 参数传入。

举个例子:

$ echo DB_HOST=test > env-vars.txt
$ echo APP=backend >> env-vars.txt
$ cat env-vars.txt
DB_HOST=test
APP=backend

我们创建了一个名为 env-vars.txt 的 env-file,并添加了两个变量:DB_HOSTAPP

然后我们启动容器并传入该文件:

$ docker run -it --env-file env-vars.txt alpine:latest /bin/sh
/ # env
HOSTNAME=984d3294e8a3
SHLVL=1
HOME=/root
APP=backend
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
DB_HOST=test

可以看到,容器内的环境变量已经成功注入。应用就可以直接使用这些变量了。


3. Kubernetes 中的 ConfigMap

在 Kubernetes 中,我们使用 ConfigMap 来传递环境变量。ConfigMap 是一种 Kubernetes API 对象,用于存储非敏感的配置数据。

与 Docker 的 env-file 不同,ConfigMap 是通过 YAML 文件定义的 Kubernetes 资源对象。我们在 data 字段中定义键值对。

来看一个 ConfigMap 的 YAML 示例:

# env-vars.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: myconfigmap
data:
  DB_HOST: test  
  APP: backend

使用 kubectl 创建这个 ConfigMap:

$ kubectl apply -f env-vars.yaml 
configmap/myconfigmap created

接下来,我们需要创建一个 Pod,并在其中引用这个 ConfigMap:

# mypod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: mycontainer
      image: alpine
      command: ["sleep", "3600"]
      envFrom:
      - configMapRef:
          name: myconfigmap

部署 Pod:

$ kubectl apply -f mypod.yaml 
pod/mypod created

进入容器查看环境变量:

$ kubectl exec -it mypod -- /bin/sh
/ # env
...
APP=backend
DB_HOST=test

✅ 成功看到注入的变量,说明 ConfigMap 已生效。


4. Kubernetes 中的 Secret

Secret 是专门用于存储敏感数据的 Kubernetes 对象,如密码、密钥或 API Token。 它与 ConfigMap 类似,但数据是以 base64 编码形式存储的。

使用 Secret 的流程和 ConfigMap 类似,只是数据需要先编码。

先对敏感信息进行 base64 编码:

$ echo PASSWORD123 | base64
UEFTU1dPUkQxMjMK
$ echo MySecretKey | base64
TXlTZWNyZXRLZXkK

创建 Secret 的 YAML 文件:

# mysecret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  db_password: UEFTU1dPUkQxMjMK
  secret_key: TXlTZWNyZXRLZXkK

应用 Secret:

$ kubectl apply -f mysecret.yaml 
secret/mysecret created

创建 Pod 并引用 Secret:

# mysecretpod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysecretpod
spec:
  containers:
    - name: mysecretcontainer
      image: alpine
      command: ["sleep", "3600"]
      envFrom:
      - secretRef:
          name: mysecret

部署 Pod:

$ kubectl apply -f mysecretpod.yaml 
pod/mysecretpod created

进入容器查看环境变量:

$ kubectl exec -it mysecretpod -- /bin/sh
/ # env
...
db_password=PASSWORD123
secret_key=MySecretKey

✅ 成功解码并注入变量,说明 Secret 已生效。


5. 总结

功能 Docker Kubernetes
传递非敏感环境变量 --env-file ConfigMap
传递敏感环境变量 --env-file(不推荐) Secret

Docker 的 --env-file 提供了一种从外部文件注入环境变量的方式,避免了将配置硬编码到镜像中。而 Kubernetes 中的 ConfigMapSecret 则分别对应了非敏感和敏感配置的管理方式。

ConfigMap 适合存储明文配置,如数据库地址、应用模式等。
Secret 更适合存储敏感信息,如密码、密钥等,但要注意其 base64 并非加密,仅用于编码。

⚠️ 踩坑提醒:Secret 的 base64 编码并不是加密,不要误以为它能提供安全性。如需加密,应配合 Kubernetes 的加密功能(如 KMS)或使用外部 Vault。

通过合理使用 ConfigMap 和 Secret,我们可以实现配置与容器镜像的解耦,提升应用的可移植性和安全性。


原始标题:Kubernetes Equivalent of env-file in Docker