【问题标题】:Kubernetes equivalent of env-file in DockerKubernetes 相当于 Docker 中的 env-file
【发布时间】: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.envtest.env 文件:

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

然后,我们的应用程序会根据prod.env 中定义的环境变量获取其配置。

问题:

  1. 有没有办法从 Kubernetes 中的文件中提供环境变量(例如在定义 pod 时),而不是像这样硬编码它们:
api版本:v1 种类:豆荚 元数据: 标签: 上下文:docker-k8s-lab 名称:mysql-pod 名称:mysql-pod 规格: 容器: - 环境: - 名称:MYSQL_USER 值:mysql - 名称:MYSQL_PASSWORD 值:mysql - 名称:MYSQL_DATABASE 值:样本 - 名称:MYSQL_ROOT_PASSWORD 值:超级机密 图片:“mysql:最新” 名称:mysql 端口: - 容器端口:3306
  1. 如果这不可能,建议的方法是什么?

【问题讨论】:

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

标签: configuration docker environment-variables configuration-files kubernetes


【解决方案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
    

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

    注意:--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.prodenv.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
    

    作为一名 ruby​​ist,我个人认为这个解决方案是最干燥的,因为您只需维护一个点(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】:

          您可以通过使用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 中指定的值填充其环境变量。

          【讨论】:

          • 这是我目前的方法,但是我有 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.yamlpod.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 的环境变量中做秘密
          • 如果我想使用kubectl-run传递20个环境变量该怎么办???那么为什么不做 12factor 更容易呢??
          猜你喜欢
          • 2018-11-21
          • 2021-11-05
          • 1970-01-01
          • 2019-08-18
          • 1970-01-01
          • 2023-02-02
          • 2017-06-30
          • 1970-01-01
          • 2019-02-12
          相关资源
          最近更新 更多