Subcharts and Global Values

To this point we have been working only with one chart. But charts can havedependencies, called subcharts, that also have their own values and templates.In this section we will create a subchart and see the different ways we canaccess values from within templates.

Before we dive into the code, there are a few important details to learn aboutsubcharts.

  • A subchart is considered “stand-alone”, which means a subchart can neverexplicitly depend on its parent chart.
  • For that reason, a subchart cannot access the values of its parent.
  • A parent chart can override values for subcharts.
  • Helm has a concept of global values that can be accessed by all charts.As we walk through the examples in this section, many of these concepts willbecome clearer.

Creating a Subchart

For these exercises, we’ll start with the mychart/ chart we created at thebeginning of this guide, and we’ll add a new chart inside of it.

  1. $ cd mychart/charts
  2. $ helm create mysubchart
  3. Creating mysubchart
  4. $ rm -rf mysubchart/templates/*.*

Notice that just as before, we deleted all of the base templates so that we canstart from scratch. In this guide, we are focused on how templates work, not onmanaging dependencies. But the Charts Guide has more informationon how subcharts work.

Adding Values and a Template to the Subchart

Next, let’s create a simple template and values file for our mysubchart chart.There should already be a values.yaml in mychart/charts/mysubchart. We’llset it up like this:

  1. dessert: cake

Next, we’ll create a new ConfigMap template inmychart/charts/mysubchart/templates/configmap.yaml:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: {{ .Release.Name }}-cfgmap2
  5. data:
  6. dessert: {{ .Values.dessert }}

Because every subchart is a stand-alone chart, we can test mysubchart on itsown:

  1. $ helm install --dry-run --debug mychart/charts/mysubchart
  2. SERVER: "localhost:44134"
  3. CHART PATH: /Users/mattbutcher/Code/Go/src/helm.sh/helm/_scratch/mychart/charts/mysubchart
  4. NAME: newbie-elk
  5. TARGET NAMESPACE: default
  6. CHART: mysubchart 0.1.0
  7. MANIFEST:
  8. ---
  9. # Source: mysubchart/templates/configmap.yaml
  10. apiVersion: v1
  11. kind: ConfigMap
  12. metadata:
  13. name: newbie-elk-cfgmap2
  14. data:
  15. dessert: cake

Overriding Values from a Parent Chart

Our original chart, mychart is now the parent chart of mysubchart. Thisrelationship is based entirely on the fact that mysubchart is withinmychart/charts.

Because mychart is a parent, we can specify configuration in mychart andhave that configuration pushed into mysubchart. For example, we can modifymychart/values.yaml like this:

  1. favorite:
  2. drink: coffee
  3. food: pizza
  4. pizzaToppings:
  5. - mushrooms
  6. - cheese
  7. - peppers
  8. - onions
  9. mysubchart:
  10. dessert: ice cream

Note the last two lines. Any directives inside of the mysubchart section willbe sent to the mysubchart chart. So if we run helm install —dry-run —debugmychart, one of the things we will see is the mysubchart ConfigMap:

  1. # Source: mychart/charts/mysubchart/templates/configmap.yaml
  2. apiVersion: v1
  3. kind: ConfigMap
  4. metadata:
  5. name: unhinged-bee-cfgmap2
  6. data:
  7. dessert: ice cream

The value at the top level has now overridden the value of the subchart.

There’s an important detail to notice here. We didn’t change the template ofmychart/charts/mysubchart/templates/configmap.yaml to point to.Values.mysubchart.dessert. From that template’s perspective, the value isstill located at .Values.dessert. As the template engine passes values along,it sets the scope. So for the mysubchart templates, only values specificallyfor mysubchart will be available in .Values.

Sometimes, though, you do want certain values to be available to all of thetemplates. This is accomplished using global chart values.

Global Chart Values

Global values are values that can be accessed from any chart or subchart byexactly the same name. Globals require explicit declaration. You can’t use anexisting non-global as if it were a global.

The Values data type has a reserved section called Values.global where globalvalues can be set. Let’s set one in our mychart/values.yaml file.

  1. favorite:
  2. drink: coffee
  3. food: pizza
  4. pizzaToppings:
  5. - mushrooms
  6. - cheese
  7. - peppers
  8. - onions
  9. mysubchart:
  10. dessert: ice cream
  11. global:
  12. salad: caesar

Because of the way globals work, both mychart/templates/configmap.yaml andmysubchart/templates/configmap.yaml should be able to access that value as{{ .Values.global.salad }}.

mychart/templates/configmap.yaml:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: {{ .Release.Name }}-configmap
  5. data:
  6. salad: {{ .Values.global.salad }}

mysubchart/templates/configmap.yaml:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: {{ .Release.Name }}-cfgmap2
  5. data:
  6. dessert: {{ .Values.dessert }}
  7. salad: {{ .Values.global.salad }}

Now if we run a dry run install, we’ll see the same value in both outputs:

  1. # Source: mychart/templates/configmap.yaml
  2. apiVersion: v1
  3. kind: ConfigMap
  4. metadata:
  5. name: silly-snake-configmap
  6. data:
  7. salad: caesar
  8. ---
  9. # Source: mychart/charts/mysubchart/templates/configmap.yaml
  10. apiVersion: v1
  11. kind: ConfigMap
  12. metadata:
  13. name: silly-snake-cfgmap2
  14. data:
  15. dessert: ice cream
  16. salad: caesar

Globals are useful for passing information like this, though it does take someplanning to make sure the right templates are configured to use globals.

Sharing Templates with Subcharts

Parent charts and subcharts can share templates. Any defined block in any chartis available to other charts.

For example, we can define a simple template like this:

  1. {{- define "labels" }}from: mychart{{ end }}

Recall how the labels on templates are globally shared. Thus, the labelschart can be included from any other chart.

While chart developers have a choice between include and template, oneadvantage of using include is that include can dynamically referencetemplates:

  1. {{ include $mytemplate }}

The above will dereference $mytemplate. The template function, in contrast,will only accept a string literal.

Avoid Using Blocks

The Go template language provides a block keyword that allows developers toprovide a default implementation which is overridden later. In Helm charts,blocks are not the best tool for overriding because it if multipleimplementations of the same block are provided, the one selected isunpredictable.

The suggestion is to instead use include.