Kubernetes 相当于 Docker 中的 env-file
Posted
技术标签:
【中文标题】Kubernetes 相当于 Docker 中的 env-file【英文标题】:Kubernetes equivalent of env-file in Docker 【发布时间】:2016-02-02 09:23:58 【问题描述】:背景:
目前我们正在使用 Docker 和 Docker Compose 来提供我们的服务。我们已将不同环境的配置外部化为定义应用程序读取的环境变量的文件。例如prod.env
文件:
ENV_VAR_ONE=Something Prod
ENV_VAR_TWO=Something else Prod
还有一个test.env
文件:
ENV_VAR_ONE=Something Test
ENV_VAR_TWO=Something else Test
因此我们可以在启动容器时简单地使用prod.env
或test.env
文件:
docker run --env-file prod.env <image>
然后,我们的应用程序会根据prod.env
中定义的环境变量获取其配置。
问题:
-
有没有办法从 Kubernetes 中的文件中提供环境变量(例如在定义 pod 时),而不是像这样硬编码它们:
-
如果这不可能,建议的方法是什么?
【问题讨论】:
我也在寻找这样的东西。我不想创建Secret
或ConfigMap
资源,因为这只是临时的并用于测试。我在 k8s 集群中的权限有限。我也许可以创建一个 Secret
资源,但一旦创建,我将无法删除它们。
【参考方案1】:
您可以通过在容器中将 K8S 值指定为环境变量来引用它们。
让您的部署为 mongo.yml,如下所示:
--
kind: Deployment
--
--
containers:
--
env:
- name: DB_URL
valueFrom:
configMapKeyRef:
name: mongo-config
key: mongo-url
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
mongo-secret 用于敏感数据,例如:密码或证书
apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
type: Opaque
data:
mongo-user: bW9uZ291c2Vy
mongo-password: bW9uZ29wYXNzd29yZA==
mongo-config 用于非敏感数据
apiVersion: v1
kind: ConfigMap
metadata:
name: mongo-config
data:
mongo-url: mongo-service
【讨论】:
【参考方案2】:Kubernetes(v1.6) 的新更新 满足您的要求(多年前)。
您现在可以在 yaml 文件中像这样使用envFrom
:
containers:
- name: django
image: image/name
envFrom:
- secretRef:
name: prod-secrets
其中 development-secrets 是您的秘密,您可以通过以下方式创建它:
kubectl create secret generic prod-secrets --from-env-file=prod/env.txt`
其中txt文件内容为key-value:
DB_USER=username_here
DB_PASSWORD=password_here
文档仍然是大量示例,我不得不在这些地方非常努力地搜索:
Secrets docs,搜索--from-file
- 表明该选项可用。
The equivalent ConfigMap
docs 展示了如何使用它的示例。
注意:--from-file
和 --from-env-file
在创建秘密时有所不同,如下面的 cmets 所述。
【讨论】:
你能分享这方面的 Kubernetes 文档吗? @ArtemDolobanko 已编辑,请记住,这仍然是新的文档湖,如果您想了解更多详细信息,可以在 Github 的问题跟踪器上找到许多讨论。 @Or Duan 我如何使用 env 将版本号传递给 docker 映像 如果我们必须将该文本文件挂载到某个位置,应用程序会从那里自动创建环境 应该是--from-env-file
吗?使用--from-file
会产生一个带有文件内容的键(以输入文件命名)。使用--from-env-file
将文件内的密钥扩展为机密。请参阅this Google documentation 了解更多信息。【参考方案3】:
我现在用 tyhis 砸了我的头 2 个小时。我在文档中找到了一个非常简单的解决方案,可以最大程度地减少我(也希望是您的)痛苦。
保留env.prod
、env.dev
原样。
使用 oneliner 脚本将它们导入 yaml:
kubectl create configmap my-dev-config --from-env-file=env.dev
kubectl create configmap my-prod-config --from-env-file=env.prod
你可以看到结果(即时满足):
# You can also save this to disk
kubectl get configmap my-dev-config -o yaml
作为一名 rubyist,我个人认为这个解决方案是最干燥的,因为您只需维护一个点(ENV bash 文件,它与 Python/Ruby 库兼容,..),然后您在一次执行中对其进行 YAML 化。
请注意,您需要保持 ENV 文件干净(我有很多 cmets 阻止了此操作,因此必须在前面加上 cat config.original | egrep -v "^#" | tee config.cleaned
),但这并不会显着改变复杂性。
全部记录在案here
【讨论】:
【参考方案4】:这是一个老问题,但让我为未来的初学者描述我的答案。
您可以使用 kustomize configMapGenerator。
configMapGenerator:
- name: example
env: dev.env
并在 pod 定义中引用此 configMap/example
【讨论】:
【参考方案5】:这是一个老问题,但它有很多观众,所以我添加了我的答案。
将配置与 K8s 实现分离的最佳方法是使用 Helm。每个 Helm 包都可以有一个 values.yaml
文件,我们可以轻松地在 Helm 图表中使用这些值。如果我们有一个多组件拓扑,我们可以创建一个伞形 Helm 包,并且父值包也可以覆盖子值文件。
【讨论】:
【参考方案6】:您可以通过使用Secrets 或ConfigMaps 来填充容器的环境变量。当您使用的数据是敏感数据(例如密码)时使用 Secrets,如果不是敏感数据则使用 ConfigMaps。
在您的 Pod 定义中指定容器应从 Secret 中提取值:
apiVersion: v1
kind: Pod
metadata:
labels:
context: docker-k8s-lab
name: mysql-pod
name: mysql-pod
spec:
containers:
- image: "mysql:latest"
name: mysql
ports:
- containerPort: 3306
envFrom:
- secretRef:
name: mysql-secret
请注意,此语法仅在 Kubernetes 1.6 或更高版本中可用。在早期版本的 Kubernetes 上,您必须手动指定每个值,例如:
env:
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_USER
(注意env
取一个数组作为值)
并为每个值重复。
无论您使用哪种方法,您现在都可以定义两种不同的 Secret,一种用于生产,一种用于开发。
dev-secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
data:
MYSQL_USER: bXlzcWwK
MYSQL_PASSWORD: bXlzcWwK
MYSQL_DATABASE: c2FtcGxlCg==
MYSQL_ROOT_PASSWORD: c3VwZXJzZWNyZXQK
prod-secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
data:
MYSQL_USER: am9obgo=
MYSQL_PASSWORD: c2VjdXJlCg==
MYSQL_DATABASE: cHJvZC1kYgo=
MYSQL_ROOT_PASSWORD: cm9vdHkK
并将正确的密钥部署到正确的 Kubernetes 集群:
kubectl config use-context dev
kubectl create -f dev-secret.yaml
kubectl config use-context prod
kubectl create -f prod-secret.yaml
现在,每当 Pod 启动时,它都会根据 Secret 中指定的值填充其环境变量。
【讨论】:
这是我目前的方法,但是我有 3 个不同的 pod,它们使用与 EnvVars 相同的秘密列表。是否可以定义一次并将它们暴露给 3 个 pod? 我不知道。 那太好了...似乎分配了样板文件以将环境变量放入容器中。 @PixelElephant @jävi 你的意思是复制控制器吗?无论如何,没有任何东西将 secret/config 映射绑定到单个 pod/RC/Deployment。它只是在上面的清单中定义,可以安装到任意数量的东西上。 我认为在 Secret 的定义中提到值必须是 base64 编码是很重要的。我刚刚用我的学习集群尝试过这个,我得到错误,除非值都是 base64 编码的【参考方案7】:这对我有用:
文件env-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: env-secret
type: Opaque
stringData:
.env: |-
APP_NAME=Laravel
APP_ENV=local
并进入deployment.yaml
或pod.yaml
spec:
...
volumeMounts:
- name: foo
mountPath: "/var/www/html/.env"
subPath: .env
volumes:
- name: foo
secret:
secretName: env-secret
````
【讨论】:
如何将 env 用于 docker 映像,这样我就不必每次需要增加版本时都更新 deployment.yaml【参考方案8】:使用 YAML 文件为 Kubernetes 定义 pod 时,没有直接的方法可以为容器指定包含环境变量的不同文件。 Kubernetes 项目表示他们将在未来改进这一领域(参见Kubernetes docs)。
同时,我建议使用配置工具并将 pod YAML 设为模板。例如,使用 Ansible,您的 pod YAML 文件将如下所示:
文件my-pod.yaml.template
:
apiVersion: v1
kind: Pod
...
spec:
containers:
...
env:
- name: MYSQL_ROOT_PASSWORD
value: mysql_root_pasword
...
然后你的 Ansible playbook 可以在方便的地方指定变量 mysql_root_password
,并在创建资源时替换它,例如:
文件my-playbook.yaml
:
- hosts: my_hosts
vars_files:
- my-env-vars- deploy_to .yaml
tasks:
- name: create pod YAML from template
template: src=my-pod.yaml.template dst=my-pod.yaml
- name: create pod in Kubernetes
command: kubectl create -f my-pod.yaml
文件my-env-vars-prod.yaml
:
mysql_root_password: supersecret
文件my-env-vars-test.yaml
:
mysql_root_password: notsosecret
现在你通过运行来创建 pod 资源,例如:
ansible-playbook -e deploy=test my-playbook.yaml
【讨论】:
理想情况下,您应该能够定义一个 Secret(或我们将拥有的最终配置对象)并将其作为环境变量注入。不幸的是,这项工作还没有完成,所以我投票赞成。 如果你使用 ansible,我们有一个共同的角色可以部署在 kubernetes 上:github.com/ansibl8s/k8s-common。然后很容易准备新的应用程序,请参阅如何在其他 repo 中使用它的示例:github.com/ansibl8s 我希望我们能在 1.2 的环境变量中做秘密 注意有模板的提议:github.com/kubernetes/kubernetes/blob/master/docs/proposals/… 如果我想使用kubectl-run
传递20个环境变量该怎么办???那么为什么不做 12factor 更容易呢??以上是关于Kubernetes 相当于 Docker 中的 env-file的主要内容,如果未能解决你的问题,请参考以下文章
docker 入门(二):docker 和 沙盒、虚拟机以及 Kubernetes 的关系
Kubernetes 集群中 Docker 镜像中的环境变量
为啥 OpenJDK Docker 容器会忽略 Kubernetes 中的内存限制?