Kubernetes equivalente a env-file en Docker

84

Antecedentes:

Actualmente usamos Docker y Docker Compose para nuestros servicios. Hemos externalizado la configuración para diferentes entornos en archivos que definen las variables de entorno leídas por la aplicación. Por ejemplo, un prod.envarchivo:

ENV_VAR_ONE=Something Prod
ENV_VAR_TWO=Something else Prod

y un test.envarchivo:

ENV_VAR_ONE=Something Test
ENV_VAR_TWO=Something else Test

Por lo tanto, podemos simplemente usar el archivo prod.envo test.enval iniciar el contenedor:

docker run --env-file prod.env <image>

Luego, nuestra aplicación toma su configuración en función de las variables de entorno definidas en prod.env.

Preguntas:

  1. ¿Hay alguna forma de proporcionar variables de entorno desde un archivo en Kubernetes (por ejemplo, al definir un pod) en lugar de codificarlas de esta manera?
apiVersion: v1
tipo: Pod
metadatos: 
  etiquetas: 
    contexto: docker-k8s-lab
    nombre: mysql-pod
  nombre: mysql-pod
Especificaciones: 
  contenedores: 
    - 
      env: 
        - 
          nombre: MYSQL_USER
          valor: mysql
        - 
          nombre: MYSQL_PASSWORD
          valor: mysql
        - 
          nombre: MYSQL_DATABASE
          valor: muestra
        - 
          nombre: MYSQL_ROOT_PASSWORD
          valor: supersecreto
      imagen: "mysql: último"
      nombre: mysql
      puertos: 
        - 
          containerPort: 3306
  1. Si esto no es posible, ¿cuál es el enfoque sugerido?
Johan
fuente
También estoy buscando algo como esto. No quiero crear un recurso Secreto ConfigMapporque esto es solo temporal y se usa para pruebas. Tengo permisos limitados en el clúster k8s. Tal vez pueda crear un Secretrecurso, pero no podré eliminarlo una vez que ya esté creado.
alltej

Respuestas:

114

Puede completar las variables de entorno de un contenedor mediante el uso de Secrets o ConfigMaps . Use Secrets cuando los datos con los que está trabajando sean confidenciales (por ejemplo, contraseñas) y ConfigMaps cuando no lo sea.

En la definición de tu pod, especifica que el contenedor debe extraer valores de un secreto:

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

Tenga en cuenta que esta sintaxis solo está disponible en Kubernetes 1.6 o posterior. En una versión anterior de Kubernetes, deberá especificar cada valor manualmente, por ejemplo:

env: 
- name: MYSQL_USER
  valueFrom:
    secretKeyRef:
      name: mysql-secret
      key: MYSQL_USER

(Tenga en cuenta que envtome una matriz como valor)

Y repitiendo por cada valor.

Independientemente del enfoque que utilice, ahora puede definir dos secretos diferentes, uno para producción y otro para desarrollo.

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

E implemente el secreto correcto en el clúster de Kubernetes correcto:

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

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

Ahora, cada vez que se inicia un Pod, completará sus variables de entorno a partir de los valores especificados en el secreto.

Pixel elefante
fuente
5
Este es mi enfoque actual, sin embargo, tengo 3 pods diferentes que usan la misma lista de secretos expuestos como EnvVars. ¿Es posible definirlos una vez y exponerlos a las 3 vainas?
jävi
1
No que yo sepa.
Pixel Elephant
2
eso sería genial ... parece una gran cantidad de texto estándar para colocar las vars env en contenedores. @PixelElephant
AndrewMcLagan
@ jävi ¿Te refieres a controladores de replicación? Independientemente, no hay nada que vincule un mapa secreto / de configuración a un solo pod / RC / Deployment. Solo se define en el manifiesto como se indicó anteriormente y se puede montar en tantas cosas como desee.
aronchick
@aronchick Creo que están buscando esta característica: github.com/kubernetes/kubernetes/issues/26299 que parece que aterrizará pronto. Actualizaré la respuesta una vez que la función esté en una versión de lanzamiento de Kubernetes.
Pixel Elephant
36

Una nueva actualización para Kubernetes (v1.6) permite lo que solicitó (hace años).

Ahora puede usar algo envFromasí en su archivo yaml:

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

Donde los secretos de desarrollo son su secreto, puede crearlo de la siguiente manera:

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

Donde el contenido del archivo txt es un valor-clave:

DB_USER=username_here
DB_PASSWORD=password_here

Los documentos siguen siendo lagos de ejemplos, tuve que buscar muy duro en esos lugares:

O Duan
fuente
¿Puede compartir la documentación de Kubernetes sobre esto?
Artem Dolobanko
@ArtemDolobanko Editado, tenga en cuenta que esto todavía es nuevo y hay muchos documentos, puede encontrar muchas discusiones sobre el rastreador de problemas de Github si desea más detalles.
O Duan
@O Duan, ¿cómo pasaría un número de versión a la imagen de la ventana acoplable usando env
dev-stack
¿Qué pasa si tenemos que montar ese archivo de texto en alguna ubicación y la aplicación creará el entorno automáticamente desde allí?
Tara Prasad Gurung
2
¿Debería ser esto --from-env-file? El uso de --from-fileresultados en una clave (que lleva el nombre del archivo de entrada) con el contenido del archivo. El uso --from-env-fileexpande las claves dentro del archivo en el secreto. Consulte esta documentación de Google para obtener más información.
David
11

Al definir un pod para Kubernetes mediante un archivo YAML, no hay una forma directa de especificar un archivo diferente que contenga variables de entorno para un contenedor. El proyecto Kubernetes dice que mejorarán esta área en el futuro (consulte los documentos de Kubernetes ).

Mientras tanto, sugiero usar una herramienta de aprovisionamiento y hacer del pod YAML una plantilla. Por ejemplo, al usar Ansible, su archivo YAML de pod se vería así:

archivo my-pod.yaml.template:

apiVersion: v1
kind: Pod
...
spec:
  containers:
  ...
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: {{ mysql_root_pasword }}
    ...

Luego, su libro de jugadas de Ansible puede especificar la variable en mysql_root_passwordalgún lugar conveniente y sustituirla al crear el recurso, por ejemplo:

archivo 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

archivo my-env-vars-prod.yaml:

mysql_root_password: supersecret

archivo my-env-vars-test.yaml:

mysql_root_password: notsosecret

Ahora crea el recurso de pod ejecutando, por ejemplo:

ansible-playbook -e deploy=test my-playbook.yaml
Spencer Brown
fuente
4
Idealmente, debería poder definir un secreto (o los eventuales objetos de configuración que tendremos) y hacer que se inyecte como env vars. Lamentablemente, el trabajo aún no está terminado, por lo que votaré a favor.
Tim Hockin
Si usa ansible, tenemos una función común para implementar en kubernetes: github.com/ansibl8s/k8s-common . Entonces es muy fácil preparar nuevas aplicaciones, vea ejemplos de cómo usarlo en otro repositorio: github.com/ansibl8s
ant31
Espero que hagamos secretos en env vars para 1.2
Paul Morie
1
Tenga en cuenta que hay una propuesta de plantillas: github.com/kubernetes/kubernetes/blob/master/docs/proposals/…
luebken
¿Qué debo hacer si quiero usar kubectl-runpara pasar 20 variables env? ¿Por qué entonces no hacer 12factor más fácil?
holms
3

Esto funciona para mi:

archivo env-secret.yaml

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

y en el deployment.yamlopod.yaml

spec:
  ...
        volumeMounts:
        - name: foo
          mountPath: "/var/www/html/.env"
          subPath: .env
      volumes:
      - name: foo
        secret:
          secretName: env-secret
````
Madwyatt
fuente
¿Cómo usaría env para la imagen de la ventana acoplable para no tener que actualizar deployment.yaml cada vez que necesito incrementar una versión
dev-stack
0

Esta es una pregunta antigua pero tiene muchos espectadores, así que agrego mi respuesta. La mejor forma de separar la configuración de la implementación de K8 es utilizando Helm. Cada paquete de Helm puede tener un values.yamlarchivo y podemos usar fácilmente esos valores en el gráfico de Helm. Si tenemos una topología multicomponente, podemos crear un paquete Helm general y el paquete de valores padre también puede sobrescribir los archivos de valores secundarios.

AVarf
fuente
0

Esta es una pregunta antigua, pero permítanme describir mi respuesta para futuros principiantes.

Puede utilizar kustomize configMapGenerator.

configMapGenerator:
  - name: example
    env: dev.env

y consulte este configMap / example en la definición de pod

sgsh
fuente