Odpowiednik Kubernetes pliku env w Dockerze

84

Tło:

Obecnie w naszych usługach używamy Docker i Docker Compose. Udostępniliśmy konfigurację dla różnych środowisk do plików definiujących zmienne środowiskowe odczytywane przez aplikację. Na przykład prod.envplik:

ENV_VAR_ONE=Something Prod
ENV_VAR_TWO=Something else Prod

i test.envplik:

ENV_VAR_ONE=Something Test
ENV_VAR_TWO=Something else Test

W ten sposób możemy po prostu użyć pliku prod.envor test.envpodczas uruchamiania kontenera:

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

Nasza aplikacja następnie wybiera swoją konfigurację na podstawie zmiennych środowiskowych zdefiniowanych w prod.env.

Pytania:

  1. Czy istnieje sposób na zapewnienie zmiennych środowiskowych z pliku w Kubernetes (na przykład podczas definiowania poda) zamiast ich zakodowania na sztywno w następujący sposób:
apiVersion: v1
rodzaj: Pod
metadane: 
  etykiety: 
    kontekst: docker-k8s-lab
    nazwa: mysql-pod
  nazwa: mysql-pod
specyfikacja: 
  pojemniki: 
    - 
      env: 
        - 
          nazwa: MYSQL_USER
          wartość: mysql
        - 
          nazwa: MYSQL_PASSWORD
          wartość: mysql
        - 
          nazwa: MYSQL_DATABASE
          wartość: próbka
        - 
          nazwa: MYSQL_ROOT_PASSWORD
          wartość: supersecret
      image: "mysql: najnowsze"
      nazwa: mysql
      porty: 
        - 
          kontenerPort: 3306
  1. Jeśli nie jest to możliwe, jakie jest sugerowane podejście?
Johan
źródło
Ja też czegoś takiego szukam. Nie chcę tworzyć zasobu Secretlub, ConfigMapponieważ jest to tylko tymczasowe i używane do testowania. Mam ograniczone uprawnienia w klastrze k8s. Być może uda mi się utworzyć Secretzasób, ale nie będę mógł ich usunąć, gdy zostanie już utworzony.
alltej

Odpowiedzi:

114

Możesz wypełnić zmienne środowiskowe kontenera za pomocą obiektów Secrets lub ConfigMaps . Używaj Secrets, gdy dane, z którymi pracujesz, są wrażliwe (np. Hasła), oraz ConfigMaps, gdy nie są.

W definicji poda określ, że kontener powinien pobierać wartości z klucza tajnego:

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

Zauważ, że ta składnia jest dostępna tylko w Kubernetes 1.6 lub nowszym. We wcześniejszej wersji Kubernetes będziesz musiał określić każdą wartość ręcznie, np .:

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

(Zauważ, że envweź tablicę jako wartość)

I powtarzanie dla każdej wartości.

Niezależnie od zastosowanego podejścia, możesz teraz zdefiniować dwa różne sekrety, jeden dla produkcji, a drugi dla programistów.

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

I wdróż poprawne hasło w odpowiednim klastrze Kubernetes:

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

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

Teraz za każdym razem, gdy Pod zostanie uruchomiony, zapełni swoje zmienne środowiskowe z wartości określonych w sekrecie.

Pixel Elephant
źródło
5
To jest moje obecne podejście, jednak mam 3 różne pody używające tej samej listy sekretów ujawnionych co EnvVars. Czy można je raz zdefiniować i wystawić na działanie 3 strąków?
jävi
1
Nie żebym o tym wiedział.
Pixel Elephant
2
byłoby tak wspaniale ... wygląda na to, że przydział gotowych płytek do umieszczenia w pojemnikach w pojemnikach. @PixelElephant
AndrewMcLagan
@ jävi Czy masz na myśli kontrolery replikacji? Niezależnie od tego nie ma nic wiążącego mapę tajną / konfiguracyjną z pojedynczym pod / RC / Deployment. Jest po prostu zdefiniowany w manifeście jak powyżej i można go zamontować do dowolnej liczby rzeczy.
aronchick,
@aronchick Myślę, że szukają tej funkcji: github.com/kubernetes/kubernetes/issues/26299, która wygląda na to, że wkrótce wyląduje. Zaktualizuję odpowiedź, gdy funkcja będzie dostępna w wydanej wersji Kubernetes.
Pixel Elephant
36

Nowa aktualizacja Kubernetes (v1.6) pozwala na to, o co prosiłeś (lata temu).

Możesz teraz użyć envFromtego w swoim pliku yaml:

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

Tam, gdzie tajemnice rozwoju są twoim sekretem, możesz je stworzyć przez:

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

Gdzie zawartość pliku txt to para klucz-wartość:

DB_USER=username_here
DB_PASSWORD=password_here

Dokumenty wciąż są jeziorami przykładów, w tych miejscach musiałem bardzo ciężko szukać:

Albo Duan
źródło
Czy możesz udostępnić dokumentację Kubernetes na ten temat?
Artem Dolobanko
@ArtemDolobanko Edytowano, pamiętaj, że to wciąż nowość i jeziora dokumentów, możesz znaleźć wiele dyskusji na temat śledzenia problemów na Github, jeśli chcesz uzyskać więcej informacji.
Lub Duan
@Or Duan jak przekazać numer wersji do obrazu Dockera za pomocą env
dev-stack
co jeśli będziemy musieli zamontować ten plik tekstowy w jakimś miejscu, a aplikacja automatycznie utworzy z tego miejsca plik env
Tara Prasad Gurung,
2
Czy tak powinno być --from-env-file? Użycie --from-filewyników w jednym kluczu (nazwanym tak jak plik wejściowy) z zawartością pliku. Użycie --from-env-filerozszerza klucze wewnątrz pliku do sekretu. Więcej informacji znajdziesz w tej dokumentacji Google .
David
11

Podczas definiowania pod dla Kubernetes przy użyciu pliku YAML nie ma bezpośredniego sposobu określenia innego pliku zawierającego zmienne środowiskowe dla kontenera. Projekt Kubernetes mówi, że poprawią ten obszar w przyszłości (zobacz dokumentację Kubernetes ).

W międzyczasie sugeruję użycie narzędzia do obsługi administracyjnej i uczynienie pod YAML szablonu. Na przykład, używając Ansible, twój plik pod YAML wyglądałby tak:

plik my-pod.yaml.template:

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

Następnie Twój Playbook Ansible może określić zmienną mysql_root_passwordw dogodnym miejscu i zastąpić ją podczas tworzenia zasobu, na przykład:

plik 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

plik my-env-vars-prod.yaml:

mysql_root_password: supersecret

plik my-env-vars-test.yaml:

mysql_root_password: notsosecret

Teraz utworzysz zasób pod, uruchamiając na przykład:

ansible-playbook -e deploy=test my-playbook.yaml
Spencer Brown
źródło
4
Idealnie byłoby, gdybyś był w stanie zdefiniować Secret (lub ewentualne obiekty konfiguracyjne, które będziemy mieć) i wstrzyknąć go jako zmienne env. Niestety ta praca jeszcze się nie skończyła, więc głosuję za tym.
Tim Hockin
Jeśli używasz ansible, mamy wspólną rolę do wdrożenia na kubernetes: github.com/ansibl8s/k8s-common . Wtedy bardzo łatwo jest przygotować nowe aplikacje, zobacz przykłady, jak używać go w innym repozytorium: github.com/ansibl8s
ant31
Mam nadzieję, że będziemy robić sekrety w warunkach środowiskowych dla 1.2
Paul Morie
1
Zauważ, że istnieje propozycja szablonów: github.com/kubernetes/kubernetes/blob/master/docs/propiments/ ...
luebken
co powinienem zrobić, jeśli chcę użyć kubectl-rundo przekazania 20 zmiennych env? dlaczego więc nie zrobić 12factor łatwiej?
holms
3

To działa dla mnie:

plik env-secret.yaml

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

i do deployment.yamllubpod.yaml

spec:
  ...
        volumeMounts:
        - name: foo
          mountPath: "/var/www/html/.env"
          subPath: .env
      volumes:
      - name: foo
        secret:
          secretName: env-secret
````
madwyatt
źródło
jak użyłbym środowiska env dla obrazu Docker, aby nie musieć aktualizować pliku deployment.yaml za każdym razem, gdy potrzebuję zwiększyć wersję
dev-stack
0

To stare pytanie, ale ma wielu widzów, więc dodaję odpowiedź. Najlepszym sposobem na oddzielenie konfiguracji od implementacji K8s jest użycie Helm. Każdy pakiet Helm może mieć values.yamlplik i możemy łatwo użyć tych wartości na wykresie Helm. Jeśli mamy topologię wieloskładnikową, możemy utworzyć pakiet parasolowy Helm, a pakiet wartości nadrzędnych może również nadpisać pliki wartości potomnych.

AVarf
źródło
0

To stare pytanie, ale pozwól, że opiszę moją odpowiedź dla przyszłych początkujących.

Możesz użyć kustomize configMapGenerator.

configMapGenerator:
  - name: example
    env: dev.env

i odnieś ten configMap / przykład w definicji poda

sgsh
źródło