考虑在 Helm 之外生成 TLS 证书,并通过值将其注入(或将其组件直接存储在 Secret 中)。这避免了一些复杂的代码。但是,还有一个更严重的问题:每次调用genCA
它genSignedCert
都会创建一个新证书,因此每次升级时都会获得不同的证书,就此而言,如果您为每个 Ingress 对象调用此模板一次,则每个都将拥有不同的证书。
values.yaml
稍微调整一下对这个问题有帮助。代码很难判断这backend1
是后端规范,但serviceName
不是。如果您只有一个列表,backends
则变得更容易:
backends:
- ingress:
host: testing.app.com
...
- ingress:
host: testing.app.com
...
然后,您将遇到 Helm 模板作为一种功能齐全的编程语言的一些限制。模板只返回字符串,因此您不能编写返回列表的模板。您不能将函数作为参数传递给模板,因此您不能编写通用的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 在这里没有任何原生支持。