背景:
目前我们正在使用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
您可以通过使用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中指定的值填充其环境变量。
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展示了如何使用它的示例。使用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
This comment显示了如何在环境变量列表发生变化时不必更新kubernetes配置。
基本上:1)用env.sh
建立秘密2)将密码映射到容器中作为卷3)容器的启动脚本运行env.sh然后app。
这对我有用:
档案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
````