Kubernetes-Äquivalent zur env-Datei in Docker

84

Hintergrund:

Derzeit verwenden wir Docker und Docker Compose für unsere Dienste. Wir haben die Konfiguration für verschiedene Umgebungen in Dateien ausgelagert, die Umgebungsvariablen definieren, die von der Anwendung gelesen werden. Zum Beispiel eine prod.envDatei:

ENV_VAR_ONE=Something Prod
ENV_VAR_TWO=Something else Prod

und eine test.envDatei:

ENV_VAR_ONE=Something Test
ENV_VAR_TWO=Something else Test

Daher können wir beim Starten des Containers einfach die Datei prod.envoder test.envverwenden:

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

Unsere Anwendung übernimmt dann ihre Konfiguration basierend auf den in definierten Umgebungsvariablen prod.env.

Fragen:

  1. Gibt es eine Möglichkeit, Umgebungsvariablen aus einer Datei in Kubernetes bereitzustellen (z. B. beim Definieren eines Pods), anstatt sie wie folgt fest zu codieren:
apiVersion: v1
Art: Pod
Metadaten: 
  Etiketten: 
    Kontext: Docker-K8s-Labor
    Name: MySQL-Pod
  Name: MySQL-Pod
spec: 
  Behälter: 
    - - 
      env: 
        - - 
          Name: MYSQL_USER
          Wert: MySQL
        - - 
          Name: MYSQL_PASSWORD
          Wert: MySQL
        - - 
          Name: MYSQL_DATABASE
          Wert: Probe
        - - 
          Name: MYSQL_ROOT_PASSWORD
          Wert: Supersekret
      Bild: "MySQL: Neueste"
      Name: MySQL
      Häfen: 
        - - 
          containerPort: 3306
  1. Wenn dies nicht möglich ist, welcher Ansatz wird vorgeschlagen?
Johan
quelle
Ich suche auch so etwas. Ich möchte keine Secretoder keine ConfigMapRessource erstellen, da dies nur vorübergehend ist und zum Testen verwendet wird. Ich habe eingeschränkte Berechtigungen im k8s-Cluster. Ich kann möglicherweise eine SecretRessource erstellen , aber ich kann sie nicht löschen, sobald sie bereits erstellt wurde.
Alltej

Antworten:

113

Sie können die Umgebungsvariablen eines Containers mithilfe von Secrets oder ConfigMaps füllen . Verwenden Sie Secrets, wenn die Daten, mit denen Sie arbeiten, vertraulich sind (z. B. Kennwörter), und ConfigMaps, wenn dies nicht der Fall ist.

Geben Sie in Ihrer Pod-Definition an, dass der Container Werte aus einem Geheimnis abrufen soll:

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

Beachten Sie, dass diese Syntax nur in Kubernetes 1.6 oder höher verfügbar ist. In einer früheren Version von Kubernetes müssen Sie jeden Wert manuell angeben, z.

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

(Beachten Sie, dass envein Array als Wert verwendet wird.)

Und für jeden Wert wiederholen.

Unabhängig davon, welchen Ansatz Sie verwenden, können Sie jetzt zwei verschiedene Geheimnisse definieren, eines für die Produktion und eines für den Entwickler.

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

Und stellen Sie das richtige Geheimnis für den richtigen Kubernetes-Cluster bereit:

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

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

Wenn ein Pod gestartet wird, werden seine Umgebungsvariablen mit den im Secret angegebenen Werten gefüllt.

Pixel Elefant
quelle
5
Dies ist mein aktueller Ansatz, ich habe jedoch 3 verschiedene Pods, die dieselbe Liste von Geheimnissen verwenden wie EnvVars. Ist es möglich, sie einmal zu definieren und sie den 3 Pods auszusetzen?
jävi
1
Nicht, dass ich davon Wüste.
Pixel Elephant
2
das wäre so toll ... scheint wie eine Menge Boilerplate, um die env vars in Container zu bekommen. @ PixelElephant
AndrewMcLagan
@ jävi Meinst du Replikationscontroller? Unabhängig davon gibt es nichts, was eine geheime / Konfigurationszuordnung an einen einzelnen Pod / RC / Deployment bindet. Es ist nur im Manifest wie oben definiert und kann an so viele Dinge angehängt werden, wie Sie möchten.
Aronchick
@aronchick Ich glaube, sie suchen nach dieser Funktion: github.com/kubernetes/kubernetes/issues/26299, die so aussieht, als würde sie bald landen. Ich werde die Antwort aktualisieren, sobald die Funktion in einer veröffentlichten Version von Kubernetes enthalten ist.
Pixel Elephant
35

Ein neues Update für Kubernetes (v1.6) ermöglicht das, wonach Sie gefragt haben (vor Jahren).

Sie können jetzt envFromFolgendes in Ihrer Yaml-Datei verwenden:

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

Wo Entwicklungsgeheimnisse Ihr Geheimnis sind, können Sie es erstellen durch:

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

Wo der Inhalt der txt-Datei ein Schlüsselwert ist:

DB_USER=username_here
DB_PASSWORD=password_here

Die Dokumente sind immer noch Seen von Beispielen, ich musste wirklich hart an diesen Orten suchen:

Oder Duan
quelle
Können Sie die Kubernetes-Dokumentation dazu freigeben?
Artem Dolobanko
@ArtemDolobanko Bearbeitet, denken Sie daran, dass dies noch neu ist und Seen von Dokumenten. Sie können viele Diskussionen über Githubs Issues Tracker finden, wenn Sie weitere Details wünschen.
Oder Duan
@ Oder Duan, wie würde ich eine Versionsnummer an Docker-Image mit env
dev-stack
Was ist, wenn wir diese Textdatei an einem bestimmten Ort bereitstellen müssen und die App die Umgebung automatisch von dort aus erstellt
Tara Prasad Gurung,
2
Sollte das sein --from-env-file? Verwenden von --from-fileErgebnissen in einem Schlüssel (benannt nach der Eingabedatei) mit dem Inhalt der Datei. Mit --from-env-fileerweitert werden die Schlüssel in der Datei ins Geheimnis. Weitere Informationen finden Sie in dieser Google-Dokumentation .
David
11

Wenn Sie einen Pod für Kubernetes mithilfe einer YAML-Datei definieren, gibt es keine direkte Möglichkeit, eine andere Datei anzugeben, die Umgebungsvariablen für einen Container enthält. Das Kubernetes-Projekt sagt, dass sie diesen Bereich in Zukunft verbessern werden (siehe Kubernetes-Dokumente ).

In der Zwischenzeit schlage ich vor, ein Bereitstellungstool zu verwenden und den Pod YAML zu einer Vorlage zu machen. Wenn Sie beispielsweise Ansible verwenden, sieht Ihre Pod-YAML-Datei folgendermaßen aus:

Datei my-pod.yaml.template:

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

Dann kann Ihr Ansible-Playbook die Variable an einer mysql_root_passwordgeeigneten Stelle angeben und beim Erstellen der Ressource ersetzen, zum Beispiel:

Datei 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

Datei my-env-vars-prod.yaml:

mysql_root_password: supersecret

Datei my-env-vars-test.yaml:

mysql_root_password: notsosecret

Jetzt erstellen Sie die Pod-Ressource, indem Sie beispielsweise Folgendes ausführen:

ansible-playbook -e deploy=test my-playbook.yaml
Spencer Brown
quelle
4
Idealerweise sollten Sie in der Lage sein, ein Geheimnis (oder die eventuellen Konfigurationsobjekte, die wir haben werden) zu definieren und dieses als env vars injizieren zu lassen. Leider ist diese Arbeit noch nicht erledigt, deshalb stimme ich dafür.
Tim Hockin
Wenn Sie ansible verwenden, haben wir eine gemeinsame Rolle für die Bereitstellung auf kubernetes: github.com/ansibl8s/k8s-common . Dann ist es sehr einfach, neue Anwendungen vorzubereiten, siehe Beispiele, wie man sie in anderen Repos verwendet: github.com/ansibl8s
ant31
Ich hoffe, dass wir Geheimnisse in env vars für 1.2
Paul Morie
1
Beachten Sie, dass es einen Vorschlag für Vorlagen gibt: github.com/kubernetes/kubernetes/blob/master/docs/proposals/…
luebken
Was soll ich tun, wenn ich kubectl-run20 env-Variablen übergeben möchte ? warum dann nicht 12factor einfacher machen ??
Holms
2

Das funktioniert bei mir:

Datei env-secret.yaml

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

und in die deployment.yamloderpod.yaml

spec:
  ...
        volumeMounts:
        - name: foo
          mountPath: "/var/www/html/.env"
          subPath: .env
      volumes:
      - name: foo
        secret:
          secretName: env-secret
````
Madwyatt
quelle
Wie würde ich env für Docker-Image verwenden, damit ich nicht jedes Mal die Datei deploy.yaml aktualisieren muss, wenn ich eine Version inkrementieren muss
dev-stack
0

Dies ist eine alte Frage, aber sie hat viele Zuschauer, deshalb füge ich meine Antwort hinzu. Der beste Weg, um die Konfiguration von der K8-Implementierung zu trennen, ist die Verwendung von Helm. Jedes Helm-Paket kann eine values.yamlDatei enthalten, und wir können diese Werte problemlos im Helm-Diagramm verwenden. Wenn wir eine Mehrkomponententopologie haben, können wir ein Umbrella-Helm-Paket erstellen und das übergeordnete Wertepaket kann auch die untergeordneten Wertedateien überschreiben.

AVarf
quelle
0

Dies ist eine alte Frage, aber lassen Sie mich meine Antwort für zukünftige Anfänger beschreiben.

Sie können kustomize configMapGenerator verwenden.

configMapGenerator:
  - name: example
    env: dev.env

und verweisen Sie auf diese configMap / dieses Beispiel in der Pod-Definition

sgsh
quelle