Helm Chart: quick start your app deployment on Kubernetes

Photo by Loik Marras on Unsplash

What is helm?

Helm is an application package manager for Kubernetes (think apt or yum or chocolatey for Windows). Helm downloads, installs and deploys apps for you on the Kubernetes.

Helm helps you manage Kubernetes applications — Helm Charts helps you define, install, and upgrade even the most complex Kubernetes application.

Charts are easy to create, version, share, and publish — so start using Helm and stop the copy-and-paste.

Helm is a graduate project in the CNCF and is maintained by the Helm community.

Using Helm

  • You can install, upgrade, and delete installation.
  • You can search the repository to find what Kubernetes applications are available.
  • You can configure applications prior to installing them.
  • You can see what is already installed and how it is configured.

The focus of this article is Helm 3. Earlier version Helm 2 is not recommended anymore.

What is a helm chart?

Creating your first chart

app/ 
charts/ #
templates/
.helmignore #
Chart.yaml
values.yaml
  • charts: a directory containing any charts upon which this chart depends.
  • templates: a directory of templates that, when combined with values, # will generate valid Kubernetes manifest files.
  • .helmignore: defines all files to ignore when packaging chart.
  • Chart.yaml: a YAML file containing information about the chart.
  • values.yaml: the default configuration values for this chart

Chart Definition

apiVersion: v2 
name: app
description: A Helm chart for Kubernetes
type: application version: 0.1.0
appVersion: "1.16.0"
  • apiVersion: v2 denotes Helm 3.
  • Version: This is the chart version. You are supposed to make changes to the version every time you make changes to the chart.
  • Type: A chart can be either ‘application’ or ‘library’. Application charts are what you deploy on Kubernetes. You can think of a library chart as a utility chart that provides utility functions for the other charts. You can include a library chart with other charts.
  • appVersion: the version number of your application. You should increment the version each time you make changes to the application.

Default Configuration

replicaCount: 1 
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""

It’s possible to override default values but more about this later.

Template

apiVersion: apps/v1 
kind: Deployment
metadata:
name: {{ include "app.fullname" . }}
labels:
{{- include "app.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }} {{- end }}

A template directive is enclosed in {{ and }} blocks.

Installing a chart

helm install my-app app

This will install a chart app with the installation name my-app.

An installation of a chart is a specific instance of the chart. You can have many installations of the same chart. When you run the helm install command, you need to give it an installation name as well as the chart name.

Running above command prints:

NAME: my-app 
LAST DEPLOYED: Sat Jul 3 12:16:04 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=app,app.kubernetes.io/instance=my-app" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT

You can validate Helm installation by running the command kubectl get deployment:

NAME   READY   UP-TO-DATE   AVAILABLE   AGE 
my-app 1/1 1 1 9s

or by using command helm list:

NAME    NAMESPACE  REVISION STATUS     CHART      APP VERSION 
my-app default 1 deployed app-0.1.0 1.16.0

To uninstall an installation run command helm uninstall my-app. This will remove all resources associated with a particular installation.

A Helm chart installation can contain many Kubernetes resources. Kubernetes sees each of these as a discrete resource. But in Helm’s view, all of the resources defined by a chart are related. So when you run the uninstall command it removes all Kubernetes resources associated with that particular installation. In the above case Helm not only removes deployment but also service associated with the installation ‘my-app’.

When you run command helm install my-app app, Helm installs the application my-app on the Kubernetes cluster. But how does Helm knows about the Kubernetes cluster?

How does the Helm know about which Kubernetes cluster to connect?

You can also override these settings with environment variables ( HELM_KUBECONTEXT) and command-line flags (--kube-context). It's recommended that you use Kubectl to manage Kubernetes credentials and let Helm autodetect these settings.

Installing a third party chart

Before you start using the MySQL chart published by Bitnami, you need to tell Helm about the Bitnami repo as:

helm repo add bitnami https://charts.bitnami.com/bitnami

You can list all repositories, which your Helm knows about, as:

helm repo list NAME    URL 
bitnami https://charts.bitnami.com/bitnami

You can search the chart as:

helm search repo mysql 

Installing a chart

helm install appdb bitnami/mysql NAME: appdb 
LAST DEPLOYED: Sat Jul 3 16:24:19 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1 TEST SUITE: None
NOTES:
** Please be patient while the chart is being deployed ** Tip: Watch the deployment status using the command: kubectl get pods -w --namespace default Services:
echo Primary: appdb-mysql.default.svc.cluster.local:3306

You can run helm list to validate MySQL deployment as:

helm list NAME    NAMESPACE   REVISION   STATUS     CHART         APP VERSION 
appdb default 1 deployed mysql-8.7.0 8.0.25

Configuring Values

helm inspect values bitnami/mysql ## Global Docker image parameters 
## Please, note that this will override the image parameters, including dependencies, configured to use the global value
## Current available global Docker image parameters: imageRegistry and imagePullSecrets
##
# global:
# imageRegistry: myRegistryName
# imagePullSecrets:
# - myRegistryKeySecretName
# storageClass: myStorageClass
## Bitnami MySQL image
## ref: https://hub.docker.com/r/bitnami/mysql/tags/
##

You can override the default values by providing a values.yaml file with --values flag as:

helm install appdb bitnami/mysql --values values.yaml

--values flag can be set with both helm install and upgrade commands.

You can also use --set flag to override default values. If you use --set flag with values.yaml, to override the same value, then --set flag gets precedence.

helm upgrade appdb bitnami/mysql --values values.yaml --set auth.rootPassword=$ROOT_PASSWORD 
Release "appdb" has been upgraded. Happy Helming!
NAME: appdb
LAST DEPLOYED: Tue Jul 6 08:32:41 2021
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None

whereas values.yaml contains:

auth.database: product_db

It is recommended as a best practice to use values.yaml instead of --set flag. The reason for that is you can version values.yaml in version control.

Helm Release

NAME   NAMESPACE  REVISION  STATUS    CHART        APP VERSION 
appdb default 2 deployed mysql-8.7.0 8.0.25

Notice that revision of appdb is marked as 2 with status deployed. When you upgraded a chart, Helm creates a new Release. A Release is an instance of a chart running in a Kubernetes cluster. You can think of a release as a particular combination of configuration and version.

When you run the helm install command, Helm creates a release record. These release records are stored as Kubernetes secret.

As you can see, Helm creates a secret record for each release. You can get more information about a release by describing secret as:

Helm History and Rollbacks

You will notice that version 1 is marked superseded and version 2 is marked deployed. The history command also lists the error message in case of a failed deployment.

If you need to roll back to the previous revision, you can do that using helm rollback <revision>.

helm rollback appdb 1 Rollback was a success! Happy Helming!

If you run the helm history command again you'll notice that Helm has created a new release and marked earlier release as superseded.

Dry Run

While installing a release Helm roughly performs these steps.

  1. Load entire chart including dependencies.
  2. Parse the value.
  3. Execute template and generate YAML. In this step Helm can contact API Server.
  4. Parse the YAML into the Kubernetes object.
  5. Send to Kubernetes.

The dry run performs all steps except step 5.

During dry run Helm contacts Kubernetes API Server for validation. You must have a Kubernetes cluster credential to execute a dry run.

If you don’t have credentials for the Kubernetes server, you can use the helm template command to generate template YAML. As Helm does not contact the API server output of the commands --dry-run and template can differ.

Creating chart

Run command helm create product-svc. This creates a chart product-svc under directory product-svc. To customize, you can modify the file values.yaml.

Deployment

## Old replicaCount: 1 
## New replicaCount: 3

Modify the image section to set the value of repository and tag as:

As product-svc exposes port 8080, change templates/deployment.yaml and set containerPort to 8080. Also, product-svc doesn't expose '/' endpoint, we need to remove entries for readinessProbe and livenessProbe.

Ingress

Enable Ingress by setting the field enable to true in values.yaml and remove host entry.

And then from /templates/ingress.yaml remove host entry.

You can validate generated YAML by running the command helm install product product-svc --dry-run.

If you are running a local cluster then you can install the Ingress controller using this guide.

Chart Dependency

dependencies: 
name: mysql
version: ^8.7.0
repository: https://charts.bitnami.com/bitnami

‘^’ in ‘8.7.0’ denotes the caret range of semantic versioning. This means >=8.7.0 < 9.0.0. The range is a preferred way of defining dependency in the Helm chart. The range helps to pull the latest charts for bugs and security fixes.

To update dependency, run command `helm dependency update`.

If you check the charts subdirectory, you will notice that Helm has downloaded mysql-8.7.1.tgz.

Locking chart to a specific version

  1. Helm reads repository metadata to chart version. From metadata and specified range, it finds the best match.
  2. Helm writes resolved information Chart.lock file. This file is used to rebuild the dependencies to an exact version.
  3. Once, specific version is resolved, Helm downloads the dependent charts and puts them in the charts subdirectory.

You can run command helm dependency build to download dependencies. This is useful when you have Chart.lock file but no dependencies charts subdirectory.

Defining values for the dependent chart

mysql: 
auth.database: product_db

To deploy the chart with dependency, you can run helm upgrade or uninstall and install the product chart. You can confirm MySQL deployment by running the command kubectl get pods.

When to use chart dependency?

If you run helm list then you’ll notice Helm lists only the main chart, not the dependent chart.

Another way of installing dependencies is to install each chart separately. In this scenario, you can upgrade each installation of the chart separately. This is the preferred approach if you create and run charts within your organization.

Chart Example

Summary

Further Reading

Originally published at https://techdozo.dev.

--

--

Software Architect @ Schlumberger ``` Cloud | Microservices | Programming | Kubernetes | Architecture | Machine Learning | Java | Python ```

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Pankaj Kumar

Software Architect @ Schlumberger ``` Cloud | Microservices | Programming | Kubernetes | Architecture | Machine Learning | Java | Python ```