Kubernetes相当于Docker中的env文件

时间:2015-11-02 13:18:22

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

背景

目前我们正在使用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时)而不是像这样对它们进行硬编码:
  2. apiVersion: v1
    kind: Pod
    metadata: 
      labels: 
        context: docker-k8s-lab
        name: mysql-pod
      name: mysql-pod
    spec: 
      containers: 
        - 
          env: 
            - 
              name: MYSQL_USER
              value: mysql
            - 
              name: MYSQL_PASSWORD
              value: mysql
            - 
              name: MYSQL_DATABASE
              value: sample
            - 
              name: MYSQL_ROOT_PASSWORD
              value: supersecret
          image: "mysql:latest"
          name: mysql
          ports: 
            - 
              containerPort: 3306
    
    1. 如果无法做到这一点,建议的做法是什么?

8 个答案:

答案 0 :(得分:81)

您可以使用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将数组作为值)

重复每一个价值。

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

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中指定的值填充其环境变量。

答案 1 :(得分:20)

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

您现在可以在yaml文件中使用envFrom这样的内容:

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

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

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

txt文件内容是键值的地方:

DB_USER=username_here
DB_PASSWORD=password_here

文档仍然是一些例子,我不得不在那些地方搜索:

答案 2 :(得分:10)

使用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

答案 3 :(得分:1)

This comment显示了如何在环境变量列表发生变化时不必更新kubernetes配置。

本质: 1)与env.sh保密 2)将密钥映射到容器中作为卷 3)容器的启动脚本运行env.sh然后app。

答案 4 :(得分:1)

我现在在 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,我个人认为这个解决方案是 DRYest,因为你有一个点需要维护(ENV bash 文件,它与 Python/Ruby 库兼容,..)然后你在一次执行中对它进行 YAMLize。

请注意,您需要保持 ENV 文件干净(我有很多评论阻止了它的工作,因此必须在前面加上 cat config.original | egrep -v "^#" | tee config.cleaned),但这并不会显着改变复杂性。

一切都记录在案here

答案 5 :(得分:0)

这对我有用:

文件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
````

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

您可以使用kustomize configMapGenerator。

configMapGenerator:
  - name: example
    env: dev.env

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