helm 模板中的查询值
Query Values in helm template
我正在尝试为我的 Helm 图表中的所有入口资源生成 TLS 证书。我的 helm chart 包含一个具有多个后端的应用程序,因此我的 Values.yaml 的结构如下:
backend1:
ingress:
host: testing.app.com
tls:
- secretName: my-tls-cert
hosts:
- testing.app.com
backend2:
ingress:
host: testing.app.com
tls:
- secretName: idp-cts-cert
hosts:
- idp-cts
db
creds: ""
serviceName: ""
请注意,其中混合了映射和字符串值。我的目标是使用我编写的实用程序模板来调用 genSignedCert
并生成一个 TLS 证书,其中的主机列为 CN 或备用名称:
{{/*
Return a self-signed TLS certificate
{{ include "common.certs.ingress-tls" .hosts }}
*/}}
{{- define "common.certs.gen-cert" -}}
{{- $hostlist := toStrings . -}}
{{- $cn := (first $hostlist) -}}
{{- $altnames := uniq (rest $hostlist) -}}
{{- $ca := genCA "idp-ca" 365 -}}
{{- $cert := genSignedCert $cn nil $altnames 365 $ca -}}
tls.crt: {{ $cert.Cert | b64enc }}
tls.key: {{ $cert.Key | b64enc }}
{{- end -}}
我已经尝试遍历这些值,但我无法想出可行的代码来执行此操作。
Edit1:我知道使用自签名证书的安全隐患。错误的 values.yaml 结构继承自以下事实:这是一个伞状图表,每个支持的图表也是它自己的图表。可能需要重构图表结构,但我想先用尽所有选项。
考虑在 Helm 外部生成 TLS 证书,并通过值注入它(或直接将其组件存储在 Secret 中)。这里避免了一些复杂的代码。但是,还有一个更严重的问题:每次调用 genCA
和 genSignedCert
时,它都会创建一个新证书,因此每次升级时,您都会获得不同的证书,就此而言,如果您调用这个模板每个 Ingress 对象一次,每个都有不同的证书。
稍微重组 values.yaml
会帮助解决这个问题。代码很难说 backend1
是后端规范,但 serviceName
不是。如果你只有 backends
的列表,这会更容易:
backends:
- ingress:
host: testing.app.com
...
- ingress:
host: testing.app.com
...
然后,您将遇到 Helm 模板作为全功能编程语言的一些限制。模板只有 return 个字符串,因此您不能编写一个 return 列表的模板。您不能将函数作为参数传递给模板,因此您不能编写通用的 map
(在有限的情况下,您可以传递模板名称并 include
它)。
您可以编写一个递归函数,将部分列表传递给下一次迭代,然后在完成时调用最终生成器。在Python中,我们可以这样写:
def generateCertificate(backends, tls, hosts):
# If `tls` is non-empty, take the first item from it and add its
# hosts to the `hosts` list; then recurse with the same backend
# list, the remaining `tls` items, and the updated `hosts`:
if len(tls) > 0:
return generateCertificate(backends, tls[1:], hosts + tls[0].hosts)
# If `tls` is empty but `backends` is non-empty, take the first
# backend, and recurse with the remaining `backends`, the `tls` items
# from the selected backend, and the same `hosts`:
else if len(backends) > 0:
return generateCertificate(backends[1:], backends[0].tls, hosts)
# If `tls` and `backends` are both empty, we're done
else:
return buildTheCertificate(hosts)
certificate = generateCertificate(values.backends, [], [])
我们可以将此逻辑转换为 Go 模板:
{{/* Emit a TLS certificate given the list of backends. The
parameter is a dictionary with keys `backends`, `tls`, and `hosts`. */}}
{{- define "common.certs.gen-cert" -}}
{{- if .tls -}}
{{- include "common.certs.gen-cert" (dict "backends" .backend "tls" (last .tls) "hosts" (concat .hosts (head .tls).hosts)) -}}
{{- else if .backends -}}
{{- include "common.certs.gen-cert" (dict "backends" (tail .backends) "tls" (head .backends).tls "hosts" .hosts) -}}
{{- else -}}
{{- include "common.certs.gen-cert-hosts" .hosts -}}
{{- end -}}
{{- end -}}
{{/* Actually generate a TLS certificate from a list of host names.
Note, the certificate will be regenerated on every call. The
single parameter is a list of names. */}}
{{- define "common.certs.gen-cert-hosts" -}}
{{- $cn := first . -}}
{{- $altnames := rest . | uniq -}}
{{- $ca := genCA "idp-ca" 365 -}}
{{- $cert := genSignedCert $cn nil $altnames 365 $ca -}}
tls.crt: {{ $cert.Cert | b64enc }}
tls.key: {{ $cert.Key | b64enc }}
{{- end -}}
{{- include "common.certs.gen-cert" (dict "backends" .Values.backends) -}}
这段代码足够复杂,可能值得对其进行单元测试。设置它留作练习; Helm 在这里没有任何类型的本地支持。
我正在尝试为我的 Helm 图表中的所有入口资源生成 TLS 证书。我的 helm chart 包含一个具有多个后端的应用程序,因此我的 Values.yaml 的结构如下:
backend1:
ingress:
host: testing.app.com
tls:
- secretName: my-tls-cert
hosts:
- testing.app.com
backend2:
ingress:
host: testing.app.com
tls:
- secretName: idp-cts-cert
hosts:
- idp-cts
db
creds: ""
serviceName: ""
请注意,其中混合了映射和字符串值。我的目标是使用我编写的实用程序模板来调用 genSignedCert
并生成一个 TLS 证书,其中的主机列为 CN 或备用名称:
{{/*
Return a self-signed TLS certificate
{{ include "common.certs.ingress-tls" .hosts }}
*/}}
{{- define "common.certs.gen-cert" -}}
{{- $hostlist := toStrings . -}}
{{- $cn := (first $hostlist) -}}
{{- $altnames := uniq (rest $hostlist) -}}
{{- $ca := genCA "idp-ca" 365 -}}
{{- $cert := genSignedCert $cn nil $altnames 365 $ca -}}
tls.crt: {{ $cert.Cert | b64enc }}
tls.key: {{ $cert.Key | b64enc }}
{{- end -}}
我已经尝试遍历这些值,但我无法想出可行的代码来执行此操作。
Edit1:我知道使用自签名证书的安全隐患。错误的 values.yaml 结构继承自以下事实:这是一个伞状图表,每个支持的图表也是它自己的图表。可能需要重构图表结构,但我想先用尽所有选项。
考虑在 Helm 外部生成 TLS 证书,并通过值注入它(或直接将其组件存储在 Secret 中)。这里避免了一些复杂的代码。但是,还有一个更严重的问题:每次调用 genCA
和 genSignedCert
时,它都会创建一个新证书,因此每次升级时,您都会获得不同的证书,就此而言,如果您调用这个模板每个 Ingress 对象一次,每个都有不同的证书。
稍微重组 values.yaml
会帮助解决这个问题。代码很难说 backend1
是后端规范,但 serviceName
不是。如果你只有 backends
的列表,这会更容易:
backends:
- ingress:
host: testing.app.com
...
- ingress:
host: testing.app.com
...
然后,您将遇到 Helm 模板作为全功能编程语言的一些限制。模板只有 return 个字符串,因此您不能编写一个 return 列表的模板。您不能将函数作为参数传递给模板,因此您不能编写通用的 map
(在有限的情况下,您可以传递模板名称并 include
它)。
您可以编写一个递归函数,将部分列表传递给下一次迭代,然后在完成时调用最终生成器。在Python中,我们可以这样写:
def generateCertificate(backends, tls, hosts):
# If `tls` is non-empty, take the first item from it and add its
# hosts to the `hosts` list; then recurse with the same backend
# list, the remaining `tls` items, and the updated `hosts`:
if len(tls) > 0:
return generateCertificate(backends, tls[1:], hosts + tls[0].hosts)
# If `tls` is empty but `backends` is non-empty, take the first
# backend, and recurse with the remaining `backends`, the `tls` items
# from the selected backend, and the same `hosts`:
else if len(backends) > 0:
return generateCertificate(backends[1:], backends[0].tls, hosts)
# If `tls` and `backends` are both empty, we're done
else:
return buildTheCertificate(hosts)
certificate = generateCertificate(values.backends, [], [])
我们可以将此逻辑转换为 Go 模板:
{{/* Emit a TLS certificate given the list of backends. The
parameter is a dictionary with keys `backends`, `tls`, and `hosts`. */}}
{{- define "common.certs.gen-cert" -}}
{{- if .tls -}}
{{- include "common.certs.gen-cert" (dict "backends" .backend "tls" (last .tls) "hosts" (concat .hosts (head .tls).hosts)) -}}
{{- else if .backends -}}
{{- include "common.certs.gen-cert" (dict "backends" (tail .backends) "tls" (head .backends).tls "hosts" .hosts) -}}
{{- else -}}
{{- include "common.certs.gen-cert-hosts" .hosts -}}
{{- end -}}
{{- end -}}
{{/* Actually generate a TLS certificate from a list of host names.
Note, the certificate will be regenerated on every call. The
single parameter is a list of names. */}}
{{- define "common.certs.gen-cert-hosts" -}}
{{- $cn := first . -}}
{{- $altnames := rest . | uniq -}}
{{- $ca := genCA "idp-ca" 365 -}}
{{- $cert := genSignedCert $cn nil $altnames 365 $ca -}}
tls.crt: {{ $cert.Cert | b64enc }}
tls.key: {{ $cert.Key | b64enc }}
{{- end -}}
{{- include "common.certs.gen-cert" (dict "backends" .Values.backends) -}}
这段代码足够复杂,可能值得对其进行单元测试。设置它留作练习; Helm 在这里没有任何类型的本地支持。