One codebase, One helm repository

Shivam Aggarwal
3 min readJul 14, 2020

Helm is a package manager for kubernetes. It uses charts to define, install, and upgrade kubernetes applications. We depend on helm for all our deployments. We define one helm repo for each application deployment. When there are applications that use single codebase but behaves differently based on configuration, this practice add a lot of redundancy.

Problem Statement

For each application behaviour, a new helm repo is required with same configurable values with exception of a few.
Please refer to this example for easy understanding — https://github.com/shivama205/helm-subcharts/tree/master/before

In this example, we have 3 charts with same configurable variables with the exception of variable ‘type’ defining the behaviour of the application.
type = apiserver ; run the code as an api server
type = consumers ; run the code as queue consumers
type = cronjobs ; run the code as cron jobs

All the rest of the variables are duplicated among these three repositories. In case we have to add or update any variable, it needs to be done thrice, which is inefficient.

Proposed Solution

The proposed solution is to make use of helm subcharts and global variables. Helm provides with a feature called subcharts which let’s us define charts within a parent chart. Subcharts have their own values.yaml and can access global variables. Subcharts can be seen as normal helm charts with their own templates. Parent chart can override values from subcharts by simply defining under values.yaml under name of the subchart. Please refer to this example — https://github.com/shivama205/helm-subcharts/tree/master/after

Subcharts use global values

In this example, we have three subcharts (apiserver, consumers and cronjobs) under a parent chart. We can deploy all three of these subcharts as individual helm charts. But we make use of the fact that they are under a single parent chart and use it to share configuration variables by defining them as global variables under parent’s values.yaml file.

Illustration

We use.Values.global.configs.configMap under file configMap.yaml intemplates of all subcharts. This reads all the global values defined under parent’s values.yaml file. And we can add specific configmap values for the subchart in the same file. This way we only have to update common values under parent’s values.yaml file and it will be used by all the subcharts.

Parent Chart override values of subcharts

When using helm charts, we made use of the command line arguments for passing env based values.yaml file.
helm lint --values=values.${ENV}.yaml .
When it comes to helm subcharts, this is not possible, which is a problem given we want our deployments to be env based. We cannot specify values.yaml path for subcharts. This is where we made use of the fact that parent chart can override values from subcharts. Since all the variables are same under different environments, we override them in parent’s values.${ENV}.yaml file. Please see the following illustration —

Illustration

  1. Under file apiserver.values.yaml , we define image tag with value v1.0 .
  2. Then we define a key named apiserver(name of the subchart) under parent.values.yaml.
  3. And under key apiserver , we define image tag with value v2.0 .
  4. When helm is installed, it will override the image tag value to v2.0 as it is defined under parent chart and it takes precedence on its subcharts.

This way we can specify values from parent values.yaml file. And since we can specify parent’s values.yaml path, we can override values in subcharts with parent values.yaml . It also provide abstraction over configuration of subcharts as we only make changes to parents values.yaml file.

Any suggestions or thoughts, let me know:
Insta + Twitter + LinkedIn + Medium | Shivam Aggarwal

--

--