Configuration Docker中env文件的Kubernetes等价物

Configuration Docker中env文件的Kubernetes等价物,configuration,docker,environment-variables,configuration-files,kubernetes,Configuration,Docker,Environment Variables,Configuration Files,Kubernetes,背景: 目前,我们的服务使用Docker和Docker Compose。我们已经将不同环境的配置外部化为文件,这些文件定义了应用程序读取的环境变量。例如prod.env文件: ENV_VAR_ONE=Something Prod ENV_VAR_TWO=Something else Prod ENV_VAR_ONE=Something Test ENV_VAR_TWO=Something else Test 和test.env文件: ENV_VAR_ONE=Something Prod EN

背景:

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

ENV_VAR_ONE=Something Prod
ENV_VAR_TWO=Something else Prod
ENV_VAR_ONE=Something Test
ENV_VAR_TWO=Something else Test
test.env
文件:

ENV_VAR_ONE=Something Prod
ENV_VAR_TWO=Something else Prod
ENV_VAR_ONE=Something Test
ENV_VAR_TWO=Something else Test
因此,在启动容器时,我们可以简单地使用
prod.env
test.env
文件:

docker run --env-file prod.env <image>
  • 如果不可能,建议的方法是什么

  • 当使用YAML文件为Kubernetes定义pod时,没有直接的方法为容器指定包含环境变量的不同文件。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 playbook可以在方便的地方指定变量
    mysql\u root\u password
    ,并在创建资源时替换它,例如:

    ansible-playbook -e deploy=test my-playbook.yaml
    
    文件
    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
    
    mysql_root_password: supersecret
    
    mysql_root_password: notsosecret
    
    文件
    my-env-vars-prod.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
    
    mysql_root_password: supersecret
    
    mysql_root_password: notsosecret
    
    文件
    my env vars test.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
    
    mysql_root_password: supersecret
    
    mysql_root_password: notsosecret
    
    现在通过运行创建pod资源,例如:

    ansible-playbook -e deploy=test my-playbook.yaml
    

    您可以通过使用或来填充容器的环境变量。当您使用的数据是敏感数据(例如密码)时,请使用机密;当数据不是敏感数据时,请使用配置映射

    在Pod定义中,指定容器应从机密文件中提取值:

    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
    将数组作为值)

    并为每个值重复

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

    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
    
    apiVersion: v1
    kind: Secret
    metadata:
      name: mysql-secret
    type: Opaque
    data:
      MYSQL_USER: am9obgo=
      MYSQL_PASSWORD: c2VjdXJlCg==
      MYSQL_DATABASE: cHJvZC1kYgo=
      MYSQL_ROOT_PASSWORD: cm9vdHkK
    
    prod-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
    
    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启动时,它都会根据机密中指定的值填充其环境变量。

    Kubernetes(v1.6)的新更新允许您(几年前)要求的内容

    您现在可以在yaml文件中这样使用
    envFrom

      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
    
    这些文档仍然是大量的示例,我不得不在这些地方非常努力地搜索:

    • ,从文件中搜索<代码>--显示此选项可用
    • 显示了如何使用它的示例
    注意:在创建以下注释中所述的机密时,文件中的
    --与环境文件中的
    --之间存在差异。

    这对我很有用:

    文件
    env secret.yaml

    apiVersion: v1
    kind: Secret
    metadata:
      name: env-secret
    type: Opaque
    stringData:
      .env: |-
        APP_NAME=Laravel
        APP_ENV=local
    
    
    spec:
      ...
            volumeMounts:
            - name: foo
              mountPath: "/var/www/html/.env"
              subPath: .env
          volumes:
          - name: foo
            secret:
              secretName: env-secret
    ````
    
    并进入
    deployment.yaml
    pod.yaml

    apiVersion: v1
    kind: Secret
    metadata:
      name: env-secret
    type: Opaque
    stringData:
      .env: |-
        APP_NAME=Laravel
        APP_ENV=local
    
    
    spec:
      ...
            volumeMounts:
            - name: foo
              mountPath: "/var/www/html/.env"
              subPath: .env
          volumes:
          - name: foo
            secret:
              secretName: env-secret
    ````
    

    这是一个老问题,但它有很多观众,所以我添加我的答案。
    将配置与K8s实现分离的最佳方法是使用Helm。每个Helm包可以有一个
    values.yaml
    文件,我们可以在Helm图表中轻松使用这些值。如果我们有一个多组件拓扑,我们可以创建一个伞形头盔包,父值包也可以覆盖子值文件。

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

    您可以使用kustomize configMapGenerator

    configMapGenerator:
      - name: example
        env: dev.env
    

    请参考pod定义中的这个配置图/示例

    我现在已经用两个小时的时间砸了头。我在文档中找到了一个非常简单的解决方案,可以最大限度地减少我(希望是你)的痛苦

    • env.prod
      env.dev
      保留在现有状态

    • 使用oneliner脚本将这些脚本导入yaml:

      kubectl create configmap my dev config——从env file=env.dev

      kubectl create configmap my prod config——从env file=env.prod

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

    作为一个Ruby开发者,我个人认为这个解决方案是最枯燥的,因为您只需要维护一个点(ENV bash文件,它与Python/Ruby库兼容,…),然后在一次执行中对其进行YAMLize

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


    这些都有文档记录

    理想情况下,您应该能够定义一个秘密(或我们将拥有的最终配置对象),并将其作为env vars注入。不幸的是,这项工作还没有完成,所以我投了赞成票。如果您使用ansible,我们有一个共同的角色部署在kubernetes:。然后,准备新的应用程序就很容易了,请参见如何在其他repo中使用它的示例:我希望我们将在1.2版的env vars中使用secrets。注意,有一个模板建议:如果我想使用
    kubectl run
    传递20个env变量,我应该怎么做???那么为什么不更简单一些呢?这是我目前的方法,但是我有3个不同的pod,它们使用与EnvVars相同的机密列表。有没有可能定义一次并将它们暴露在3个吊舱中?我不知道。那太好了。。。似乎是为了把环境变量放入容器而分配的样板文件@PixelElephant@jävi您是指复制控制器吗?无论如何,没有任何东西可以将secret/config映射绑定到单个pod/RC/Deployment。它只是在上面的清单中定义的,并且可以装载到您想要的任何东西上。我认为重要的一点是,在秘密的定义中,这些值必须是base64编码的。易居