如何使用 Helm 图表拉取环境变量

How to pull environment variables with Helm charts

我在 Helm 图表的模板目录中有我的 deployment.yaml 文件,其中有几个容器的环境变量我将 运行 使用 Helm。

现在我希望能够从掌舵的任何机器本地提取环境变量 运行 这样我就可以用这种方式隐藏秘密。

当我使用 Helm 到 运行 应用程序时,如何传入它并让 helm 在本地获取环境变量?

这是我的 deployment.yaml 文件的一部分

...
...
    spec:
      restartPolicy: Always
      containers:
        - name: sample-app
          image: "sample-app:latest"
          imagePullPolicy: Always
          env:          
            - name: "USERNAME"
              value: "app-username"
            - name: "PASSWORD"
              value: "28sin47dsk9ik"
...
...

当我 运行 helm 时,如何从本地环境变量中提取 USERNAME 和 PASSWORD 的值?

这可能吗?如果是,那我该怎么做?

您可以 export 变量并在 运行 宁 helm install 时使用它。

在此之前,您必须修改您的图表,以便在安装时该值可以是 set

如果您已经知道如何设置模板字段,请跳过此部分。


因为不想暴露数据,所以最好在kubernetes中保存为secret。

首先,将这两行添加到您的 Values 文件中,以便可以从外部设置这两个值。

username: root
password: password

现在,在 template 文件夹中添加一个 secret.yaml 文件。并将此代码片段复制到该文件中。

apiVersion: v1
kind: Secret
metadata:
  name: {{ .Release.Name }}-auth
data:
  password: {{ .Values.password | b64enc }}
  username: {{ .Values.username | b64enc }}

现在调整您的部署 yaml 模板并在 env 部分进行更改,像这样

...
...
    spec:
      restartPolicy: Always
      containers:
        - name: sample-app
          image: "sample-app:latest"
          imagePullPolicy: Always
          env:          
          - name: "USERNAME"
            valueFrom:
              secretKeyRef:
                key:  username
                name: {{ .Release.Name }}-auth
          - name: "PASSWORD"
            valueFrom:
              secretKeyRef:
                key:  password
                name: {{ .Release.Name }}-auth
...
...

如果您已针对 --set 标志正确修改模板, 您可以使用环境变量进行设置。

$ export USERNAME=root-user

现在在 运行ning helm 安装时使用这个变量,

$ helm install --set username=$USERNAME ./mychart

如果你运行这个helm install处于dry-run模式,你可以验证更改,

$ helm install --dry-run --set username=$USERNAME --debug ./mychart
[debug] Created tunnel using local port: '44937'

[debug] SERVER: "127.0.0.1:44937"

[debug] Original chart version: ""
[debug] CHART PATH: /home/maruf/go/src/github.com/the-redback/kubernetes-yaml-drafts/helm-charts/mychart

NAME:   irreverant-meerkat
REVISION: 1
RELEASED: Fri Apr 20 03:29:11 2018
CHART: mychart-0.1.0
USER-SUPPLIED VALUES:
username: root-user

COMPUTED VALUES:
password: password
username: root-user

HOOKS:
MANIFEST:

---
# Source: mychart/templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: irreverant-meerkat-auth
data:
  password: password
  username: root-user
---
# Source: mychart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: irreverant-meerkat
  labels:
    app: irreverant-meerkat
spec:
  replicas: 1
  template:
    metadata:
      name: irreverant-meerkat
      labels:
        app: irreverant-meerkat
    spec:
      containers:
      - name: irreverant-meerkat
        image: alpine
        env:
        - name: "USERNAME"
          valueFrom:
            secretKeyRef:
              key:  username
              name: irreverant-meerkat-auth
        - name: "PASSWORD"
          valueFrom:
            secretKeyRef:
              key:  password
              name: irreverant-meerkat-auth

        imagePullPolicy: IfNotPresent
      restartPolicy: Always
  selector:
    matchLabels:
      app: irreverant-meerkat

可以看到secret中username的数据已经变成root-user.

我已将 this example 添加到 github 存储库中。

kubernetes/helm repo regarding this. You can see this issue 中也有一些讨论,以了解使用环境变量的所有其他方式。

我想问题是如何通过查看 env 变量本身而不是通过 --set 传递它来查找 chart 中的 env 变量。

例如:我设置了一个键“my_db_password”,不支持通过查看环境变量中的值来更改值。

我不太确定 GO 模板,但我猜这是禁用的,正如他们在 helm 文档中所解释的那样。 “出于安全原因,我们删除了两个:env 和 expandenv(这将使图表作者能够访问 Tiller 的环境)。” https://helm.sh/docs/developing_charts/#know-your-template-functions

您可以通过如下设置部署 yaml 来从值 yaml 传递 env 键值:

spec:
  restartPolicy: Always
  containers:
    - name: sample-app
      image: "sample-app:latest"
      imagePullPolicy: Always
      env:          
        {{- range $name, $value := .Values.env }}
        - name: {{ $name }}
          value: {{ $value }}
        {{- end }}

在values.yaml中:

env:          
 - name: "USERNAME"
   value: ""
 - name: "PASSWORD"
   value: ""

安装图表时可以传递用户名密码值

helm install chart_name --name release_name --set env.USERNAME="app-username" --set env.PASSWORD="28sin47dsk9ik"

对于那些希望使用数据结构而不是列表作为环境变量文件的人来说,这对我有用:

spec:
  containers:
    - name: {{ .Chart.Name }}
      image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
      imagePullPolicy: {{ .Values.image.pullPolicy }}
      env:          
      {{- range $key, $val := .Values.env }}
        - name: {{ $key }}
          value: {{ $val | quote }}
      {{- end }}

values.yaml:

env:          
 FOO: "BAR"
 USERNAME: "CHANGEME"
 PASWORD: "CHANGEME"

这样我就可以在 helm chart 的其他部分按名称访问特定值,并通过 helm 命令行传递敏感值。

为了避免手动设置每个秘密,您可以使用:

export MY_SECRET=123
envsubst < values.yaml | helm install my-release . --values -

在您的 values.yaml 文件中引用了 ${MY_SECRET},例如:

mychart:
  secrets:
    secret_1: ${MY_SECRET}

我认为一种简单的方法就是直接设置值。例如,在您的 Values.yml 中,您希望传递服务名称:

...
myapp:
  service:
    name: ""
...

您的 service.yml 照常使用此值即可:

{{ .Values.myapp.service.name }}

然后设置值,使用--set,如:--set myapp.service.name=hello


然后比如你要使用环境变量,在这之前做export:

#set your env variable 
export MYAPP_SERVICE=hello

#pass it to helm
helm install myapp --set myapp.service.name=$MYAPP_SERVICE.

如果你像这样调试:

helm install myapp --set myapp.service.name=$MYAPP_SERVICE --debug --dry-run ./myapp

您可以在设置“hello”的 yml 开头看到此信息。

USER-SUPPLIED VALUES:
myapp:
  service:
    name: hello

作为传递本地环境变量的替代方法,我喜欢将这些敏感值存储在 VCS 忽略的文件夹中,并使用 Helm .Files 对象读取它们并将值提供给模板.

在我看来,优点是它不需要运行 Helm chart 的主机来设置任何 OS 特定的环境变量,并使 chart 自包含而不暴露这些值.

# In a folder not committed, e.g. <chart_base_directory>/secrets
username: app-username
password: 28sin47dsk9ik

然后在您的图表模板中:

# In deployment.yaml file
---
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Release.Name }}-auth
stringData::
{{ .Files.Get "<chart_base_directory>/secrets" | indent 2 }}

因此,图表所需的一切都可以从您定义其他所有内容的目录中访问。而不是设置系统范围的环境变量,它只需要一个文件。

此文件可以自动生成,也可以使用虚拟值从已提交的模板中复制。如果未定义,Helm 也会在 install/update 早期触发错误,而不是如果您的环境变量尚未定义,则使用 username=""password="" 创建您的秘密,这仅一旦您的更改应用到集群,就会变得很明显。

Helm 3.1 支持 post 渲染 (https://helm.sh/docs/topics/advanced/#post-rendering),它在将清单实际发送到 Kubernetes API 之前将清单传递给脚本。 Post 呈现允许以多种方式操作清单(例如,在 Helm 上使用 kustomize)。

替换预定义环境值的 post 渲染器的最简单形式如下所示:

#!/bin/sh
envsubst <&0

请注意,这将替换 $<VARNAME> 次出现,这可能会与模板中的变量发生冲突,例如活性探测中的 shell 脚本.因此,最好明确定义要替换的变量: envsubst '${USERNAME} ${PASSWORD}' <&0

在 shell:

中定义环境变量
export USERNAME=john PASSWORD=my-secret

在模板中(例如 secret.yaml)使用 values.yaml 中定义的值:

apiVersion: v1
kind: Secret
metadata:
    name: {{ .Release.Name }}-auth
data:
    username: {{ .Values.username }}
    password: {{ .Values.password }}

请注意,在 Helm 已经处理完所有 YAML 文件后,您不能在清单中注入 b64enc 等字符串转换。相反,如果需要,您可以在 post 渲染器中对它们进行编码。

values.yaml中使用变量占位符:

...
username: ${USERNAME}
password: ${PASSWORD}

几个 Helm 命令支持参数 --post-renderer,例如

helm install --dry-run --post-renderer ./my-post-renderer.sh my-chart

通过使用 post 渲染器,variables/placeholders 会自动被 envsubst 替换,无需额外的脚本。