根据 Helm 图中的变量值动态访问值

Pal*_*teJ 2 kubernetes-helm

我目前正在为多容器应用程序编写 Helm 图表。我们有一堆微服务容器(我们称它们为“应用程序”),它们在通过 K8s 处理的方式上非常相似,并且可以(因此应该)由相同的 Helm 模板处理以避免重复。另一方面,能够为不同的应用程序(例如,资源请求)单独配置某些设置是有意义的。我目前正在做这样的事情:

{{- $applications:= <obtain list of applications> }}
{{ range $app:= $applications }}
apiVersion: apps/v1
kind: StatefulSet
spec:
[...]
    spec:
      containers:
      - name: {{ $app }}
        image: {{ $.Values.image.registry }}mycompany/myproduct-{{ $app }}:{{ $.Values.image.version }}
[...]
Run Code Online (Sandbox Code Playgroud)

我现在想要做的是能够设置一些特定于应用程序的值(以 K8s resources.requests.memory 或副本数为例),可以在 values.yaml 中为每个应用程序单独设置,但回退到如果未设置,则为默认值。这个想法是在 values.yaml 中有这样一个部分:

applications:
  default:
    replicas: 1
    resources:
      requests:
        memory: 512Mi
        cpu: 250m
  applicationA:
    resources:
      requests:
        memory: 7Gi
  applicationB:
    resources:
      requests:
        cpu: 500m
[...]
Run Code Online (Sandbox Code Playgroud)

我的想法是我将“默认”部分中的值用于应用程序,除非在相应应用程序的部分中指定了特定于应用程序的值。在我的示例中,我有一个用于 applicationA 的内存请求的自定义值和一个用于应用程序 B 的 CPU 请求的自定义值,但所有其他值都应来自默认部分。也可能存在根本没有定义应用程序特定设置的应用程序(在这种情况下,所有内容都来自 values.yaml 的默认部分)。“索引”功能似乎允许我做我想做的事情,所以在我的模板中,我尝试了这个(为了可读性而换行):

resources:
  requests:
    memory: {{ default \
(index $.Values "applications" "default" "resources" "requests" "memory") \
(index $.Values "applications" $app "resources" "requests" "memory") }}  
Run Code Online (Sandbox Code Playgroud)

由于索引允许我使用我的循环变量“$app”的值从 values.yaml“取消引用”一个值,这实际上有效......唉,索引失败,错误调用索引:在这些情况下索引为 nil 指针我没有为其中一个设置指定特定于应用程序的值,因此取消引用失败。我需要的是 index 在那种情况下不会失败,而只是返回一个空值,以便默认值生效。不幸的是,我似乎找不到办法做到这一点。

但也许有一种完全不同的方式来处理这个问题,所以任何想法和建议都值得赞赏。当然,作为后备,我可以在 values.yaml 中为每个应用程序明确设置每个值,但这感觉不对。

aay*_*ore 12

我对我的图表做了类似的事情,但基于环境而不是应用程序。

在我的values.yaml

env: dev

replicaCount:
  _default: 1
  staging: 2
  prod: 4
Run Code Online (Sandbox Code Playgroud)

在我的模板中:

  replicas: {{ pluck .Values.env .Values.replicaCount | first | default .Values.replicaCount._default }}
Run Code Online (Sandbox Code Playgroud)

pluck命令返回一个列表,并first从该列表中选择第一项。如果没有返回任何内容,它会回退到该_default值。所以当我运行时helm template --set env=staging,我会得到我为我的登台环境设置的配置。

您的values.yaml文件将如下所示:

replicas:
  _default: 1
resources:
  requests:
    memory:
      _default: 512Mi
      applicationA: 7Gi
    cpu:
      _default: 250m
      applicationB: 500m
Run Code Online (Sandbox Code Playgroud)

您的模板将具有以下内容:

memory: {{ pluck .Values.app .Values.resources.requests.memory | first | default .Values.resources.requests.memory._default }}
Run Code Online (Sandbox Code Playgroud)

然后你只需要添加--set app=applicationA到你的 Helm 命令中。

我认为这使values.yaml或多或少具有可读性,但模板变得有点难看。

您可能会使用pluck与原始值文件的组合来实现以下目的:

{{ pluck .Values.app .Values.applications | default .Values.applications.default | toYaml | indent N }}
Run Code Online (Sandbox Code Playgroud)

我没试过,所以YMMV。(您肯定必须更改N以匹配插入块的缩进级别。)只是一个想法。似乎脆弱配置的潜力很大。