背景
目前我们正在使用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.env
或test.env
文件:
docker run --env-file prod.env <image>
然后,我们的应用程序根据prod.env
中定义的环境变量选择其配置。
问题:
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
答案 0 :(得分:81)
您可以使用Secrets或ConfigMaps填充容器的环境变量。当您使用的数据敏感(例如密码)时使用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
文档仍然是一些例子,我不得不在那些地方搜索:
envFrom
- 显示此选项可用。ConfigMap
docs显示了如何使用它的示例。答案 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.prod
、env.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
作为一个 rubyist,我个人认为这个解决方案是 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.yaml
或pod.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 /示例