Helm:从 json 个文件覆盖配置,有没有更好的方法?

Helm: Overwrite configuration from json files, is there a better way?

我们使用 helm 在不同的系统上部署一个微服务。

除其他外,我们有一个 ConfigMap 模板,当然还有一个包含服务回购中默认值的值文件。其中一些值是 JSON,目前存储为 JSON 字符串:

apiVersion: v1
data:
  Configuration.json: {{ toYaml .Values.config | indent 4 }}
kind: ConfigMap
metadata:
  name: service-cm
config: |-
  {
    "val1": "key1",
    "val2": "key2"
  }

我们还有一个部署仓库,其中定义了不同的系统。在这里,我们也用 json 字符串覆盖了值。

由于这些 json 字符串的可用性不太好,我们想将它们移动到 json 文件中。

我们使用 AKS 和 Azure Pipelines 来部署服务。 我们创建图表:

helm chart save Chart $(acr.name).azurecr.io/$(acr.repo.name):$(BUILD_VERSION)

并推送:

helm chart push $(acr.name).azurecr.io/$(acr.repo.name):$(BUILD_VERSION)

并在另一个作业中拉取和导出后升级:

helm upgrade --install --set image-name --wait -f demo-values.yaml service service-chart

我们已经完成的是使用 --set-file:

在升级命令中设置 json 配置
upgrade --install --set image-name --wait -f demo-values.yaml --set-file config=demo-config.json service service-chart

虽然仅适用于不同系统的值,但不适用于默认值。但我们也想外包这些,也不想没有它们。 因此此时第一个问题,是否有办法为每个文件注入默认值,以便它们位于保存的图表中?

我们知道您可以使用以下语法读取模板中的文件:

  Configuration.json: |-
{{ .Files.Get "default-config.json" | indent 4 }}

但我们不能推翻它。另一个想法是从值中注入路径:

 Configuration.json: |-
{{ .Files.Get (printf "%s" .Values.config.filename) | indent 4 }}

但是路径好像是相对于图表文件夹的。所以没有部署 repo 的路径。

我们现在有以下带有条件模板的解决方案:

data:
  {{ if .Values.config.overwrite }}
  Configuration.json: {{ toYaml .Values.config.value | indent 4 }}
  {{ else }}
  Configuration.json: |-
{{ .Files.Get "default-config" | indent 4 }}
  {{ end }}

在部署回购中,值文件如下所示:

config:
  overwrite: true
  value: will_be_replaced_by_file_content

并且demo-config.json是通过管道中的升级命令设置的。

这可行,但对我们来说似乎有点繁琐。那么问题来了:你知道更好的方法吗?

在您的第一个设置中,.Values.config 是一个字符串。 key: |- 语法创建了一个 YAML block scalar,其中包含一个恰好是 JSON 的缩进文本块。 helm install --set-file 也将一个值设置为一个字符串,.Files.Get returns 一个字符串。

所有这些都是字符串,这意味着您可以简化围绕它们的逻辑。例如,考虑 Helm default 模板函数:如果它的参数是一个空字符串,它在逻辑上是假的,所以 default 回退到它的默认值。

在您的最终布局中,您希望将默认配置保留在单独的文件中,但只有在未提供覆盖配置时才使用它。因此,您可以采用以下方法:

  1. values.yaml中,config为空串。 (null 或者根本不定义它也适用于此设置。)

    # config is a string containing JSON-format application configuration.
    config: ''
    
  2. 因为你已经有了它,.Files.Get "default-config.json" 可以作为后备值。

  3. 使用 default 函数检查 .Values.config 是否为 non-empty,如果不是,则返回默认值。

  4. 使用 helm install --set-file config=demo-config.json 在部署时提供备用配置。

更新后的 ConfigMap 可能如下所示:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "myapp.fullname" . }}
data:
  Configuration.json:
{{ .Values.config | default (.Files.Get "default-config.json") | indent 4 }}

(因为任何形式的 .Values.config 都是字符串,所以它不是一个复杂的结构,您不需要对其调用 toYaml。)