Search code examples
templateskuberneteskubernetes-helm

Generic helm chart


I am beginner in helm chart templating and I'm looking for best practise. I would like to create a helm chart template enough generics to use same chart for all team project (backend, front-end,..) On order to make it generics I can let developer to specify list of many cases in values.yml (volumes for deployment, network policy ingress egress etc...). And i could keep the kubernetes template deployment, service etc.. Enough generics to never mention any specific keys. So the developer could only modify values yml for add values for their application behavior.

The disadvantage is that the kubernetes generics template will not contain any logic about the application , and the generic template will be hard to maintain (because it will handle every possible case). The advantage is that the developer doesn't need to understand helm because they will not modify the kubernetes template.

So you have any experience about that?


Solution

  • You can use _*.tpl files to define generic templates, They are located in ./templates/_*.tpl (. being the directory with global Chart.yaml and values.yaml). Also by defaul in helm global values override local values. Solution to this can be found here - https://github.com/helm/helm/issues/5676

    By using these 2 techniques in conjunction you can make generic templates and only use values.yaml to render what you want to render.

    For example:

    values.yaml:

    global:
      defaults:
        switches:
          volumesEnabled: false
          ingressEnabled: false
        ingress:
          host: "generic-host.com"
        volumes:
          volumeName: "generic-volume-name"
    
    subchart1:
      defaultOverrides:
        switches:
          volumesEnabled: true
      volumes:
        volumeName: "not-so-generic-name"
    
    subchart2:
      defaultOverrides:
        switches:
          volumesEnabled: true
          ingressEnabled: true
    

    Then templates (java is just for grouping templates in one category, you can try to guess in which language my backend microservices are written :) )

    ./templates/java/_deployment.tpl:

    {{- define "templates.java.deployment" }}
    {{- $properties := merge .Values.defaultOverrides $.Values.global.defaults -}}
    {{*/ generic deployment structure */}}
    {{- if $properties.switches.volumesEnabled -}}
    volume: {{ $properties.volumes.volumeName }}
    {{- end }}
    {{*/ generic deployment structure */}}
    {{- end }}
    

    ./templates/java/_ingress.tpl:

    {{- define "templates.java.ingress" }}
    {{- $properties := merge .Values.defaultOverrides $.Values.global.defaults -}}
    {{- if $properties.switches.ingressEnabled -}}
    host: {{ $properties.ingress.host }}
    {{*/ generic ingress structure */}}
    {{- end }}
    {{- end }}
    

    And then subchart templates ./charts/subchart1/templates/deployment.yaml:

    {{ include "templates.java.deployment" . }}
    

    ./charts/subchart1/templates/ingress.yaml:

    {{ include "templates.java.ingress" . }}
    

    subchart2 has exactly the same includes.

    In the end we will have:

    subchart1:

    • has deployment
    • volumeName is overriden from local values with "not-so-generic-name"
    • ingress is not rendered at all

    subchart2:

    • has deployment
    • volumeName is default from global values
    • ingress host is default from global values

    But I would say that it's a bad practice to generlize to much, because it will make your templates overly complex. In my case I found 2 distinct groups which have nearly identical manifests within them (basically frontend and backend) and made a set of _*.tpl files for each of them and settings default values for each group respectivelly in global values.yaml.