We had been using single ingress per application(public) by default but with the recent requirement we need to expose (private) endpoint as well for some of the apps. That means we had a single template that looks like this:
templates/ingress.yaml
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "app.fullname" . -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{ include "app.labels" . | indent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ . }}
backend:
serviceName: {{ $fullName }}
servicePort: http
{{- end }}
{{- end }}
{{- end }}
templates/cert.yaml
{{- if .Values.ingress.tls -}}
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: {{ .Values.ingress.name }}
namespace: {{ .Values.ingress.namespace }}
spec:
{{- range .Values.ingress.tls }}
secretName: {{ .secretName }}
duration: 24h
renewBefore: 12h
issuerRef:
name: {{ .issuerRef.name }}
kind: {{ .issuerRef.kind }}
dnsNames:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
{{- end -}}
{{- end -}}
And the values.yaml looks like this:
ingress:
enabled: true
name: apps-ingress
namespace: app1-namespace
annotations:
kubernetes.io/ingress.class: hybrid-external
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
hosts:
- host: apps.test.cluster
paths:
- /
tls:
- secretName: app1-tls
issuerRef:
name: vault-issuer
kind: ClusterIssuer
hosts:
- "apps.test.cluster"
So, to accomodate the new setup. I have added the below block on values.yaml file.
ingress-private:
enabled: true
name: apps-ingress-private
namespace: app1-namespace
annotations:
kubernetes.io/ingress.class: hybrid-internal
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
hosts:
- host: apps.internal.test.cluster
paths:
- /
tls:
- secretName: app1-tls
issuerRef:
name: vault-issuer
kind: ClusterIssuer
hosts:
- "apps.internal.test.cluster"
And duplicated both templates i.e templates/ingress-private.yaml and templates/certs-private.yaml, and is working fine but my question here is - is there a way using a single template for each ingress and certs and create conditional resource?
As I mentioned above, some apps need internal ingress and some don't. What I want to do is; make public ingress/certs as default and private as optional. i have been using {{- if .Values.ingress.enabled -}}
option to validate if ingress is required but in 2 different files.
Also, in values.yaml file, rather than having 2 different block is there a way to use the list if multiple resources are required?
There are a couple of ways to approach this problem.
The way you have it now, with one file per resource but some duplication of logic, is a reasonably common pattern. It's very clear exactly what resources are being created, and there's less logic involved. The Go templating language is a little bit specialized, so this can be more approachable to other people working on your project.
If you do want to combine things together there are a couple of options. As @Matt notes in their comment, you can put multiple Kubernetes resources in the same file so long as they're separated by the YAML ---
document separator.
{{/* ... arbitrary templating logic ... */}}
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ $fullName }}
...
{{/* ... more logic ... */}}
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ $fullName }}-private
...
The only thing that matters here is that the output of the template is a valid multi-document YAML file. You can use the helm template
command to see what comes out without actually sending it to the cluster.
This approach pairs well with having a list of configuration rules in your YAML file
ingresses:
- name: apps-ingress
annotations:
kubernetes.io/ingress.class: hybrid-external
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
- name: apps-ingress-private
annotations:
kubernetes.io/ingress.class: hybrid-internal
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
You can use the Go template range
construct to loop over all of these. Note that this borrows the .
special variable, so if you do refer to arbitrary other things in .Values
you need to save away the current value of it.
{{- $top := . -}}
{{- range $ingress := .Values.ingresses -}}
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ $ingress.name }}
annotations: {{- $ingress.annotations.toYaml | nindent 4 }}
...
{{ end }}
Thanks David for getting us started . But it did not work for me. I used following to generate multiple resources in single YAML.
{{- if .Values.nfs }}
{{- $top := . -}}
{{- range $index, $pvc := .Values.nfs }}
{{- if $pvc.persistentClaim }}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: "{{ $top.Chart.Name }}-{{ $top.Release.Name }}-nfs-{{ $index }}"
namespace: {{ $top.Release.Namespace }}
....
resources:
requests:
storage: {{ $pvc.persistentClaim.storageRequest }}
{{- end }}
{{- end }}
{{- end }}
helm docs show how to define and use range: https://helm.sh/docs/chart_template_guide/variables/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With