Photo by Nate Cheney / Unsplash

Helm Charts Deep Dive for Advanced Users

Jubril Oyetunji
Jubril Oyetunji

Table of Contents

In the previous installment of this series, we discussed Helm, a cloud-native tool that brings package manager-like capabilities to Kubernetes. We covered the basics of Helm and how it uses charts to simplify the deployment and management of applications on Kubernetes clusters.

This post assumes some familiarity with Helm fundamentals. If you need a refresher on the core concepts, I recommend visiting the previous post first.

In this guide, we'll be highlighting some of the more advanced features and capabilities offered by Helm charts. We'll go beyond the basics and see how leveraging these powerful features can help further simplify application definitions.

Helm Chart Releases

Helm charts allow you to define, install, and upgrade releases of a Kubernetes application. Understanding the release lifecycle is key to mastering advanced helm usage.

Helm Release Lifecycle
The helm release lifecycle refers to the entire process an application goes through from installation all the way to uninstall or an upgrade, the stages in a release lifecycle are:

  • Install: A new instance of a chart is installed via helm install. This deploys chart resources to Kubernetes.
  • Upgrade: An existing release can be upgraded using helm upgrade. This changes the resources applied based on chart changes.
  • Rollback: A release can be reverted to a previous version using helm rollback. This restores the state from an older revision.
  • Uninstall: A release can be completely removed from the cluster with helm uninstall. This deletes all related Kubernetes objects.

Release Versions
Helm tracks release history and assigns incremental revision numbers starting from 1. This allows referencing and rolling back to specific versions. Releases ensure applications can be managed, updated, or removed independently without affecting subsequent deployments.

Helm Architecture

Helm follows a client-server architecture with two main components - the Helm client and the Helm library.

The Helm client is a CLI that end users interact with to perform operations like installing, upgrading, and managing releases. It manages local chart development, repositories, and interacts with the Helm library.

The Helm library encapsulates the core logic for combining charts and configurations into releasable objects and installing, upgrading, and uninstalling releases by interfacing with the Kubernetes API server.

This separation of concerns allows the Helm logic to be reused by different client implementations. The library does the heavy lifting of managing chart rendering, release tracking, and Kubernetes native operations behind the scenes while the Helm client focuses on user interactions and surface commands.

Together, the client and library provide an architecture optimized for lifecycle management of Kubernetes applications packaged into declarative Helm charts.

To learn more about Helm architecture, I recommend visiting our previous post on Helm.

How to Use Helm – Advanced Commands

With an understanding of the internals of helm, lets turn our attention toward some advanced commands and use cases.

Helm fetch

Often times before installing a chart, you’d like to inspect and possibly modify some values before installation, the helm fetch command allows us to do this, in this example we would be using the MySQL helm chart as an example:

helm fetch bitnami/mysql --untar

In a few minutes the MySQL helm chart should be download in the current working directory:

Helm Dry Run

The --dry-run flag allows simulating a helm install or helm upgrade command. This is useful for validating any changes to a chart or its values before actually applying them.
For example, to simulate installing the MySQL chart:

helm install mysql --dry-run bitnami/mysql

This will print the Kubernetes manifests that would be applied, without deploying them on the cluster.

Dry run provides a valuable validation step in chart development and deployment workflows. It acts as a sandbox for experimenting with configuration changes and changing default values before actual deployment.

Helm — generate-name

We can use the — generate-name flag to auto-generate the release name during the helm chart installation

helm install bitnami/tomcat --generate-name --dry-run 

We can also provide a name template for generating the release name during the installation

helm install bitnami/tomcat --dry-run --generate-name \
   --name-template="myserver-{{randAlpha 3}}"

Removing a Helm Repository and Uninstalling a Helm Chart Release

Helm repositories provide access to a collection of charts. While convenient, situations may arise where you no longer need a specific repository

helm repo remove bitnami

This command removes the specified repository named bitnami from your local configuration. After running this command, Helm will no longer search for charts within that repository.

💡
Important Note: This command only removes the repository from your local configuration. It doesn't delete the repository itself or any charts hosted within it.

Once you no longer need a deployed chart, you can remove it using the helm uninstallcommand.

helm uninstall <release-name> 

This command removes the chart release named <release-name> from your Kubernetes cluster. By default, it also removes the release history information.

Advanced Options:

  • --keep-history: This flag preserves the release history, allowing you to roll back to the previous version if needed.

Example:

helm uninstall --keep-history my-mysql-app

--purge: This flag forcefully removes the release and all associated resources, including persistent volumes and secrets. Use this option with caution, as it cannot be undone.

Example:

helm uninstall --purge my-mongodb-app
💡
Remember: Always double-check the release name before using the --purge option, as it can lead to unintended data loss.

Advanced Chart Configuration

The Chart.yaml file is a central part of a Helm chart. It's a YAML-formatted document that defines the essential metadata and configuration details for your application deployment.

Typically a Chart.yaml file would contain:

  • name: The unique identifier for your chart. This name is used for installation, upgrades, and referencing the chart within the Kubernetes cluster.
  • version: The chart's version number, following semantic versioning conventions (e.g., 1.2.3).
  • appVersion: (Optional) The specific application version this chart deploys. This can be useful for tracking application logic changes independent of the chart itself.
  • description: A brief description of the chart and its functionality.
  • maintainers: (Optional) Information about the chart maintainers, including contact details.
  • sources: (Optional) A list of URLs referencing the source code or documentation for the chart.
  • keywords: (Optional) A list of keywords to categorize the chart for easier discovery.
  • dependencies: (Optional) A list of other charts this chart depends on to function properly.
  • icon: (Optional) A URL pointing to an icon representing the chart.
  • deprecated: (Optional) A flag indicating if the chart is deprecated and should no longer be used.
  • apiVersions: (Optional) Specifies the Kubernetes API versions this chart supports.

Here's a basic example Chart.yaml showcasing some key fields:

name: my-webserver
version: 1.0.0
appVersion: v2.1.5
description: A simple web server deployment
maintainers:
  - John Doe <john.doe@example.com>
dependencies:
  - name: nginx-ingress
    repository: https://stable.helm.sh/charts

Helm charts employ a "reconcile" strategy to ensure the deployed state of your application matches the desired state defined in the chart. This strategy defines how Helm reacts to changes made to the chart values or the Kubernetes cluster itself. The most common strategies include:

  • Hook Strategy: Triggers specific hooks (pre-install, post-install, pre-upgrade, post-upgrade, pre-delete, post-delete) during the install/upgrade/uninstall process. Hooks are defined through the use of annotations, a Pre-Install hook would look something like:
annotations:
  "helm.sh/hook": pre-install
  • Wait Strategy: Waits for specific conditions (e.g., pods reaching a ready state) to be met before proceeding with the next step.
  • RollingUpdate Strategy: Upgrades deployments in a rolling fashion, ensuring minimal downtime.

Working with Helm Chart Status

Helm status is a powerful tool command for understanding the current state of your deployed Helm charts.

helm status <release-name> 

Running helm status on a release provides users with vital information about the state of chart including the last time the chart was deployed, the status (deployed, failed or pending install)

Utilize the --show-notes and --show-resources flags with the helm status command:

helm status <release-name> --show-notes

Reveals any notes included within the chart's Chart.yaml file.

helm status <release-name> --show-resources

Lists all Kubernetes resources deployed as part of the release, categorized by kind (e.g., Deployment, Service, etc.).

Waiting for resources

While deploying resources with Helm, you might encounter situations where you want to wait until specific conditions are met before proceeding. This ensures your application is fully functional and ready to handle requests, avoiding potential issues downstream.

The --wait flag allows you to specify conditions that Helm must wait for before marking the deployment as successful. This flag is used in conjunction with the helm upgrade or install command.

Example:

helm install <release-name> bitnami/mysql --wait

This waits until all pods within the release are in a ready state. This is the most common use case, ensuring your application's core functionality is operational before proceeding.

Waiting for Jobs:

  • --wait-for-jobs: When your chart utilizes Jobs for specific tasks like performing migrations or configuration during deployment, you can use --wait-for-jobs in conjunction with --wait. This ensures those Jobs complete successfully before marking the deployment as finished.
💡
Remember: Using --wait can add some time to your deployment process. However, it offers valuable benefits by guaranteeing your application is fully ready before moving forward, potentially saving you from encountering unexpected issues later.

CI/CD with Helm Charts

In the previous post in this series we discussed how to create helm charts using the helm create command, developing charts locally is a great first step towards using helm, more often than not you want to be able to deploy new chart versions in an automated fashion as well as test or lint your charts.

In this section we will be taking a look at how to build and host helm charts using Github Actions and Github pages.

Prerequisites

In order to follow along with this section you would need the following:

Within the your terminal navigate to the directory where you create your helm chart and initialize a new git repository.

git init

To publish the helm repository to GitHub pages, create an empty gh_pages branch in your repo

git checkout --orphan gh-pages
git rm -rf .

git commit -m "scaffold" --allow-empty

# optional if you have added a remote repository 
git remote add <your github repo> 

git push

With the branch created github should set the default deployment branch to gh_pages.

Creating a Personal Access Token

In order to publish the charts we need to provide Github actions with an access token with specific scopes.

On your Github dashboard visit Settings > Developer Settings > Personal Access Token to generate a token.

⚠️  Be sure to select Tokens(Classic)

When creating a token select  workflow,write:packages,delete:packages , click on “Generate Token” and copy the token into a safe place.

Create Repository Secret

Next you’ll need to add the token you just copied to your repository secrets. Visit Settings > Secrets for your repository and add REPO_TOKEN with value of personal token created in previous step.

Before we push the helm chart ets organize the directory structure so it’s easier to publish. Start by switching branches and  creating a new directory in the charts folder

git checkout main && mkdir charts/helm-experiments  

Move chart into the new folder

mv values.yaml Chart.yaml templates charts charts/helm-exp

Finally edit Chart.yaml so your chart has a name:

apiVersion: v2

#name your chart here
name: mychart
description: A Helm chart for Kubernetes

type: application

version: 0.3.0


appVersion: "1.19.0"



git commit -m "add charts" 
git push 

Creating a workflow

with the secrets set and charts pushed we can turn our attention towards the workflow that will publish our charts.

Create a directory to house the workflow file

 mkdir -p .github/workflows

Create a workflow file:

 .github/workflows/release.yaml

In your editor of choice open up release.yaml and add the following configuration

name: Helm Release 

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  helm-release:
    permissions:
      contents: write
    runs-on: ubuntu-latest
    name: Release Helm Chart
    steps:
      - name: Checkout
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Configure Git
        run: |
          git config --global user.name "$GITHUB_ACTOR"
          git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com"

      - name: Install Helm
        uses: azure/setup-helm@v1

      - name: Run User chart-releaser
        uses: helm/chart-releaser-action@v1.6.0

        env:
          CR_TOKEN: "${{ secrets.REPO_TOKEN }}"
          CR_SKIP_EXISTING: true
        with:
          charts_dir: charts

the core step that actually publishes your Helm chart. It uses the helm/chart-releaser-action GitHub Action, which performs the following tasks:

  • Packages your Helm chart into a versioned archive file
  • Creates a new commit with the packaged chart
  • Pushes the new commit to the GitHub repository

Publishes the chart to a GitHub Pages site, using the GH_TOKEN to authenticate with GitHub
The charts_dir input specifies the directory containing your Helm chart files (in this case, charts).

Once the workflow completes you should be able to add the chart repository locally:

 helm repo add experiments <yourusername.github.io>/<reponame>

be sure to replace with your Github username,  and repository name.

Install the chart:

helm install experiments experiments/mychart

In this case mychart refers to the name defined in Chart.yaml

Conclusion

In this article we took a deep dive into some of the advanced features of helm, we also demonstrated how to continuously create helm chart releases using Github actions.

In addition to using Github actions for continuous delivery of our custom charts, you can also leverage GitHub Actions to automate the testing of your Helm charts. The Helm chart-testing-action allows you to define and run tests against your chart installations, ensuring that your charts are thoroughly validated before being released into production environments.

If you're looking to test your chart templates before release take a look at this section of the official documentation for how to lint your template files,  consider using this action from the Helm team,  this makes linting a more straightforward process in CI.

Like this article? Sign up for our newsletter below and become one of over 1000 subscribers who stay informed on the latest developments in the world of DevOps. Subscribe now!

HelmKubernetes

Jubril Oyetunji Twitter

Jubril is a software engineer, primarily focused on building infrastructure using cloud native technologies. When he’s not coding or ranting, he’s sharing his learnings through technical writing.