Using Helm helper files to manage shared properties across multiple micro-services

In Helm we use Charts. In Cloud services, a service is typically separated to multiple micro-services.
In Helm lingo then, a micro-service could be considered as a Chart.

Despite being separate to multiple micro-services, it is likely that some properties would be the same across some of them. You would typically resolve this by either duplicating the properties in each micro-service’s ConfigMap (not recommended), or by using a “common ConfigMap” (works well).

But what to do if you want to switch over to using Helm? In Helm you can’t use a common ConfigMap across charts since a Chart can only manage its own “resources” – you cannot use the same common ConfigMap in multiple Charts as Helm will complain the resource already exists, and creating another Chart just for the common ConfigMap seems a bit much (but doable) IMO.

To the rescue come Helm helper (.tpl) files, also called “Partials”. These files are basically “includes” that can be embedded into existing files while a Chart is being installed. Lets see an example.

Lets assume you want to add some common properties to your ConfigMap, to do so create a .tpl file. Make sure the filename starts with an underscore.

_my-common-configmap.tpl:

{{- define "my-common-configuration" -}}
# Evironment
clusterEnv: {{ index .Values.global.clusterEnv .Values.global.env | quote }}
namespace: {{ index .Values.global.namespace .Values.global.env | quote }}

Also create a YAML file to store the values (assuming you need different common properties for different environments…).

my-values.yaml:

--
global:
  # env refers to the environment properties belong to during build-time. Default is "development".
  env: development

  clusterEnv:
    development: staging
    pre_production: preprod

  registry:
    development: dev-images
    pre_production: preprod-images

Next, in the micro-service’s (Chart) ConfigMap, include the helper file.
Note the use of include to load the configuration data.

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap-name
  namespace: {{ index .Values.global.namespace .Values.global.env }}
data:
  log_level: {{ index .Values.global.log_level .Values.global.env | quote }}
  ...
  ...
  ...
{{ include "my-common-configuration" . | indent 2 }}

The generated result would look like this:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap-name
  namespace: dev
data:
  log_level: debug
  ...
  ...
  ...
  namespace: staging
  registry: dev-images

You can repeat this in each micro-service that needs the common properties.
And of course, remember to specify the properties in your Deployment…

- name: clusterEnv
  valueFrom:
    configMapKeyRef:
       name: my-configmap-name
       key: clusterEnv

But wait, what do I actually do with these files?
The .tpl file should be placed in your Chart’s templates folder and the values YAML file at the root of the Chart directory.

Since the files are shared across multiple micro-services, and each micro-service is likely its own repository, stored them in some Helm or DevOps repository. Configure your pipeline so that these files will get picked and placed in the right location during job execution.

If you’re wondering how to determine which value gets picked from the values YAML file, see my previous blog post, Upgrading to Helm.

Additional reading material