Equivalente Kubernetes del file env in Docker


87

Sfondo:

Attualmente stiamo utilizzando Docker e Docker Compose per i nostri servizi. Abbiamo esternalizzato la configurazione per diversi ambienti in file che definiscono le variabili di ambiente lette dall'applicazione. Ad esempio un prod.envfile:

ENV_VAR_ONE=Something Prod
ENV_VAR_TWO=Something else Prod

e un test.envfile:

ENV_VAR_ONE=Something Test
ENV_VAR_TWO=Something else Test

Quindi possiamo semplicemente usare il file prod.envo test.envall'avvio del contenitore:

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

La nostra applicazione quindi prende la sua configurazione in base alle variabili d'ambiente definite in prod.env.

Domande:

  1. C'è un modo per fornire variabili di ambiente da un file in Kubernetes (ad esempio quando si definisce un pod) invece di codificarle come segue:
apiVersion: v1
tipo: Pod
metadati: 
  etichette: 
    contesto: docker-k8s-lab
    nome: mysql-pod
  nome: mysql-pod
spec: 
  contenitori: 
    - 
      env: 
        - 
          nome: MYSQL_USER
          valore: mysql
        - 
          nome: MYSQL_PASSWORD
          valore: mysql
        - 
          nome: MYSQL_DATABASE
          valore: campione
        - 
          nome: MYSQL_ROOT_PASSWORD
          valore: supersecret
      immagine: "mysql: latest"
      nome: mysql
      porti: 
        - 
          containerPort: 3306
  1. Se ciò non è possibile, qual è l'approccio suggerito?

Sto anche cercando qualcosa di simile. Non voglio creare una risorsa Secreto ConfigMapperché è solo temporanea e viene utilizzata per il test. Ho autorizzazioni limitate nel cluster k8s. Forse potrò creare una Secretrisorsa ma non potrò eliminarla una volta che è già stata creata.
alltej

Risposte:


116

È possibile popolare le variabili di ambiente di un contenitore tramite l'uso di Secrets o ConfigMaps . Usa Secrets quando i dati con cui stai lavorando sono sensibili (ad esempio password) e ConfigMaps quando non lo sono.

Nella definizione del pod specifica che il contenitore deve estrarre i valori da un segreto:

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

Tieni presente che questa sintassi è disponibile solo in Kubernetes 1.6 o versioni successive. In una versione precedente di Kubernetes dovrai specificare ogni valore manualmente, ad esempio:

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

(Nota che envprendi un array come valore)

E ripetendo per ogni valore.

Qualunque sia l'approccio utilizzato, ora è possibile definire due diversi segreti, uno per la produzione e uno per lo sviluppo.

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 distribuisci il segreto corretto nel cluster Kubernetes corretto:

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

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

Ora ogni volta che un Pod viene avviato, popolerà le sue variabili di ambiente dai valori specificati nel Segreto.


5
Questo è il mio approccio attuale, tuttavia ho 3 pod diversi che utilizzano lo stesso elenco di segreti esposti come EnvVars. È possibile definirli una volta ed esporli ai 3 pod?
jävi

1
Non che io sappia.
Pixel Elephant

2
sarebbe fantastico ... sembra un sacco di boilerplate per mettere gli env vars nei contenitori. @PixelElephant
AndrewMcLagan

@ jävi Vuoi dire controller di replica? Indipendentemente da ciò, non c'è nulla che colleghi una mappa segreta / di configurazione a un singolo pod / RC / distribuzione. È semplicemente definito nel manifest come sopra e può essere montato su tutte le cose che desideri.
aronchick

@aronchick Credo che stiano cercando questa funzione: github.com/kubernetes/kubernetes/issues/26299 che sembra che arriverà presto. Aggiornerò la risposta una volta che la funzionalità sarà disponibile in una versione rilasciata di Kubernetes.
Pixel Elephant

36

Un nuovo aggiornamento per Kubernetes (v1.6) consente ciò che hai richiesto (anni fa).

Ora puoi usare envFromquesto nel tuo file yaml:

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

Laddove i segreti dello sviluppo sono il tuo segreto, puoi crearlo:

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

Dove il contenuto del file txt è un valore-chiave:

DB_USER=username_here
DB_PASSWORD=password_here

I documenti sono ancora laghi di esempi, ho dovuto cercare molto duramente in quei luoghi:


Puoi condividere la documentazione di Kubernetes su questo?
Artem Dolobanko

@ArtemDolobanko Modificato, tieni presente che questo è ancora nuovo e laghi di documenti, puoi trovare molte discussioni sul tracker dei problemi di Github se vuoi maggiori dettagli.
Oppure Duan

@ Oppure Duan come passerei un numero di versione all'immagine docker usando env
dev-stack

e se dovessimo montare quel file di testo in una posizione e l'app creerà automaticamente l'env da lì
Tara Prasad Gurung

2
Questo dovrebbe essere --from-env-file? Utilizzo dei --from-filerisultati in una chiave (denominata in base al file di input) con il contenuto del file. L'utilizzo --from-env-fileespande le chiavi all'interno del file nel segreto. Consulta questa documentazione di Google per ulteriori informazioni.
David

11

Quando si definisce un pod per Kubernetes utilizzando un file YAML, non esiste un modo diretto per specificare un file diverso contenente variabili di ambiente per un contenitore. Il progetto Kubernetes afferma che migliorerà quest'area in futuro (vedere la documentazione di Kubernetes ).

Nel frattempo, suggerisco di utilizzare uno strumento di provisioning e di rendere il pod YAML un modello. Ad esempio, utilizzando Ansible il tuo file pod YAML sarebbe simile a:

file my-pod.yaml.template:

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

Quindi il tuo playbook Ansible può specificare la variabile in un mysql_root_passwordpunto conveniente e sostituirla durante la creazione della risorsa, ad esempio:

file 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

file my-env-vars-prod.yaml:

mysql_root_password: supersecret

file my-env-vars-test.yaml:

mysql_root_password: notsosecret

Ora crei la risorsa pod eseguendo, ad esempio:

ansible-playbook -e deploy=test my-playbook.yaml

4
Idealmente dovresti essere in grado di definire un Secret (o gli eventuali oggetti di configurazione che avremo) e averlo iniettato come env vars. Purtroppo quel lavoro non è ancora finito, quindi voto a favore.
Tim Hockin

Se utilizzi ansible, abbiamo un ruolo comune da distribuire su kubernetes: github.com/ansibl8s/k8s-common . Quindi è molto facile preparare nuove applicazioni, vedere esempi su come usarlo in altri repository: github.com/ansibl8s
ant31

Spero che faremo segreti in env vars per 1.2
Paul Morie

1
Tieni presente che esiste una proposta per i modelli: github.com/kubernetes/kubernetes/blob/master/docs/proposals/…
luebken

cosa devo fare se voglio utilizzare kubectl-runper passare 20 variabili env ??? perché allora non fare 12factor più facile ??
holms

5

Questo funziona per me:

file env-secret.yaml

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

e nel deployment.yamlopod.yaml

spec:
  ...
        volumeMounts:
        - name: foo
          mountPath: "/var/www/html/.env"
          subPath: .env
      volumes:
      - name: foo
        secret:
          secretName: env-secret
````

come dovrei usare env per l'immagine docker in modo da non dover aggiornare deployment.yaml ogni volta che ho bisogno di incrementare una versione
dev-stack

0

Questa è una vecchia domanda ma ha molti spettatori, quindi aggiungo la mia risposta. Il modo migliore per separare la configurazione dall'implementazione di K8 è usare Helm. Ogni pacchetto Helm può avere un values.yamlfile e possiamo facilmente utilizzare questi valori nel grafico Helm. Se disponiamo di una topologia multicomponente, possiamo creare un pacchetto Helm ombrello e il pacchetto dei valori padre può anche sovrascrivere i file dei valori figli.


0

Questa è una vecchia domanda, ma lasciatemi descrivere la mia risposta per il futuro principiante.

Puoi usare kustomize configMapGenerator.

configMapGenerator:
  - name: example
    env: dev.env

e fare riferimento a questo configMap / esempio nella definizione del pod


0

Ho fracassato la mia testa su questo per 2 ore. Ho trovato nei documenti una soluzione molto semplice per ridurre al minimo il mio (e si spera il tuo) dolore.

  • Mantieni env.prod, env.devcome li hai.

  • Usa uno script oneliner per importarli in yaml:

    kubectl create configmap my-dev-config --from-env-file=env.dev

    kubectl create configmap my-prod-config --from-env-file=env.prod

Puoi vedere il risultato (per una gratificazione immediata):

# You can also save this to disk
kubectl get configmap my-dev-config -o yaml

Come rubyist, personalmente trovo questa soluzione la DRYest in quanto hai un unico punto da mantenere (il file bash ENV, che è compatibile con le librerie Python / Ruby, ..) e poi lo YAMLize in una singola esecuzione.

Nota che devi mantenere pulito il tuo file ENV (ho molti commenti che hanno impedito che funzionasse, quindi ho dovuto anteporre a cat config.original | egrep -v "^#" | tee config.cleaned) ma questo non cambia sostanzialmente la complessità.

È tutto documentato qui

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.