Kubernetes tương đương với env-file trong Docker


84

Lý lịch:

Hiện tại, chúng tôi đang sử dụng Docker và Docker Compose cho các dịch vụ của mình. Chúng tôi đã ngoại hóa cấu hình cho các môi trường khác nhau thành các tệp xác định các biến môi trường được ứng dụng đọc. Ví dụ một prod.envtệp:

ENV_VAR_ONE=Something Prod
ENV_VAR_TWO=Something else Prod

và một test.envtệp:

ENV_VAR_ONE=Something Test
ENV_VAR_TWO=Something else Test

Vì vậy, chúng ta có thể chỉ cần sử dụng prod.envhoặc test.envtệp khi khởi động vùng chứa:

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

Ứng dụng của chúng tôi sau đó chọn cấu hình của nó dựa trên các biến môi trường được xác định trong prod.env.

Câu hỏi:

  1. Có cách nào để cung cấp các biến môi trường từ một tệp trong Kubernetes (ví dụ: khi xác định một nhóm) thay vì mã hóa cứng chúng như thế này không:
apiVersion: v1
loại: Pod
metadata: 
  nhãn: 
    ngữ cảnh: docker-k8s-lab
    tên: mysql-pod
  tên: mysql-pod
đặc điểm kỹ thuật: 
  hộp đựng: 
    - 
      vi: 
        - 
          tên: MYSQL_USER
          giá trị: mysql
        - 
          tên: MYSQL_PASSWORD
          giá trị: mysql
        - 
          tên: MYSQL_DATABASE
          giá trị: mẫu
        - 
          tên: MYSQL_ROOT_PASSWORD
          giá trị: supersecret
      hình ảnh: "mysql: mới nhất"
      tên: mysql
      các cổng: 
        - 
          containerPort: 3306
  1. Nếu điều này là không thể, cách tiếp cận được đề xuất là gì?

Tôi cũng đang tìm kiếm một cái gì đó như thế này. Tôi không muốn tạo Secrethoặc ConfigMaptài nguyên vì đây chỉ là tạm thời và sử dụng để thử nghiệm. Tôi có quyền hạn chế trong cụm k8s. Tôi có thể tạo Secrettài nguyên nhưng tôi sẽ không thể xóa chúng sau khi nó đã được tạo.
alltej

Câu trả lời:


114

Bạn có thể điền các biến môi trường của vùng chứa thông qua việc sử dụng Secrets hoặc ConfigMaps . Sử dụng Bí mật khi dữ liệu bạn đang làm việc nhạy cảm (ví dụ: mật khẩu) và ConfigMaps khi không.

Trong định nghĩa Pod của bạn, chỉ định rằng vùng chứa phải lấy các giá trị từ một Bí mật:

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

Lưu ý rằng cú pháp này chỉ khả dụng trong Kubernetes 1.6 trở lên. Trên phiên bản Kubernetes cũ hơn, bạn sẽ phải chỉ định từng giá trị theo cách thủ công, ví dụ:

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

(Lưu ý rằng envlấy một mảng làm giá trị)

Và lặp lại cho mọi giá trị.

Cho dù bạn sử dụng cách tiếp cận nào, giờ đây bạn có thể xác định hai Bí mật khác nhau, một dành cho sản xuất và một dành cho nhà phát triển.

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

Và triển khai bí mật chính xác cho đúng cụm Kubernetes:

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

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

Bây giờ bất cứ khi nào một Pod khởi động nó sẽ điền các biến môi trường của nó từ các giá trị được chỉ định trong Bí mật.


5
Đây là cách tiếp cận hiện tại của tôi, tuy nhiên tôi có 3 nhóm khác nhau sử dụng cùng một danh sách bí mật được tiết lộ như EnvVars. Có thể xác định chúng một lần và cho chúng tiếp xúc với 3 vỏ không?
jävi

1
Không phải là tôi biết.
Pixel Elephant

2
điều đó sẽ rất tuyệt vời ... có vẻ như phân bổ boilerplate để đưa các env vars vào các thùng chứa. @PixelElephant
AndrewMcLagan

@ jävi Ý bạn là bộ điều khiển sao chép? Bất kể, không có gì ràng buộc một bản đồ bí mật / cấu hình với một pod / RC / Triển khai. Nó chỉ được định nghĩa trong tệp kê khai như trên và có thể được gắn vào bao nhiêu thứ bạn muốn.
aronchick

@aronchick Tôi tin rằng họ đang tìm kiếm tính năng này: github.com/kubernetes/kubernetes/issues/26299 , có vẻ như nó sẽ sớm hạ cánh. Tôi sẽ cập nhật câu trả lời khi tính năng này có trong phiên bản Kubernetes được phát hành.
Pixel Elephant,

36

Bản cập nhật mới cho Kubernetes (v1.6) cho phép những gì bạn yêu cầu (nhiều năm trước).

Bây giờ bạn có thể sử dụng envFromnhư thế này trong tệp yaml của mình:

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

Nơi bí mật phát triển là bí mật của bạn, bạn có thể tạo ra nó bằng cách:

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

Trong đó nội dung tệp txt là một khóa-giá trị:

DB_USER=username_here
DB_PASSWORD=password_here

Các tài liệu vẫn còn là những ví dụ, tôi đã phải tìm kiếm thực sự khó khăn về những nơi đó:


Bạn có thể chia sẻ tài liệu Kubernetes về điều này không?
Artem Dolobanko

@ArtemDolobanko Đã chỉnh sửa, hãy nhớ rằng điều này vẫn còn mới và hồ sơ tài liệu, bạn có thể tìm thấy nhiều cuộc thảo luận trên trình theo dõi vấn đề của Github nếu bạn muốn biết thêm chi tiết.
Hoặc Duẩn

@Or Duẩn làm thế nào tôi sẽ vượt qua một số phiên bản để hình ảnh Docker sử dụng env
dev-stack

gì xảy ra nếu chúng ta phải gắn kết rằng tập tin văn bản để một số vị trí và ứng dụng sẽ tạo ra các env tự động từ đó
Tara Prasad Gurung

2
Điều này có nên --from-env-filekhông? Sử dụng --from-filekết quả trong một khóa (được đặt tên theo tệp đầu vào) với nội dung của tệp. Sử dụng --from-env-filesẽ mở rộng các khóa bên trong tệp thành bí mật. Xem tài liệu này của Google để biết thêm.
David

11

Khi xác định một nhóm cho Kubernetes bằng tệp YAML, không có cách nào trực tiếp để chỉ định một tệp khác chứa các biến môi trường cho vùng chứa. Dự án Kubernetes cho biết họ sẽ cải thiện lĩnh vực này trong tương lai (xem tài liệu của Kubernetes ).

Trong thời gian chờ đợi, tôi khuyên bạn nên sử dụng công cụ cung cấp và làm cho nhóm YAML trở thành mẫu. Ví dụ: sử dụng Ansible, tệp YAML nhóm của bạn sẽ trông giống như sau:

tập tin my-pod.yaml.template:

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

Sau đó, playbook Ansible của bạn có thể chỉ định biến mysql_root_passwordở đâu đó thuận tiện và thay thế nó khi tạo tài nguyên, ví dụ:

tập tin 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

tập tin my-env-vars-prod.yaml:

mysql_root_password: supersecret

tập tin my-env-vars-test.yaml:

mysql_root_password: notsosecret

Bây giờ bạn tạo tài nguyên nhóm bằng cách chạy, ví dụ:

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

4
Lý tưởng nhất là bạn có thể xác định một Bí mật (hoặc các đối tượng cấu hình cuối cùng mà chúng ta sẽ có) và đã đưa nó vào dưới dạng env vars. Thật không may là công việc vẫn chưa được hoàn thành, vì vậy tôi đang bỏ phiếu cho điều này.
Tim Hockin

Nếu bạn đang sử dụng ansible, chúng tôi có vai trò chung là triển khai trên kubernetes: github.com/ansibl8s/k8s-common . Sau đó, nó rất dễ dàng để chuẩn bị các ứng dụng mới, xem exemples làm thế nào để sử dụng nó trong repo khác: github.com/ansibl8s
ant31

Tôi hy vọng rằng chúng tôi sẽ làm bí mật trong env VAR cho 1.2
Paul Morie

1
Lưu ý rằng có một đề xuất cho các mẫu: github.com/kubernetes/kubernetes/blob/master/docs/proposal/…
luebken

Tôi phải làm gì nếu tôi muốn sử dụng kubectl-runđể chuyển 20 biến env ??? tại sao sau đó không làm 12factor dễ dàng hơn ??
holms

3

Điều này phù hợp với tôi:

tập tin env-secret.yaml

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

và vào deployment.yamlhoặcpod.yaml

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

làm thế nào tôi sẽ sử dụng env cho hình ảnh Docker vì vậy tôi không cần phải cập nhật deployment.yaml mỗi khi tôi cần phải tăng một phiên bản
dev-stack

0

Đây là một câu hỏi cũ nhưng nó có rất nhiều người xem nên tôi thêm câu trả lời của mình. Cách tốt nhất để tách cấu hình khỏi việc triển khai K8s là sử dụng Helm. Mỗi gói Helm có thể có một values.yamltệp và chúng ta có thể dễ dàng sử dụng các giá trị đó trong biểu đồ Helm. Nếu chúng ta có cấu trúc liên kết nhiều thành phần, chúng ta có thể tạo một gói Helm ô và gói giá trị mẹ cũng có thể ghi đè lên các tệp giá trị con.


0

Đây là một câu hỏi cũ nhưng hãy để tôi mô tả câu trả lời của tôi cho người mới bắt đầu trong tương lai.

Bạn có thể sử dụng kustomize configMapGenerator.

configMapGenerator:
  - name: example
    env: dev.env

và tham khảo configMap / example này trong định nghĩa nhóm

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.