Creating the Helm chart

In order to use Helm for deployment I had to create a Chart, this section details how I got started and shows the individual components that make up the chart.

Getting started

The Helm CLI provides a create command to generate a skeleton chart with the required directory structure and files. This was run as follows:

helm create themeparks-bot

The output of this command is this folder structure:

themeparks-bot/

|

|- .helmignore # Contains patterns to ignore when packaging Helm charts.

|

|- Chart.yaml # Information about your chart

|

|- values.yaml # The default values for your templates

|

|- charts/ # Charts that this chart depends on

|

|- templates/ # The template files

The main working area is the templates folder as this is where Kubernetes resources reside. In fact, the skeleton chart actually comes with example Deployment, Ingress and Service templates.

Creating the Values file

Before I created the templates, I first of all modified the values.yaml file. This contains the defaults for properties used in the templates.

Values

There a number of best practices for Values files that I followed when making modifications (see the documentation). A number of key ones are:

Variables names should use camelcase.

A flat structure should be preferred, over nesting.

All properties should be documented.

One thing to note it that I haven’t specified values for those under the secret property; this is because I pass this at deployment time, since they are values I don’t want in source control.

Defining the templates

Using the skeleton templates as a starting point, I modified and created additional templates for the chat bot.

Helm has a lot of general guidance around developing templates such as:

Templates files should follow a naming convention of [Chart name]-[Kubernetes resource type].yaml e.g. themeparks-bot-deployment.yaml.

A template file should only contain a single Kubernetes resource (source).

All resources should have the standard set of Helm labels (source).

The include function should be used over the template function (source).

With these in mind here are the individual templates.

_helpers

This is the default location for template partials and helpers. These helpers are used amongst the separate Kubernetes resource templates.

Guidance around helpers include:

Defining a documentation block for each function (source).

Prefixing each function with the name of the chart (source).

Helper templates

Secret

Here’s the first example of using those helper functions and values together to define a Secret.

Secret template

Deployment

Next up is the Deployment which depends on the previously defined secret; this is why I reference it in annotations section.

The reason I am doing is so that whenever any secret values change, Kubernetes will redeploy picking up any new values (More information about this can be found here).

Deployment template

Service

Now that I had a Deployment I needed to expose it within the cluster, hence the Service definition.

Service template

Ingress

Finally the last piece is an Ingress resource. The Service currently is only available within the cluster and not available externally.

This is because since the bot is based on expressjs it is recommended to use a proxy like NGINX to make it internet facing. This is exactly the job of this Ingress definition.

Ingress template

Specifying dependencies

As I mentioned in the defining the templates section, the chat bot is exposed to the world through NGINX. Additionally the bot uses Redis for caching theme park data.

Rather than creating the Kubernetes templates to deploy NGINX and Redis myself, Helm allows you to define other charts as dependencies which get deployed alongside your chart.

Luckily for me there happened to be charts already for NGINX and Redis. These were included as part of this chart by creating a requirements.yaml file.

Chart dependencies

Chart.yaml

The final piece of puzzle is the actual chart definition:

Chart definition

Build and deployment

After creating the Helm chart, I put everything together using Travis CI to build and deploy the bot to Kubernetes.

My .travis.yml file looks like the following:

This Travis CI definition utilizes Build Stages (currently in Beta) which allow you to cleanly separate the various phases of a build/deploy pipeline. You will also notice that I am using a number of environment variables which are set using the Repository settings.

This definition performs the following actions:

Before any stage, it installs dependencies that the scripts require to work i.e. Azure CLI, kubectl and helm.

The build stage performs the following tasks:

Installs dependencies using yarn. Builds the bot using yarn. Lints the helm chart definition. If the build is working off master and it is successful, then it builds a docker image and publishes it to Docker Hub.

If the build phase passes and the build is working off the master branch, then it runs the deploy stage. This stage uses the experimental Script deployment to run a wrapper script to deploy the chart to Kubernetes.

The wrapper script looks as follows: