Kubernetes相当于Docker中的env文件


84

背景:

当前,我们将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.envortest.env文件:

docker run --env-file prod.env <image>

然后,我们的应用程序根据中定义的环境变量选择其配置prod.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
      端口: 
        -- 
          containerPort:3306
  1. 如果这不可能,建议的方法是什么?

我也在寻找这样的东西。我不想创建SecretConfigMap资源,因为这只是临时的,可用于测试。我在k8s集群中的权限有限。我也许可以创建Secret资源,但是一旦创建资源就无法删除它们。
alltej

Answers:


114

您可以使用SecretsConfigMaps填充容器的环境变量。当您使用的数据敏感时(例如密码),请使用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中指定的值填充其环境变量。


5
这是我目前的方法,但是我有3个不同的Pod,使用与EnvVars相同的秘密列表。是否可以定义一次并将它们暴露在3个吊舱中?
哈维-

1
从来没听说过。
Pixel Elephant

2
真是太好了...似乎很简单,可以将环境变量放入容器中。@PixelElephant
AndrewMcLagan

@jävi您的意思是复制控制器吗?无论如何,没有任何东西可以将密钥/配置映射绑定到单个pod / RC / Deployment。它仅在上面的清单中定义,并且可以根据需要安装到许多东西上。
aronchick

@aronchick我相信他们正在寻找此功能:github.com/kubernetes/kubernetes/issues/26299看来它将很快登陆。一旦该功能在Kubernetes的发行版本中,我将更新答案。
Pixel Elephant

36

Kubernetes(v1.6)的新更新可以满足您几年前的要求。

您现在可以envFrom在yaml文件中使用以下代码:

  containers:
  - name: django
    image: image/name
    envFrom:
      - secretRef:
         name: prod-secrets

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

kubectl create secret generic prod-secrets --from-env-file=prod/env.txt`

txt文件的内容是键值:

DB_USER=username_here
DB_PASSWORD=password_here

这些文档仍然是大量示例,我不得不在这些地方进行认真的搜索:


您可以在此共享Kubernetes文档吗?
Artem Dolobanko

@ArtemDolobanko编辑,请记住,这仍然是新手,是一堆文档,如果您需要更多细节,可以在Github的问题跟踪器上找到许多讨论。
还是段

@Or Duan我将如何使用env将版本号传递给docker镜像
dev-stack

如果我们必须将该文本文件安装到某个位置,然后该应用程序将在那里自动创建环境,该怎么办
Tara Prasad Gurung

2
应该这样--from-env-file吗?使用会--from-file产生一个带有文件内容的键(以输入文件命名)。使用--from-env-file将文件内的密钥扩展为机密。有关更多信息,请参阅此Google文档
大卫

11

当使用YAML文件为Kubernetes定义Pod时,没有直接的方法来指定包含容器环境变量的其他文件。Kubernetes项目表示他们将在未来改善这一领域(请参阅Kubernetes文档)。

同时,我建议使用配置工具并将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剧本就可以指定变量 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

4
理想情况下,您应该能够定义一个Secret(或我们将拥有的最终配置对象)并将其作为env var注入。不幸的是,这项工作尚未完成,所以我对此表示赞成。
蒂姆·霍金

如果您使用的是Ansible,我们将在kubernetes上扮演一个共同的角色:github.com/ansibl8s/k8s-common。然后,准备新的应用程序非常容易,请参阅示例
ant31

我希望我们会在环境变量中保密1.2
Paul Morie


如果我想kubectl-run用来传递20个环境变量,该怎么办?为什么不那么容易做12factor?
霍尔姆斯

3

这对我有用:

文件 env-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: env-secret
type: Opaque
stringData:
  .env: |-
    APP_NAME=Laravel
    APP_ENV=local

并进入deployment.yamlpod.yaml

spec:
  ...
        volumeMounts:
        - name: foo
          mountPath: "/var/www/html/.env"
          subPath: .env
      volumes:
      - name: foo
        secret:
          secretName: env-secret
````

我将如何使用docker镜像的env,这样我每次需要增加版本时就不必更新deploy.yaml
开发堆栈

0

这是一个古老的问题,但是有很多观众,因此我添加了答案。将配置与K8s实现分开的最好方法是使用Helm。每个Helm软件包都可以有一个values.yaml文件,我们可以轻松地在Helm图表中使用这些值。如果我们具有多组件拓扑,则可以创建一个伞形Helm包,并且父值包也可以覆盖子值文件。


0

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

您可以使用kustomize configMapGenerator。

configMapGenerator:
  - name: example
    env: dev.env

并在pod定义中引用此configMap / example

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.