Kubernetes相当于Docker中的env文件

Joh*_*han 70 configuration environment-variables configuration-files docker kubernetes

背景:

目前我们正在使用Docker和Docker Compose来提供服务.我们已将不同环境的配置外部化为定义应用程序读取的环境变量的文件.例如一个prod.env文件:

ENV_VAR_ONE=Something Prod
ENV_VAR_TWO=Something else Prod
Run Code Online (Sandbox Code Playgroud)

和一个test.env文件:

ENV_VAR_ONE=Something Test
ENV_VAR_TWO=Something else Test
Run Code Online (Sandbox Code Playgroud)

因此,我们可以在启动容器时简单地使用prod.envor test.env文件:

docker run --env-file prod.env <image>
Run Code Online (Sandbox Code Playgroud)

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

问题:

  1. 有没有办法从Kubernetes中的文件提供环境变量(例如在定义pod时),而不是像这样对它们进行硬编码:
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. 如果不可能,建议的方法是什么?

Pix*_*ant 90

您可以通过使用SecretsConfigMaps填充容器的环境变量.当您使用的数据敏感(例如密码)时使用Secrets,而不使用ConfigMaps时使用Secrets.

在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
Run Code Online (Sandbox Code Playgroud)

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

env: 
- name: MYSQL_USER
  valueFrom:
    secretKeyRef:
      name: mysql-secret
      key: MYSQL_USER
Run Code Online (Sandbox Code Playgroud)

并重复每一个价值观.

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

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

kubectl config use-context dev
kubectl create -f dev-secret.yaml

kubectl config use-context prod
kubectl create -f prod-secret.yaml
Run Code Online (Sandbox Code Playgroud)

现在每当Pod启动时,它将从Secret中指定的值填充其环境变量.

  • 这是我目前的方法,但是我有3个不同的pod使用与EnvVars相同的秘密列表.是否可以定义它们并将它们暴露给3个豆荚? (3认同)
  • 那将是如此之大......看起来像是分配样板来将env变量变成容器.@PixelElephant (2认同)

Or *_*uan 25

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

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

  containers:
  - name: django
    image: image/name
    envFrom:
      - secretRef:
         name: prod-secrets
Run Code Online (Sandbox Code Playgroud)

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

kubectl create secret generic prod-secrets --from-file=prod/env.txt`
Run Code Online (Sandbox Code Playgroud)

txt文件内容是键值的位置:

DB_USER=username_here
DB_PASSWORD=password_here
Run Code Online (Sandbox Code Playgroud)

文档仍然是例子的湖泊,我必须在那些地方非常努力地搜索:

  • 这应该是“--from-env-file”吗?使用“--from-file”会产生一个包含文件内容的键(以输入文件命名)。使用“--from-env-file”将文件内的密钥扩展为秘密。有关更多信息,请参阅[此 Google 文档](https://cloud.google.com/kubernetes-engine/docs/concepts/secret#secret-from-env-file)。 (3认同)

小智 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 }}
    ...
Run Code Online (Sandbox Code Playgroud)

然后你的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
Run Code Online (Sandbox Code Playgroud)

档案my-env-vars-prod.yaml:

mysql_root_password: supersecret
Run Code Online (Sandbox Code Playgroud)

档案my-env-vars-test.yaml:

mysql_root_password: notsosecret
Run Code Online (Sandbox Code Playgroud)

现在,您可以通过运行来创建pod资源,例如:

ansible-playbook -e deploy=test my-playbook.yaml
Run Code Online (Sandbox Code Playgroud)

  • 理想情况下,您应该能够定义一个Secret(或者我们将拥有的最终配置对象),并将其注入为env vars.不幸的是,这项工作尚未完成,所以我正在为此投票. (4认同)

mad*_*att 6

这对我有用:

文件 env-secret.yaml

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

Run Code Online (Sandbox Code Playgroud)

并进入deployment.yamlpod.yaml

spec:
  ...
        volumeMounts:
        - name: foo
          mountPath: "/var/www/html/.env"
          subPath: .env
      volumes:
      - name: foo
        secret:
          secretName: env-secret
````
Run Code Online (Sandbox Code Playgroud)


Ric*_*rdo 6

我的头被撞了两个小时了。我在文档中找到了一个非常简单的解决方案,可以最大限度地减少我(也希望是您)的痛苦。

  • 保留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
Run Code Online (Sandbox Code Playgroud)

作为一名 Ruby 专家,我个人认为这个解决方案是最干燥的,因为您需要维护一个点(ENV bash 文件,与 Python/Ruby 库兼容,..),然后您在一次执行中对其进行 YAMLize。

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

一切都记录在这里