Over time, the Kubernetes community discovered that creating and maintaining Kubernetes resources to deploy applications is difficult. This prompted the development of a simple yet powerful tool that would allow teams to overcome the challenges posed by deploying applications on Kubernetes. The tool that was created is called Helm. Helm is an open source tool used for packaging and deploying applications on Kubernetes. It is often referred to as the Kubernetes Package Manager because of its similarities to any other package manager you would find on your favorite OS. Helm is widely used throughout the Kubernetes community and is a CNCF graduated project.
Given Helm's similarities to traditional package managers, let's begin exploring Helm by first reviewing how a package manager works.
Understanding package managers
Package managers are used to simplify the process of installing, upgrading, reverting, and removing a system's applications. These applications are defined in units, called packages, which contain metadata around target software and its dependencies.
The process behind package managers is simple. First, the user passes the name of a software package as an argument. The package manager then performs a lookup against a package repository to see whether that package exists. If it is found, the package manager installs the application defined by the package and its dependencies to the specified locations on the system.
Package managers make managing software very easy. As an example, let's imagine you wanted to install htop
, a Linux system monitor, to a Fedora machine. Installing this would be as simple as typing a single command:
dnf install htop
--assumeyes
This instructs dnf
, the Fedora package manager since 2015, to find htop
in the Fedora package repository and install it. dnf
also takes care of installing the htop
package's dependencies, so you would not have to worry about installing its requirements beforehand. After dnf
finds the htop
package from the upstream repository, it asks you whether you're sure you want to proceed. The --assumeyes
flag automatically answers yes
to this question and any other prompts that dnf
may potentially ask.
Over time, newer versions of htop
may appear in the upstream repository. dnf
and other package managers allow users to efficiently upgrade to new versions of the software. The subcommand that allows users to upgrade using dnf
is upgrade:
dnf upgrade htop
--assumeyes
This instructs dnf
to upgrade htop
to its latest version. It also upgrades its dependencies to the versions specified in the package's metadata.
While moving forward is often better, package managers also allow users to move backward and revert an application back to a prior version if necessary. dnf
does this with the downgrade
subcommand:
dnf downgrade htop
--assumeyes
This is a powerful process because the package manager allows users to quickly roll back if a critical bug or vulnerability is reported.
If you want to remove an application completely, a package manager can take care of that as well. dnf
provides the remove
subcommand for this purpose:
dnf remove htop
--assumeyes
In this section, we reviewed how the dnf
package manager on Fedora can be used to manage a software package. Helm, as the Kubernetes package manager, is similar to dnf
, both in its purpose and functionality. While dnf
is used to manage applications on Fedora, Helm is used to manage applications on Kubernetes. We will explore this in greater detail next.
The Kubernetes package manager
Given that Helm was designed to provide an experience similar to that of package managers, experienced users of dnf
or similar tools will immediately understand Helm's basic concepts. Things become more complicated, however, when talking about the specific implementation details. dnf
operates on RPM
packages that provide executables, dependency information, and metadata. Helm, on the other hand, works with charts. A Helm chart can be thought of as a Kubernetes package. Charts contain the declarative Kubernetes resource files required to deploy an application. Similar to an RPM
, it can also declare one or more dependencies that the application needs in order to run.
Helm relies on repositories to provide widespread access to charts. Chart developers create declarative YAML files, package them into charts, and publish them to chart repositories. End users then use Helm to search for existing charts to deploy onto Kubernetes, similar to how end users of dnf
will search for RPM
packages to deploy to Fedora.
Let's go through a basic example. Helm could be used to deploy Redis
, an in-memory cache, to Kubernetes by using a chart published to an upstream repository. This could be performed using Helm's install
command:
helm install redis
bitnami/redis --namespace=redis
This would install the redis
chart from the bitnami chart repository to a Kubernetes namespace called redis
. This installation would be referred to as the initial revision, or the initial deployment of a Helm chart.
If a new version of the redis
chart becomes available, users can upgrade to a new version using the upgrade
command:
helm upgrade redis
bitnami/redis --namespace=redis
This would upgrade Redis
to meet the specification defined by the newer redis
-ha chart.
With operating systems, users should be concerned about rollbacks if a bug or vulnerability is found. The same concern exists with applications on Kubernetes, and Helm provides the rollback command to handle this use case:
helm rollback redis
1 --namespace=redis
This command would roll Redis
back to its first revision.
Finally, Helm provides the ability to remove Redis
altogether with the uninstall
command:
helm uninstall redis
--namespace=redis
Compare dnf
, Helm's subcommands, and the functions they serve in the following table. Notice that dnf
and Helm offer similar commands that provide a similar user experience:
With an understanding of how Helm functions as a package manager, let's discuss in greater detail the benefits that Helm brings to Kubernetes.The benefits of Helm
Earlier in this chapter, we reviewed how Kubernetes applications are created by managing Kubernetes resources, and we discussed some of the challenges involved. Here are few ways that Helm can overcome these challenges.
The abstracted complexity of Kubernetes resources
Let's assume that a developer has been given the task of deploying a MySQL database onto Kubernetes. The developer would need to create the resources required to configure its containers, network, and storage. The amount of Kubernetes knowledge required to configure such an application from scratch is high and is a big hurdle for new and even intermediate Kubernetes users to clear.
With Helm, a developer tasked with deploying a MySQL database could simply search for MySQL charts in upstream chart repositories. These charts would have already been written by chart developers in the community and would already contain the declarative configuration required to deploy a MySQL database. In this regard, developers with this kind of task would act as simple end users that use Helm in a similar way to any other package manager.
The ongoing history of revisions
Helm has a concept called release history. When a Helm chart is installed for the first time, Helm adds that initial revision to the history. The history is further modified as revisions increase via upgrades, keeping various snapshots of how the application was configured at varying revisions.
The following diagram depicts an ongoing history of revisions. The squares in blue illustrate resources that have been modified from their previous versions:
Figure 1.6 - An example of a revision history
The process of tracking each revision provides opportunities for rollback. Rollbacks in Helm are very simple. Users simply point Helm to a previous revision and Helm reverts the live state to that of the selected revision. With Helm, gone are the days of the n-1
backup. Helm allows users to roll back their applications as far back as they desire, even back to the very first installation.
Dynamically configured declarative resources
One of the biggest hassles with creating resources declaratively is that Kubernetes resources are static and cannot be parameterized. As you may recall from earlier, this results in resources becoming boilerplate across applications and similar configurations, making it more difficult for teams to configure their applications as code. Helm alleviates these issues by introducing values and templates.
Values are simply what Helm calls parameters for charts. Templates are dynamically generated files based on a given set of values. These two constructs provide chart developers the ability to write Kubernetes resources that are automatically generated based on values that end users provide. By doing so, applications managed by Helm become more flexible, less boilerplate, and easier to maintain.
Values and templates allow users to do things such as the following:
- Parameterize common fields, such as the image name in a Deployment and the ports in a Service
- Generate long pieces of YAML configuration based on user input, such as volume mounts in a Deployment or the data in a ConfigMap
- Include or exclude resources based on user input
The ability to dynamically generate declarative resource files makes it simpler to create YAML-based resources while still ensuring that applications are created in an easily reproducible fashion.
Consistency between the local and live states
Package managers prevent users from having to manage an application and its dependencies manually. All management can be done through the package manager itself. The same idea holds true with Helm. Because a Helm chart contains a flexible configuration of Kubernetes resources, users shouldn't have to make modifications directly to live Kubernetes resources. Users that want to modify their applications can do so by providing new values to a Helm chart or by upgrading their application to a more recent version of the associated chart. This allows the local state (represented by the Helm chart configuration) and the live state to remain consistent across modifications, giving users the ability to provide a source of truth for their Kubernetes resource configurations.
Intelligent Deployments
Helm simplifies application deployments by determining the order that Kubernetes resources need to be created. Helm analyzes each of a chart's resources and orders them based on their types. This pre-deterministic order exists to ensure that resources that commonly have resources dependent on them are created first. For example, Secrets and ConfigMaps should be created before Deployments, since a Deployment would likely consume those resources as volumes. Helm performs this ordering without any interaction from the user, so this complexity is abstracted and prevents users from needing to worry about the order that these resources are applied.
Automated life cycle hooks
Similar to other package managers, Helm provides the ability to define life cycle hooks. Life cycle hooks are actions that take place automatically at different stages of an application's life cycle. They can be used to do things such as the following:
- Perform a data backup on an upgrade.
- Restore data on a rollback.
- Validate a Kubernetes environment prior to installation.
Life cycle hooks are valuable because they abstract complexities around tasks that may not be Kubernetes-specific. For example, a Kubernetes user may not be familiar with the best practices behind backing up a database or may not know when such a task should be performed. Life cycle hooks allow experts to write automation that performs those best practices when recommended so that users can continue to be productive without needing to worry about those details.