Program Club

Docker의 env-file에 해당하는 Kubernetes

proclub 2020. 11. 17. 21:16
반응형

Docker의 env-file에 해당하는 Kubernetes


배경:

현재 우리는 서비스에 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의 파일 (예 : 포드를 정의 할 때)에서 환경 변수를 제공하는 방법이 있습니까?
apiVersion : v1
종류 : 포드
메타 데이터 : 
  라벨 : 
    컨텍스트 : docker-k8s-lab
    이름 : mysql-pod
  이름 : mysql-pod
투기: 
  용기 : 
    - 
      env : 
        - 
          이름 : MYSQL_USER
          값 : mysql
        - 
          이름 : MYSQL_PASSWORD
          값 : mysql
        - 
          이름 : MYSQL_DATABASE
          값 : 샘플
        - 
          이름 : MYSQL_ROOT_PASSWORD
          값 : 극비
      이미지 : "mysql : latest"
      이름 : mysql
      포트 : 
        - 
          containerPort : 3306
  1. 이것이 가능하지 않은 경우 제안 된 접근 방식은 무엇입니까?

Secrets 또는 ConfigMaps 사용을 통해 컨테이너의 환경 변수를 채울 수 있습니다 . 작업중인 데이터가 민감한 경우 (예 : 비밀번호) Secrets를 사용하고 그렇지 않은 경우 ConfigMaps를 사용합니다.

포드 정의에서 컨테이너가 보안 비밀에서 값을 가져 오도록 지정합니다.

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

이제 포드가 시작될 때마다 보안 비밀에 지정된 값으로 환경 변수를 채 웁니다.


Kubernetes (v1.6)의 새로운 업데이트를 통해 몇 년 전 요청한 내용을 사용할 수 있습니다.

이제 envFromyaml 파일에서 다음과 같이 사용할 수 있습니다 .

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

개발 비밀이 비밀 인 경우 다음과 같이 만들 수 있습니다.

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

txt 파일 콘텐츠가 키-값인 경우 :

DB_USER=username_here
DB_PASSWORD=password_here

The docs are still lakes of examples, I had to search really hard on those places:


When defining a pod for Kubernetes using a YAML file, there's no direct way to specify a different file containing environment variables for a container. The Kubernetes project says they will improve this area in the future (see Kubernetes docs).

In the meantime, I suggest using a provisioning tool and making the pod YAML a template. For example, using Ansible your pod YAML file would look like:

file my-pod.yaml.template:

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

Then your Ansible playbook can specify the variable mysql_root_password somewhere convenient, and substitute it when creating the resource, for example:

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

Now you create the pod resource by running, for example:

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

This works for me:

file env-secret.yaml

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

and into the deployment.yaml or pod.yaml

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

This is an old question but it has a lot of viewers so I add my answer. The best way to separate the configuration from K8s implementation is using Helm. Each Helm package can have a values.yaml file and we can easily use those values in the Helm chart. If we have a multi-component topology we can create an umbrella Helm package and the parent values package also can overwrite the children values files.

참고URL : https://stackoverflow.com/questions/33478555/kubernetes-equivalent-of-env-file-in-docker

반응형