在Docker中相当于env-file的Kubernetes
背景:
目前我们正在使用Docker和Docker Compose来处理我们的服务。 我们将不同环境的configuration外化为定义由应用程序读取的环境variables的文件。 例如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.env
或test.env
文件:
docker run --env-file prod.env <image>
然后,我们的应用程序将根据prod.env
定义的环境variables来select其configuration。
问题:
- 有没有办法从Kubernetes中的文件提供环境variables(例如定义一个pod时),而不是像这样硬编码它们:
apiVersion:v1 类:Pod 元数据: 标签: 上下文:docker-k8s-lab 名称:mysql-pod 名称:mysql-pod 规格: 容器: - ENV: - 名称:MYSQL_USER 值:mysql - 名称:MYSQL_PASSWORD 值:mysql - 名称:MYSQL_DATABASE 值:样本 - 名称:MYSQL_ROOT_PASSWORD 价值:supersecret image:“mysql:latest” 名字:mysql 端口: - containerPort:3306
- 如果这是不可能的,那么build议的方法是什么?
您可以通过使用Secrets或ConfigMaps来填充容器的环境variables。 当你正在使用的数据是敏感的(例如密码)时使用秘密,当不是时则使用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
并重复每一个价值。
无论您使用哪种方法,现在都可以定义两个不同的秘密,一个用于生产,另一个用于开发。
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中指定的值中填充其环境variables。
当使用YAML文件为Kubernetes定义一个窗格时,没有直接的方法来指定一个包含容器环境variables的不同文件。 Kubernetes项目说,他们将在未来改善这一领域(见Kubernetes文件 )。
同时,我build议使用configuration工具并将YAML吊舱作为模板。 例如,使用Ansible你的pod YAML文件看起来像这样:
文件my-pod.yaml.template
:
apiVersion: v1 kind: Pod ... spec: containers: ... env: - name: MYSQL_ROOT_PASSWORD value: {{ mysql_root_pasword }} ...
然后,您的Ansible手册可以方便地指定variablesmysql_root_password
,并在创build资源时replace它,例如:
文件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
现在通过运行来创buildpod资源,例如:
ansible-playbook -e deploy=test my-playbook.yaml
Kubernetes(v1.6)的一个新的更新允许你问(几年前)。
你现在可以在yaml文件中像这样使用envFrom
:
containers: - name: django image: image/name envFrom: - secretRef: name: prod-secrets
在哪里发展秘密是你的秘密,你可以通过以下方式创build它:
kubectl create secret generic prod-secrets --from-file=prod/env.txt`
在txt文件内容是一个键值的地方:
DB_USER=username_here DB_PASSWORD=password_here
文件仍然是湖的例子,我不得不在这些地方努力search:
- 秘密文档 ,search
envFrom
– 显示此选项可用。 - 等效的
ConfigMap
文档显示了如何使用它的例子。
这个注释显示了如何做到这一点,而不必更新环境variables列表时更新kubernetesconfiguration。
从本质上说:1)与env.sh
秘密2)将秘密映射到容器作为卷3)容器的启动脚本运行env.sh然后应用程序。