136

背景:

目前我们的服务使用Docker和Docker Compose。我们已经将不同环境的配置外部化为定义应用程序读取的环境变量的文件。例如a产品env文件:

ENV_VAR_ONE=产品ENV_VAR_TWO=其他产品

和a测试env文件:

ENV_VAR_ONE=某些测试ENV_VAR_TWO=其他测试

因此,我们可以简单地使用产品.env测试env启动容器时的文件:

docker运行--env-file prod.env<image>

然后,我们的应用程序根据中定义的环境变量选择其配置产品env.

问题:

  1. 是否有方法从Kubernetes中的文件提供环境变量(例如,在定义pod时),而不是像这样硬编码:
apiVersion版本:v1种类:吊舱元数据:标签:上下文:docker-k8s-lab名称:mysql-pod名称:mysql-pod规格:容器:- 环境:- 名称:MYSQL_USER值:mysql- 名称:MYSQL_PASSWORD值:mysql- 名称:MYSQL_DATABASE值:示例- 名称:MYSQL_ROOT_PASSWORD值:超机密图片:“mysql:latest”名称:mysql端口:- 集装箱港口:3306
  1. 如果这不可能,建议的方法是什么?
1
  • 我也在找这样的东西。我不想创建秘密配置映射资源,因为这只是临时的,用于测试。我在k8s集群中的权限有限。我也许可以创建一个秘密资源,但一旦创建了资源,我将无法删除它们。 评论 2020年3月16日15:19

9个答案9

重置为默认值
149

您可以通过使用秘密配置映射。当您使用的数据是敏感的(例如密码)时使用“秘密”,当数据不是敏感的时使用“配置地图”。

在Pod定义中,指定容器应从Secret中提取值:

api版本:v1种类:吊舱元数据:标签:上下文:docker-k8s-lab名称:mysql pod名称:mysql-pod规格:容器:-图片:“mysql:latest”名称:mysql端口:-集装箱端口:3306envFrom(环境自):-秘书参考:名称:mysql-secret

请注意,此语法仅在Kubernetes 1.6或更高版本中可用。在Kubernetes的早期版本中,您必须手动指定每个值,例如:

环境:-名称:MYSQL_USER值从:secretKeyRef:名称:mysql-secret键:MYSQL_USER

(注意:环境价值将数组作为值)

并对每个值进行重复。

无论您使用哪种方法,现在都可以定义两个不同的Secret,一个用于生产,另一个用于开发。

dev-secret.yaml:

api版本:v1kind:秘密元数据:名称:mysql-secret类型:不透明数据:MYSQL_用户:bXlzcWwKMYSQL_密码:bXlzcWwKMYSQL_数据库:c2FtcGxlCg==MYSQL_ROOT_密码:c3VwZXJzZWNyZXQK

prod-secret.yaml:

api版本:v1种类:秘密元数据:名称:mysql-secret类型:不透明数据:MYSQL_USER:am9obgo(我的SQL用户)=MYSQL_密码:c2VjdXJlCg==MYSQL_数据库:cHJvZC1kYgo=MYSQL_ROOT_密码:cm9vdHkK

并将正确的秘密部署到正确的Kubernetes集群:

kubectl配置use-context开发kubectl create-f dev-secret.yaml公司kubectl配置use-context产品kubectl create-f产品机密.yaml

现在,每当Pod启动时,它都会根据Secret中指定的值填充其环境变量。

8
  • 5
    这是我当前的方法,但是我有3个不同的pod,使用与EnvVars相同的秘密列表。是否可以定义一次并将其暴露在3个豆荚中?
    – 贾维
    评论 2016年5月25日14:06
  • 2
    那太棒了。。。看起来像是一份样板文件,用于将env变量放入容器中@像素大象 评论 2016年9月21日7:24
  • @jävi你指的是复制控制器吗?无论如何,没有将秘密/配置映射绑定到单个pod/RC/Deployment。它只是在上面的清单中定义的,可以安装到任意多的东西上。 评论 2017年1月9日21:58
  • @aronchick我相信他们正在寻找这个功能:github.com/kubernetes/kubernetest/issues/26299看起来很快就要着陆了。我将在Kubernetes的发布版本中更新该功能的答案。 评论 2017年1月9日22:02
  • 1
    我认为重要的是要提到,在Secret的定义中,值必须是base64编码的。我刚刚在我的学习集群中尝试了这一点,除非这些值都是base64编码的,否则会出错 评论 2019年4月17日14:57
75

Kubernetes的新更新(v1.6)允许你(多年前)要求的。

您现在可以使用envFrom(环境自)在yaml文件中如下所示:

容器:-姓名:djangoimage:图像/名称envFrom(环境自):-秘书参考:名称:prod-secrets

如果发展秘密是您的秘密,您可以通过以下方式创建:

kubectl创建秘密通用prod-secrets--from-env-file=prod/env.txt`

其中txt文件内容是键值:

DB_USER=用户名在此DB_PASSWORD=密码在此

这些文档仍然是大量的示例,我不得不在这些地方努力搜索:

注:两者之间有区别--来自文件--from-env文件按照下面的注释中所述创建秘密时。

6
  • 你能分享一下Kubernetes关于这个的文档吗? 评论 2017年5月10日19:55
  • @ArtemDolobanko编辑,请记住这仍然是一个新的文档库,如果您想了解更多详细信息,可以在Github的问题跟踪器上找到许多讨论。
    – 或段
    评论 2017年5月10日22:03
  • @或者段,我如何使用env将版本号传递给docker image 评论 2019年8月26日10:06
  • 如果我们必须将该文本文件装载到某个位置,应用程序将从那里自动创建env,该怎么办 评论 2019年10月25日5:24
  • 5
    应该这样吗--from-env文件? 使用--来自文件结果是一个带有文件内容的键(以输入文件命名)。使用--from-env文件将文件中的密钥展开为机密。请参见这个谷歌文档了解更多信息。
    – 大卫
    评论 2020年5月21日8:04
13

使用YAML文件为Kubernetes定义pod时,无法直接指定包含容器环境变量的其他文件。Kubernetes项目表示,他们将在未来改进这一领域(参见Kubernetes文档).

同时,我建议使用配置工具并将pod YAML作为模板。例如,使用Ansible,pod YAML文件将如下所示:

文件my-pod.yaml.template(my-pod.jaml.模板):

api版本:v1种类:吊舱...规格:容器:...环境:-名称:MYSQL_ROOT_PASSWORD值:{{mysqlrootpasword}}...

然后Ansible剧本可以指定变量mysql_root_password在方便的地方,并在创建资源时替换它,例如:

文件我的弹壳.yaml:

-主机:my_hostsvars_files(变量_文件):-my-env-vars-{{deploy_to}}.yaml任务:-name:从模板创建pod YAML模板:src=my-pod.yaml.template dst=my-pod.yaml-name:在Kubernetes创建pod命令:kubectl create-f my-pod.yaml

文件my-env-vars-prod.yaml公司:

mysql_root_password:超级机密

文件my-env-vars-test.yaml公司:

mysql_root_password:非机密

现在,您可以通过运行以下命令来创建pod资源:

ansible-playbook-e部署=测试my-playbbook.yaml
8
  • 4
    理想情况下,您应该能够定义一个Secret(或我们将拥有的最终配置对象),并将其作为envvars注入。不幸的是,这项工作尚未完成,所以我投票赞成。 评论 2015年11月2日16:09
  • 如果您使用的是ansible,那么我们可以在kubernetes上部署一个共同的角色:github.com/ansibl8s/k8s-common。然后很容易准备新应用程序,请参阅如何在其他回购中使用它的示例:github.com/ansibl8s
    – 蚂蚁31
    评论 2015年11月4日14:03
  • 我希望我们能在1.2的env-vars中做秘密 评论 2015年11月8日6:34
  • 1
    请注意,有一个关于模板的建议:github.com/kubernetes/kubernets/blob/master/docs/propossies/…
    – 卢布肯
    评论 2016年2月17日11:11
  • 如果我想用我该怎么办库贝特伦传递20个env变量???那么为什么不做12factor更容易呢??
    – 霍姆斯
    评论 2016年9月18日16:26
11

这对我很有效:

文件env-secret.yaml病毒

api版本:v1kind:秘密元数据:名称:env-secret类型:不透明字符串数据:.env(环境):|-APP_NAME=拉拉维勒APP_ENV=本地

并进入部署.yaml豆荚山药

规格:...卷装载:-名称:foo安装路径:“/var/www/html/.env”子路径:.env卷:-名称:foo秘密:secretName:env-secret````
2
  • 我该如何对docker映像使用env,以便不必每次需要增加版本时都更新deployment.yaml 评论 2019年8月26日10:17
  • 引用“/var/www/html/.env”正在创建一个.env(英语)文件夹而不是文件名。
    – 第12级
    评论 2022年3月7日16:59
6

我的头撞了两个小时。我在文档中找到了一个非常简单的解决方案,可以将我(希望是你)的痛苦降到最低。

  • 保留env.prod公司,环境.dev就像你拥有的那样。

  • 使用oneliner脚本将其导入yaml:

    kubectl创建configmap my-dev-config--from-env-file=env.dev

    kubectl创建configmap my-prod-config--from-env-file=env.prod

您可以看到结果(为了即时满足):

#您也可以将其保存到磁盘kubectl获取configmap我的开发配置-o yaml

作为一名Ruby爱好者,我个人认为这个解决方案是DRYest,因为您只有一个需要维护的点(ENV bash文件,它与Python/Ruby库兼容…),然后您可以在单个执行中对其进行YAMLize。

请注意,您需要保持ENV文件干净(我有很多意见阻止了这项工作,因此必须在cat config.original|egrep-v“^#”|tee config.cleaned)但这并没有实质性地改变复杂性。

都有记录在这里

2

这是一个老问题,但让我为未来的初学者描述一下我的答案。

您可以使用kustomize configMapGenerator。

configMapGenerator:-名称:示例环境:dev.env

并在pod定义中引用此configMap/示例

1

这是一个古老的问题,但它有很多观众,所以我添加了我的答案。将配置与K8实现分离的最佳方法是使用Helm。每个Helm包都可以有一个值.yaml文件,我们可以很容易地使用赫尔姆图表中的这些值。如果我们有一个多组件拓扑,我们可以创建一个伞形Helm包,父值包也可以覆盖子值文件。

0

您可以通过在容器中指定K8S值作为环境变量来引用它们。

让您的部署为mongo.yml,如下所示:

--种类:部署----容器:--环境:-名称:DB_URL值从:配置映射键参考:名称:mongo-config关键字:mongo-url-名称:MONGO_INITDB_ROOT_PASSWORD值从:secretKeyRef:名称:mongo-secret密钥:mongo-password

mongo-secret用于敏感数据,例如:密码或证书

api版本:v1kind:秘密元数据:名称:mongo-secret类型:不透明数据:蒙古用户:bW9uZ291c2Vy蒙古语密码:bW9uZ29wYXNzd29yZA==

mongo配置用于非敏感数据

apiVersion版本:v1种类:配置映射元数据:名称:mongo-config数据:mongo-url:mongo-service
0

您可以尝试以下步骤:

此命令将放置您的文件产品env在秘密中。

kubectl创建机密通用env-prod--from-file=prod.env=prod_env

然后,您可以像这样在deployment.yaml中引用该文件

api版本:apps/v1种类:部署元数据:名称:api-identity标签:app.kubernetes.io/name:api标识规格:副本:1选择器:匹配标签:app.kubernetes.io/name:api标识模板:元数据:标签:app.kubernetes.io/name:api标识规格:imagePullSecrets:-名称:docker-registry-credential容器:-名称:api-identity图片:“api标识:测试”图像拉动策略:IfNotPresent端口:-名称:http集装箱港口:8005协议:TCP卷装载:-名称:env-file-volmountPath:“/var/www/html/.env”子路径:.env卷:-名称:env-file-vol秘密:分泌名称:env-prod

你的答案

单击“发布您的答案”,表示您同意我们的服务条款并确认您已阅读我们的隐私政策.

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.