如何在 helm 模板中包含嵌套值

Agu*_*ama 10 kubernetes-helm

我在掌舵中有这种模板文件:

api 版本:networking.istio.io/v1alpha3

kind: VirtualService
metadata:
  name: {{.Values.app.name}}-global-route
  namespace: {{.Release.Namespace}}
spec:
  hosts:
  - "{{.Values.app.name}}-global.{{.Release.Namespace}}.svc.cluster.local"
  gateways:
  - {{.Values.app.name}}-gateway
  - mesh
  http:
  # 1st priority, to route specific end-user to canary service
  - route:
    - destination:
        host: "{{.Values.app.name}}-global.{{.Release.Namespace}}.svc.cluster.local"
        subset: canary
    match: {{.Values.infra.trafficRoute.canaryCondition}}
Run Code Online (Sandbox Code Playgroud)

我想公开 values.yaml 如下:

# default values supplied for templates/* files
app:
  name: java-maven-app

infra:
  trafficRoute:
    canaryCondition:
    - headers:
        end-user:
          exact: apratama
        key:
          exact: agung
Run Code Online (Sandbox Code Playgroud)

所以,基本上我想要实现的是让最终用户(使用我的掌舵图的人)自定义金丝雀条件。条件本身取决于 istio 的match数据结构(可以是嵌套的和复杂的值)。我用helm upgrade --install命令在上面尝试过,但不知何故我得到了这个错误:

Error: UPGRADE FAILED: YAML parse error on java-maven-app-infra/templates/global-service.yaml: error converting YAML to JSON: yaml: line 17: found unexpected ':'
make: *** [deploy-infra] Error 1
Run Code Online (Sandbox Code Playgroud)

但是,当我注释掉这一行时:

match: {{.Values.infra.trafficRoute.canaryCondition}}
Run Code Online (Sandbox Code Playgroud)

它可以正常工作。

有什么建议吗?

Jaa*_*ari 9

我们之前在 k8s Slack 中讨论过这个解决方案。我注意到您发布了自己的答案,但我想我不妨对其进行一些扩展,以防其他人遇到同样的问题。

问题是 Helm 图表模板执行文本模板而不是 YAML 模板。因此,插入的 YAML 子树 ( canaryCondition) 不会自动转换为 YAML 并优雅地放置在match键下,而是转换为字符串并直接插入模板指令所在的位置。对于字符串和整数等简单值,这在大多数情况下都可以正常工作,但更复杂的值(例如数组和映射)需要以不同方式处理。

为了在模板中插入 YAML 子树,您需要首先使用toYaml函数将子树转换为 YAML ,然后确保函数使用正确的缩进级别indent

{{ toYaml .Values.infra.trafficRoute.canaryCondition | indent 4 }}
Run Code Online (Sandbox Code Playgroud)

有关如何在模板中插入 YAML 子树的另一个示例,请参阅NGINX 模板示例

要开始调试 Helm 图表模板,您可以使用该helm template命令查看 Helm 图表生成的 YAML。


tee*_*zet 7

如果围绕缩进有共同的困惑:

您还可以使用左修剪 {{- toYaml ... }}nindent换行 + 缩进)来获得正确的缩进:

  # 1st priority, to route specific end-user to canary service
  - route:
    - destination:
        host: "{{.Values.app.name}}-global{{.Release.Namespace}}.svc.cluster.local"
        subset: canary
    match:
      {{- toYaml .Values.infra.trafficRoute.canaryCondition | nindent 4 }}
Run Code Online (Sandbox Code Playgroud)