49 Service Orchestration Understanding the Basics of Helm Service Orchestration

49 Service Orchestration Understanding the Basics of Helm Service Orchestration #

Hello, I am Kong Lingfei.

When deploying applications on Kubernetes, we may need to create multiple services. I have seen a super large application with over 40 microservices, and each service contains multiple Kubernetes resources, such as Service, Deployment, StatefulSet, ConfigMap, etc. The same application needs to be deployed in different environments, such as test, staging, and production environments, which means the application configurations are also different.

For a large-scale application, deploying Kubernetes resources one by one based on YAML files is very tedious and inefficient. Moreover, maintaining these YAML files is extremely complex and prone to errors. So, is there a more efficient way? For example, just like Docker images, we can package all the Kubernetes resource files required by the application together and deploy and manage the application as a whole using this package, thus reducing the complexity of application deployment and maintenance.

The answer is yes. We can use Helm Charts to manage these Kubernetes files and create and manage applications based on the Charts using the helm command.

Next, I will introduce the basics of Helm and demonstrate how to deploy an IAM application based on Helm.

Introduction to Helm Basics #

Helm is currently the de facto standard for Kubernetes service orchestration. Helm provides various functionalities to support Kubernetes service orchestration, such as the helm command-line tool, Chart packages, Chart repositories, etc. Now, let’s dive into the details.

What is Helm? #

Helm is a package manager for Kubernetes, similar to Python’s pip or CentOS’s yum. Helm is primarily used to manage Chart packages. A Helm Chart package consists of a series of YAML-formatted Kubernetes resource definition files and their configurations. With Helm Chart packages, you can maintain these resources as a whole.

Helm also provides a helm command-line tool, which can be used to create applications with one click based on Chart packages. While creating an application, you can customize the Chart configuration. Application publishers can package applications, manage application dependencies and versions, and publish applications to software repositories using Helm. For users, Helm eliminates the need to write complex application deployment files and makes it easy to find, install, upgrade, roll back, and uninstall applications on Kubernetes.

The latest version of Helm is v3, which builds upon the core functionalities of Helm 2 and introduces improvements to Chart repositories, release management, security, and library Charts. The most significant change in Helm 3 compared to Helm 2 is the removal of Tiller (Helm 2 uses a client-server architecture, where the client is called Helm and the server is called Tiller). Helm 3 also introduces new features, deprecates or refactors some features from Helm 2, and is not backward compatible with Helm 2. Additionally, Helm 3 introduces some new experimental features, including OCI support.

Here is the architecture diagram of Helm 3:

Image

In the above architecture diagram, the core components are the Helm Client (the helm command) and Helm Chart packages. The helm command can download Helm Chart packages from the Chart Repository, read the kubeconfig file, and construct HTTP requests to the kube-apiserver’s REST API interface. By calling the REST API interface provided by Kubernetes, all YAML-formatted Kubernetes resources contained in the Chart package are created in the Kubernetes cluster.

These resources exist in the Kubernetes cluster in the form of Releases, where each Release contains multiple Kubernetes resources, such as Deployments, Pods, Services, etc.

Three Key Concepts in Helm #

To learn and use Helm, it is essential to understand the three key concepts in Helm. Most of the Helm operations revolve around these concepts. Let me introduce the three key concepts in Helm.

  • Chart: Represents a Helm package. It includes all the YAML-formatted resource definition files required to run an application, tool, or service in a Kubernetes cluster.
  • Repository: A place to store and share Helm Charts, similar to GitHub repositories for storing source code and Docker repositories for storing images.
  • Release: An instance of a Chart running in a Kubernetes cluster. A Chart can usually be installed multiple times in the same cluster, creating a new Release each time.

Why do we need to use Helm? #

Now that you have a basic understanding of Helm, let me explain in detail why we need to use Helm.

First, let’s take a look at the traditional application deployment model:

Image

We have three environments: testing, staging, and production. Each environment deploys an application A, which contains multiple services. Each service has its own configuration, and some configurations are shared between different services, such as Configuration A.

Each service is defined and created using a complex Kubernetes YAML file. As you can see, it is a very complex task to maintain these YAML files and deploy applications with different configurations in different environments using the traditional approach. Additionally, maintaining these YAML files and deploying applications in a Kubernetes cluster becomes complex over time. As the scale of microservices grows, the following challenges arise:

  • The increasing number of microservices poses a significant challenge to service management.
  • The growing number of services increases the difficulty of management and poses challenges to deployment in operations.
  • The increased number of services raises higher requirements for service configuration management.
  • As the number of services increases, managing service dependencies becomes more complex.
  • It becomes increasingly difficult to quickly deploy a complex application in a new environment in terms of managing environment information.

Therefore, we need a better way to maintain and manage these YAML files and applications deployed in Kubernetes. Helm can help us address these challenges.

Next, let’s see how Helm solves these problems.

In Helm, there are two types of files: template files and configuration files. Template files are usually multiple, whereas configuration files are typically one. Helm’s template files are based on text/template templates, providing more powerful template rendering capabilities. Helm can render the values from the configuration files into the template files, resulting in a deployable YAML-formatted Kubernetes resource definition file, as shown in the following diagram:

Image

In the diagram above, we have rendered the following configuration into the template and generated a Kubernetes YAML file:

replicas: 2
tag: latest
common:
    username: colin
    password: iam1234

Therefore, in Helm, deploying an application can be simplified as Chart templates (multiple services) + Chart configuration -> Application, as shown in the following diagram:

Image

Chart templates need to be written only once for an application and can be reused. During deployment, you can specify different configurations to deploy the application in different environments or with different configurations within the same environment.

Hands-on Helm Operations #

In the previous section, I introduced some basic knowledge about Helm. Now let’s learn how to use Helm for application lifecycle management.

Prerequisites #

Before we get started, make sure you have a Kubernetes cluster to work with. The most convenient, fast, and economical way is to apply for a Tencent Cloud EKS cluster. As for how to apply and access it, you can refer to the tutorial in Lesson 48, “Preparing a Kubernetes Cluster”. Here’s a reminder: after you finish using the cluster, remember to delete the cluster resources to avoid continuous charges.

Installing Helm #

Helm provides multiple installation methods. If you have internet access, you can use a script to install Helm. Use the following installation commands:

$ mkdir -p $HOME/bin
$ wget https://get.helm.sh/helm-v3.6.3-linux-amd64.tar.gz
$ tar -xvzf helm-v3.6.3-linux-amd64.tar.gz
$ mv linux-amd64/helm $HOME/bin
$ chmod +x $HOME/bin/helm
$ helm version
version.BuildInfo{Version:"v3.6.3", GitCommit:"d506314abfb5d21419df8c7e7e68012379db2354", GitTreeState:"clean", GoVersion:"go1.16.5"}

If executing helm version can print out the version number of the helm command, it means that Helm is installed successfully.

The installation package addresses of different Helm versions can be found under Helm Releases.

After installing the helm command, you can install the autocomplete script for the helm command. If you are using the bash shell, use the following installation method:

$ helm completion bash > $HOME/.helm-completion.bash
$ echo 'source $HOME/.helm-completion.bash' >> ~/.bashrc
$ bash

Executing helm comp<TAB> will automatically complete to helm completion.

Getting Started with Helm #

You can quickly create a Chart application by following these six steps.

Step 1: Initialize a Helm Chart repository.

After installing Helm, you can use the helm command to add a Chart repository. Similar to DockerHub for hosting Docker images and GitHub for hosting code, Chart packages also have a hosting platform. Currently, the popular Chart package hosting platform is Artifact Hub.

Artifact Hub has many Chart repositories. You can add the desired Chart repositories. Here, we add the Chart repository provided by BitNami:

$ helm repo add bitnami https://charts.bitnami.com/bitnami # Add Chart Repository
$ helm repo list # View the added Repository list

After adding, we can use the helm search command to query the desired Chart packages. helm search supports two different query methods, and I will introduce them below.

  • helm search repo <keyword>: Search in the repositories added to the local Helm client using helm repo add. This command searches based on local data and does not require an internet connection.
  • helm search hub <keyword>: Search and list Helm Charts from Artifact Hub. Artifact Hub contains a large number of repositories.

Helm search uses fuzzy string matching algorithm, so you can enter only a part of the name. Here’s an example of helm search:

$ helm search repo bitnami
NAME                                        	CHART VERSION	APP VERSION  	DESCRIPTION
bitnami/bitnami-common                      	0.0.9        	0.0.9        	DEPRECATED Chart with custom templates used in ...
bitnami/airflow                             	10.2.8       	2.1.2        	Apache Airflow is a platform to programmaticall...
bitnami/apache                              	8.6.1        	2.4.48       	Chart for Apache HTTP Server
bitnami/argo-cd                             	1.0.2        	2.0.5        	Declarative, GitOps continuous delivery tool fo...
bitnami/aspnet-core                         	1.3.14       	3.1.18       	ASP.NET Core is an open-source framework create...
bitnami/cassandra                           	8.0.2        	4.0.0        	Apache Cassandra is a free and open-source dist...
bitnami/cert-manager                        	0.1.15       	1.5.1        	Cert Manager is a Kubernetes add-on to automate...
# ... and many more

Step 2: Install an example Chart.

After finding the desired Helm Chart, you can use the helm install command to install a Chart. helm install supports installation from multiple sources:

  • Chart repository.
  • Local Chart Archive, for example, helm install foo foo-1.0.0.tgz.
    • An unpackaged Chart path, for example helm install foo path/to/foo.
    • A complete URL, for example helm install foo https://example.com/charts/foo-1.0.0.tgz.

Here, we choose to install a MySQL application using the bitnami/mysql Chart package. You can execute the command helm show chart bitnami/mysql to get a basic understanding of this Chart’s information. Alternatively, you can execute helm show all bitnami/mysql to get all the information about this Chart.

Next, you can use the helm install command to install this Chart package. The installation command is as follows:

$ helm repo update              # Make sure we get the latest list of charts
$ helm install bitnami/mysql --generate-name
NAME: mysql-1629528555
LAST DEPLOYED: Sat Aug 21 14:49:19 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES: ...

In the above example, we installed the bitnami/mysql Chart and created a mysql-1629528555 Release. The --generate-name option tells Helm to automatically name this Release.

During the installation process, the Helm client will print out some useful information, including which resources have been created, the current status of the Release, and whether you need to perform additional configuration steps. For example, from the output of the above example, you can get information such as the root password, login method, update method, etc. of the database.

After installation, you can use helm status to track the status of the Release.

Every time you execute helm install, a new release version is created. So a Chart can be installed multiple times in the same cluster, and each one can be managed and upgraded independently.

The helm install command renders the templates into the final YAML format that Kubernetes can recognize, and then installs them into the Kubernetes cluster.

helm install is a very powerful command. If you want to learn more about its functionality, you can refer to this guide: Using Helm.

Step 3: Pre-install Chart customizations.

The installation method used in the previous step only uses the default configuration options of the Chart. Many times, we need to customize the Chart to specify the configurations we want. You can use helm show values to view the configurable options in the Chart:

$ helm show values bitnami/mysql # For convenience of display, I removed the `#` comments in the output of `helm show values`
# ... and many more
architecture: standalone
auth:
  rootPassword: ""
  database: my_database
  username: ""
  password: ""
  replicationUser: replicator
  replicationPassword: ""
  existingSecret: ""
  forcePassword: false
  usePasswordFiles: false
  customPasswordFiles: {}
initdbScripts: {}
# ... and many more

Then, you can use a YAML file to override any of the above configurations and use the file during the installation process.

$ echo '{auth.database: iam, auth.username: iam, auth.password: iam59!z$}' > values.yaml
$ helm install bitnami/mysql -f values.yaml --generate-name

The above command will create a default user named iam with a password of iam59!z$ for MySQL, and grant this user access to the newly created iam database. The other default configurations in the Chart remain unchanged.

During the installation process, there are two ways to pass configuration data.

  • -f, --values: Use a YAML file to override the configurations. Multiple files can be specified, and the rightmost file takes precedence.
  • --set: Override specific configuration options through the command line.

If both methods are used, the values in --set will be merged into --values, but the values in --set have higher priority. The contents overridden in --set will be stored in a ConfigMap. You can use helm get values <release-name> to view the values set by --set in a specific Release, or use helm upgrade with the --reset-values flag to clear the values set by --set.

Now, let me explain the format and restrictions of --set.

The --set option uses one or more key-value pairs. The simplest usage is like --set name=value, which is equivalent to the following YAML format: name: value

Values are separated by commas, so the YAML representation of --set a=b,c=d is:

a: b
c: d

--set also supports more complex expressions. For example, --set outer.inner=value is converted to:

outer:
  inner: value

Lists are represented using curly braces {}. For example, --set name={a, b, c} is converted to:

name:
  - a
  - b
  - c

Starting from version 2.5.0, we can use array indexing syntax to access elements in a list. For example, --set servers[0].port=80 becomes:

servers:
  - port: 80

Multiple values can also be set this way. --set servers[0][0].host=``marmotedu becomes:

servers:
  - port: 80
    host: marmotedu

If you need to use special characters in --set, you can use backslash to escape them. For example, --set name=value1\,value2 becomes:

name: "value1,value2"

If the data structure is deeply nested, it may be difficult to express it using --set. For more information, you can refer to the Values Files documentation.

Step 4, View the Releases in the current Cluster

You can use helm list to view the list of Releases installed in the current cluster and namespace:

$ helm list
NAME            	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART      	APP VERSION
mysql-1629528555	default  	1       	2021-08-21 14:49:19.101935218 +0800 CST	deployed	mysql-8.8.4	8.0.26
mysql-1629529348	default  	1       	2021-08-21 15:02:32.079969128 +0800 CST	deployed	mysql-8.8.4	8.0.26

You can see that we have created two Releases, which are located in the default namespace. The command above also shows the update time, status, chart version, and app version of the Releases.

Step 5, Upgrade a Release and Rollback on Failure

After deploying an application, you may need to upgrade it in the future. You can use the helm upgrade command to upgrade an application. The upgrade operation is based on the existing Release and will only modify the content that has changed.

For example, let’s upgrade mysql-1629528555 and change its root password:

$ helm upgrade mysql-1629528555 bitnami/mysql --set auth.rootPassword='iam59!z$'

In the example above, the mysql-1629528555 Release is upgraded using the same Chart, but with a new rootPassword configuration.

We can use the helm get values command to check if the configuration value has been updated:

$ helm get values mysql-1629528555
USER-SUPPLIED VALUES:
auth:
  rootPassword: iam59!z$

You can see that the new value of rootPassword has been deployed to the cluster.

In case the upgrade fails, you can easily rollback to a previous version using the helm rollback [RELEASE] [REVISION] command.

$ helm rollback mysql-1629528555 1

The command above rolls back our mysql-1629528555 to its initial version. The version of a Release is an incrementing revision. Every time an installation, upgrade, or rollback operation occurs, the revision value is incremented. The initial revision value is always 1.

You can use the helm history [RELEASE] command to view the revision version of a specific Release:

$ helm history mysql-1629528555
REVISION	UPDATED                 	STATUS    	CHART      	APP VERSION	DESCRIPTION
1       	Sat Aug 21 14:49:19 2021	superseded	mysql-8.8.4	8.0.26     	Install complete
2       	Sat Aug 21 15:14:45 2021	deployed  	mysql-8.8.4	8.0.26     	Upgrade complete

You can also specify other options to customize Helm’s behavior during installation, upgrade, and rollback operations. Here, I’ll introduce some commonly used parameters for your reference:

  • --timeout: A Go duration value that represents the timeout for waiting for Kubernetes commands to complete. The default value is 5m0s.
  • --no-hooks: Disables running hooks for the current command.
  • --wait: Specifies that the command should wait until all Pods are in the ready state, PVCs are bound, and the number of ready Pods in Deployments reaches the minimum value (Desired minus maxUnavailable) before marking the Release as successful. The maximum wait time is specified by the --timeout value. If the timeout is reached, the Release is marked as FAILED.

Note that when the replicas of a Deployment are set to 1, but maxUnavailable in its rolling upgrade strategy is not set to 0, --wait returns when the minimum ready Pod count is met.

Step 6, Uninstall a Release

You can use the helm uninstall command to uninstall a Release:

$ helm  uninstall mysql-1629528555

The above command uninstalls mysql-1629528555 from Kubernetes and deletes all associated resources (Service, Deployment, Pod, ConfigMap, etc.) related to that version, including all version history of the Release.

If you provide the --keep-history option when executing helm uninstall, Helm will keep the version history. You can use the helm status command to view the information of that version:

$ helm status mysql-1629528555
Status: UNINSTALLED
...

Because the --keep-history option allows Helm to track your versions (even if you uninstall them), you can audit the cluster history and even use helm rollback to roll back versions.

Helm Commands #

Above, I introduced the usage of some Helm commands. If you want to see all the commands provided by Helm, you can execute helm help. Alternatively, you can execute helm <subcommand> -h to see the usage of a specific subcommand, for example:

$ helm get -h

This command consists of multiple subcommands which can be used to get extended information about the release, including:

  • The values used to generate the release
  • The generated manifest file
  • The notes provided by the chart of the release
  • The hooks associated with the release

Usage: helm get [command]

… and many more #

I have compiled a list of commands for your reference:

Image

Some of these commands have subcommands and command-line arguments. You can execute helm <subcommand> -h to view them specifically.

Summary #

Today, I introduced the basics of Helm and demonstrated how to deploy an IAM application using Helm.

When an application consists of many microservices, manually deploying, upgrading, and rolling back these microservices in a Kubernetes cluster can be a complex task. In such cases, we need a service orchestration solution to orchestrate these services and improve the efficiency of deployment and maintenance.

Currently, there are various service orchestration solutions available in the industry, and the most popular one is Helm, which has become the de facto standard for Kubernetes service orchestration.

In Helm, there are three key concepts: Chart, Repository, and Release. A Chart represents a Helm package containing all the YAML files defining the resources needed to run a Kubernetes application. A Repository is a storage location for Helm Charts, where they can be stored and shared. A Release is an instance of a Chart running in a Kubernetes cluster.

We can use helm install [NAME] [CHART] [flags] to install a Chart package, helm upgrade [RELEASE] [CHART] [flags] to update a Helm Release, and helm uninstall RELEASE_NAME [...] [flags] to uninstall a Helm Release. Additionally, the helm command-line tool provides other functionalities which you can review again.

Homework Exercises #

  1. Think about whether there is a problem of starting a service before creating a service configuration when using Helm. If there is, how can Helm solve this problem?
  2. Try packaging IAM application as a Chart and install it using Helm.

Feel free to leave a message in the comment section to discuss and communicate with me. See you in the next lesson.