When working with Kubernetes, managing application deployments can quickly become complex. As applications grow, so does the number of configuration files needed to deploy them.
Helm, often described as the package manager for Kubernetes, offers an elegant solution to this challenge through the concept of Helm charts.
In this guide, we'll dive deep into what Helm charts are, how they work, and how you can use them to simplify your Kubernetes deployments.
What are Helm charts?
Helm charts are packages of pre-configured Kubernetes resources that can be
managed as a single unit. Think of them as the equivalent of a software package
in traditional package managers like apt, yum, or npm, but specifically
designed for Kubernetes applications.
A Helm chart contains all the resource definitions necessary to run an application in a Kubernetes cluster. This includes deployments, services, config maps, secrets, and any other Kubernetes resources your application might need. By bundling these resources together, Helm charts make it significantly easier to deploy and manage complex applications on Kubernetes.
The problem Helm charts solve
To understand why Helm charts are valuable, consider this common scenario:
You have a microservice-based application consisting of several components, each requiring multiple Kubernetes resources (deployments, services, config maps, etc.). For each environment (development, staging, production), these resources need slight variations in configuration.
Without Helm, you would:
- Maintain separate YAML files for each resource
- Manually track which files go together
- Create different versions of these files for each environment
- Manually handle updates and rollbacks
This approach becomes unwieldy as your application grows. Helm charts solve this problem by:
- Bundling related resources together
- Providing templating capabilities for configuration
- Managing versioning and release history
- Simplifying updates and rollbacks
Core concepts of Helm charts
Before diving deeper into Helm charts, let's understand some core concepts:
Chart: A package containing all the resource definitions needed to run an application on Kubernetes.
Release: An instance of a chart running in a Kubernetes cluster. When you install a chart, Helm creates a new release. Each release has a unique name.
Repository: A place where charts can be stored and shared. Similar to Docker Hub for Docker images.
Values: Configuration options for a chart that can be overridden during installation or upgrade.
Anatomy of a Helm chart
Let's look at the key components of a Helm chart:
Chart.yaml
This file contains metadata about the chart, such as its name, version, description, and dependencies.
values.yaml
This file contains default configuration values for the chart. These values can be overridden during installation.
Templates directory
This directory contains template files that generate Kubernetes manifests. These
templates use values from the values.yaml file and can include conditional
logic and loops.
In this template, expressions like {{ .Values.replicaCount }} will be replaced
with values from the values.yaml file. The .Release.Name refers to the name
given when installing the chart.
Creating your first Helm chart
Let's create a simple Helm chart for a web application. Before you proceed, ensure that you have helm installed.
This command generates a chart with the default structure:
Edit the Chart.yaml file to include your application details:
Then modify the values.yaml file with your application's configuration:
The default templates include deployment.yaml, service.yaml, and others. You
can modify these or create new ones based on your requirements.
Now you can validate your chart using the lint and template commands:
This command will output the rendered Kubernetes manifests without installing them.
Installing a Helm chart
Once your chart is ready, you can install it in your Kubernetes cluster:
This command installs the chart with the release name my-release. You can
customize the values during installation if you wish:
Or use a custom values file like this:
Working with Helm repositories
Helm charts can be shared through repositories. The Artifact Hub (previously known as the Helm Hub) is a public repository for Helm charts.
For example, here's how to add the Bitnami application catalog:
Then update your repose as follows:
Once the repos are up-to-date, you can search for Helm charts with:
You will likely see a few results with hopefully the chart you're looking for. Once you've identified it, go ahead and install it using:
Customizing charts with templating
One of the most powerful features of Helm is its templating engine, which is based on Go templates. This allows you to create dynamic Kubernetes manifests that adapt to different environments and configurations.
Basic templating
Conditionals
Loops
Upgrading and rolling back releases
Helm makes it easy to upgrade applications and roll back to previous versions if needed.
To upgrade to a new release, use:
This command updates the existing release with new values.
You can also check the revision history with:
Finally, you can revert to a previous version using:
This command rolls back to revision 1.
Managing dependencies with Helm charts
Helm allows you to manage dependencies between charts, making it easier to
deploy complex applications. To define these dependencies, you'll add them to
your Chart.yaml file.
For example, if your application requires MongoDB, you can specify it as a dependency by including the relevant information about the chart: its name, the specific version you need, the repository where it can be found, and optionally a condition that determines whether it should be installed.
Here's how you would define a MongoDB dependency:
The condition field is particularly useful as it allows you to make the
dependency optional. In this example, MongoDB will only be installed if the
value mongodb.enabled is set to true in your values.yaml file. This gives
you flexibility to deploy your application with or without certain dependencies
based on your environment requirements.
Once you've defined your dependencies, you need to download them before installing your chart. You can do this with the dependency update command:
This command reads the dependencies from your Chart.yaml file and downloads all
the required charts to the charts/ directory within your own chart. Each
dependency is downloaded as a packaged .tgz file, which will be extracted and
installed when you deploy your main chart.
When you install your chart, Helm will automatically install all these dependencies in the correct order, handling any relationship or dependency chain that might exist between them.
This approach to managing dependencies significantly simplifies the deployment of complex applications, ensuring that all components are installed consistently and with the correct configurations.
It also makes your charts more modular and reusable, as you can easily swap in different versions of dependencies or conditionally include them based on your deployment needs.
Creating a real-world application chart
Let's create a more realistic example: a chart for a web application with a Redis cache. We'll walk through the entire process step by step.
To begin, we'll initialize a new Helm chart using the helm create command.
This generates the standard directory structure and template files that we'll
customize for our application:
Next, we need to define our chart's dependencies. Since our application requires Redis, we'll add it as a dependency in the Chart.yaml file. We'll specify that we want to use version 16.0.0 of the Redis chart from the Bitnami repository, and we'll make it conditional so it can be enabled or disabled as needed:
With our dependencies defined, we'll now configure the default values for our chart in the values.yaml file. We'll set up our application to run two replicas using a specific image.
We'll configure a ClusterIP service to expose it within the cluster on port 80, and set up an ingress with the NGINX ingress controller. We'll also define resource limits and requests to ensure our application gets the resources it needs.
Finally, we'll configure the Redis dependency to use a standalone architecture with password authentication:
Now we need to update the deployment template to connect our application to
Redis. We'll modify the templates/deployment.yaml file to include environment
variables that point to our Redis instance.
This deployment will use the values we defined earlier, such as the replica count, image details, and resource limits.
The environment variables REDIS_HOST and REDIS_PASSWORD will allow our
application to connect to the Redis instance that will be deployed as part of
our chart:
With our chart fully configured, we're ready to install it. First, we need to update the dependencies to download the Redis chart:
This command downloads the Redis chart and stores it in the charts/ directory
of our web-app chart. Finally, we can install our chart with a single command:
This command deploys our web application and the Redis dependency to our Kubernetes cluster as a single release named "my-web-app".
Helm handles the creation of all the necessary Kubernetes resources, including the deployment, service, ingress, and Redis components.
Our application is now deployed and configured to connect to Redis using the environment variables we defined in the deployment template.
Final thoughts
Helm charts provide a powerful way to package, configure, and deploy applications on Kubernetes. By leveraging Helm's templating capabilities, dependency management, and versioning features, you can significantly reduce the complexity of managing applications in Kubernetes environments.
Whether you're deploying a simple web service or a complex microservices architecture, Helm charts offer a standardized approach that improves consistency, reproducibility, and maintainability across your entire application lifecycle.
As you continue your Kubernetes journey, consider exploring the vast ecosystem of public Helm charts available on Artifact Hub, contributing to open-source charts, or creating your own organizational chart repository to share best practices and standardized deployments across your teams.