Kubernetes-еквівалент env-файлу в Docker


84

Передумови:

В даний час ми використовуємо 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.

Запитання:

  1. Чи є спосіб надати змінні середовища з файлу в Kubernetes (наприклад, при визначенні pod) замість жорсткого їх кодування таким чином:
apiVersion: v1
вид: Под
метадані: 
  етикетки: 
    контекст: docker-k8s-lab
    назва: mysql-pod
  ім'я: mysql-pod
специфікація: 
  контейнери: 
    - 
      env: 
        - 
          ім'я: MYSQL_USER
          значення: mysql
        - 
          ім'я: MYSQL_PASSWORD
          значення: mysql
        - 
          ім'я: MYSQL_DATABASE
          значення: зразок
        - 
          ім'я: MYSQL_ROOT_PASSWORD
          значення: суперсекрет
      зображення: "mysql: останнє"
      ім'я: mysql
      порти: 
        - 
          контейнер Порт: 3306
  1. Якщо це неможливо, який запропонований підхід?

Я теж шукаю щось подібне. Я не хочу створювати ресурс Secretабо ConfigMapресурс, оскільки це лише тимчасово і використовується для тестування. У мене обмежені дозволи в кластері k8s. Можливо, я зможу створити Secretресурс, але не зможу видалити його, коли він уже створений.
alltej

Відповіді:


114

Ви можете заповнити змінні середовища контейнера за допомогою Secrets або ConfigMaps . Використовуйте Secrets, коли дані, з якими ви працюєте, є конфіденційними (наприклад, паролі), а ConfigMaps - коли це не так.

У своєму визначенні Pod вкажіть, що контейнер повинен витягувати значення з секрету:

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.


5
Це мій поточний підхід, однак у мене є 3 різні стручки, що використовують той самий перелік секретів, що і EnvVars. Чи можна визначити їх один раз і виставити на 3 стручки?
Яві

1
Не те, що я знаю.
Pixel Elephant

2
це було б настільки чудово ... здається, багато зразка, щоб перевезти вантаж в контейнери. @PixelElephant
AndrewMcLagan

@ jävi Ви маєте на увазі контролери реплікації? Незважаючи на це, немає нічого, що прив’язує таємну / конфігураційну карту до єдиного під / RC / Розгортання. Він просто визначений у маніфесті, як зазначено вище, і може бути змонтований до будь-якої кількості речей, скільки завгодно.
aronchick

@aronchick Я вважаю, що вони шукають цю функцію: github.com/kubernetes/kubernetes/issues/26299, яка, схоже, незабаром приземлиться. Я оновлю відповідь, як тільки функція з’явиться у випущеній версії Kubernetes.
Pixel Elephant,

36

Нове оновлення Kubernetes (v1.6) дозволяє те, про що ви просили (роки тому).

Тепер ви можете використовувати ось envFromтаке у своєму файлі yaml:

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

Де секрети розвитку - це ваша таємниця, ви можете створити їх, виконавши:

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

Де вміст файлу txt є ключовим значенням:

DB_USER=username_here
DB_PASSWORD=password_here

Документи все ще є прикладами прикладів, мені довелося дуже важко шукати ці місця:


Чи можете ви поділитися документацією Kubernetes щодо цього?
Артем Долобанко

@ArtemDolobanko Відредаговано, майте на увазі, це все ще нове, і озера документів, ви можете знайти багато обговорень щодо відстеження питань Github, якщо вам потрібні докладніші відомості.
Або Дуан

@ Або Дуане, як би я передав номер версії на зображення
dev-stack

що, якщо нам доведеться змонтувати цей текстовий файл в якомусь місці, і додаток автоматично створить env звідти
Tara Prasad Gurung

2
Це має бути --from-env-file? Використання --from-fileрезультатів в одному ключі (названому за вхідним файлом) із вмістом файлу. Використання --from-env-fileрозширює ключі всередині файлу в секрет. Докладніше див. У цій документації Google .
Девід

11

При визначенні стручка для Kubernetes за допомогою файлу YAML немає прямого способу вказати інший файл, що містить змінні середовища для контейнера. Проект Kubernetes каже, що вони покращать цю сферу в майбутньому (див. Документи Kubernetes ).

Тим часом я пропоную скористатися інструментом підготовки та зробити шаблон YAML стручка. Наприклад, використовуючи Ansible, ваш файл YAML pod виглядатиме так:

файл my-pod.yaml.template:

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

Тоді ваша книга Ansible може вказати змінну 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

4
В ідеалі ви повинні мати змогу визначити Секрет (або можливі об'єкти конфігурації, які ми матимемо) і вводити їх як env vars. На жаль, ця робота ще не виконана, тому я голосую за це.
Тім Хокін

Якщо ви використовуєте ansible, у нас є загальна роль для розгортання на kubernetes: github.com/ansibl8s/k8s-common . Тоді дуже просто підготувати нові програми, див. Приклади, як використовувати їх в інших репо: github.com/ansibl8s
ant31

Я сподіваюся, що ми будемо робити таємниці в env vars протягом 1.2
Paul Morie

1
Зверніть увагу, що є пропозиція щодо шаблонів: github.com/kubernetes/kubernetes/blob/master/docs/proposals/…
luebken

що робити, якщо я хочу використовувати kubectl-runдля передачі 20 змінних env ??? чому тоді не зробити 12factor простіше ??
Холмс

3

Це працює для мене:

файл 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
````

як мені використовувати env для образу докера, щоб мені не довелося оновлювати deployment.yaml щоразу, коли мені потрібно збільшити версію
dev-stack

0

Це давнє запитання, але у нього багато глядачів, тому я додаю свою відповідь. Найкращий спосіб відокремити конфігурацію від реалізації K8 - це використання Helm. Кожен пакет Helm може мати values.yamlфайл, і ми можемо легко використовувати ці значення в діаграмі Helm. Якщо у нас є багатокомпонентна топологія, ми можемо створити парасольковий пакет Helm, а батьківський пакет значень також може перезаписати файли дочірніх значень.


0

Це старе запитання, але дозвольте мені описати свою відповідь для майбутнього новачка.

Ви можете використовувати kustomize configMapGenerator.

configMapGenerator:
  - name: example
    env: dev.env

і зверніться до цього configMap / прикладу у визначенні pod

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.