Search code examples
kubernetes-helmgo-templates

helm charting - how to render a same template more than once?


I wish to create a helm chart to deploy an app that has multiple different pods (hence multiple deployment manifests). Here's the structure of the chart:

├── Chart.yaml
├── templates
│   ├── NOTES.txt
│   ├── _helpers.yaml
│   ├── comp-1
│   │   ├── comp-1-deployment.yaml
│   │   ├── comp-1-ingress.yaml
│   │   └── comp-1-service.yaml
│   ├── comp-2
│   │   ├── comp-2-deployment.yaml
│   │   └── comp-2-service.yaml
│   ├── comp-3
│   │   ├── comp-3-deployment.yaml
│   │   └── comp-3-service.yaml
└── values.yaml

I realize the templates for all the components look the same, so I want to refactor to reduce the templates to:

├── Chart.yaml
├── templates
│   ├── NOTES.txt
│   ├── _helpers.yaml
│   ├── comp
│   │   ├── comp-deployment.yaml
│   │   ├── comp-ingress.yaml
│   │   └── comp-service.yaml
└── values.yaml

and use the values in values.yaml to render comp more than once to generate multiple copies of it. How do I do that? I've looked into partials, it seems it does not do what I want.


Solution

  • You can use any templating constructs you want inside the template files. A file can include (or generate) multiple YAML files (or none); if it's more than one you need to make sure each begins with the --- YAML start-of-document marker.

    If you wanted to generate multiple Deployments based on values, for example, you can specify

    {{ $top := . -}}
    {{ range .Values.components -}}
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: {{ $top.Release.Name }}-{{ .name }}
    ...
    {{ end -}}
    

    The one trick in here is that, inside the range loop, the special variable . is the loop iterator, and the normal Helm top-level object is hidden. I tend to save the original value of . in a variable, or the special template variable $ will often work too.

    Make sure to carefully check the - whitespace controls: this will not work if the --- is not on a line of its own. You can see what the template produces without submitting it to the cluster using helm template.

    In templates I've looked at on GitHub, "normal style" seems to be one Kubernetes resource to a file, possibly hidden with a {{ if }}...{{ end }} at the top level but no more control flow than that. These are often fairly repetitive, but at the same time the set of components that needs to be deployed is usually fixed (you wouldn't usually use values to only deploy one part of your application).