Helm: Kubernetes package manager — an overview, getting started
Tags: kubernetes, tutorial, devops, todayilearned
Published: 2020-05-05 10:48:40

---
title: Helm: Kubernetes package manager — an overview, getting started
published: true
date: 2020-05-03 10:25:35 UTC
tags: kubernetes,tutorial,devops,todayilearned
canonical_url: https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/
---

### Helm: Kubernetes package manager — an overview, getting started

![](https://cdn-images-1.medium.com/max/128/0*d9LnomRPy1hdilAc.png)

The [official documentation](https://helm.sh/) calls Helm as a “_The package manager for Kubernetes_”, but in fact, Helm is something bigger than just a package manager — it’s more an application controlling tool for their installation, managing, upgrading, configuration, etc.

In this post, we will take an overview of Helm in general, its Charts, templates, variables, and repositories.

The post is really more like an intro to the Help and doesn’t cover some aspects like release versioning, dependencies, etc.

In contrast to the Kubernetes itself — Helm has really good [documentation](https://helm.sh/docs/intro/).

**Content**

- [Helm architecture](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Helm_architecture)
- [Helm concepts](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Helm_concepts)
- [Helm components](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Helm_components)
- [Helm Charts](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Helm_Charts)
- [Files structure](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Files_structure)
- [Preparing the environment](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Preparing_the_environment)
- [Minikube — a Kubernetes cluster](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Minikube_%E2%80%93_a_Kubernetes_cluster)
- [Installing Helm](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Installing_Helm)
- [Creating a Helm Chart](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Creating_a_Helm_Chart)
- [Adding a template](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Adding_a_template)
- [chart linter](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#chart_linter)
- [chart install](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#chart_install)
- [chart uninstall](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#chart_uninstall)
- [Template variables](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Template_variables)
- [chart upgrade](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#chart_upgrade)
- [helm package](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#helm_package)
- [Helm repositories](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Helm_repositories)
- [Running local Helm repo](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/#Running_local_Helm_repo)

#### Helm architecture

Helm operates with packages to run applications in Kubernetes, and in terms of Helm they are called **chart**, and helm allows to:

- create new charts
- pack charts into archives (tgz)
- work with shared charts using their repositories
- install and uninstall charts in a Kubernetes cluster
- manage charts releases in a cluster

#### Helm concepts

The main three concepts are:

1. _chart_: information necessary to run an application in a Kubernetes cluster
2. _config_: information about necessary configuration options to be used by such a chart to create an application instance and manage its releases
3. _release_: работающий инстанс _chart_-а, связанный с определённым _config-_ом

#### Helm components

Helm can be divided into two main part — the client itself, and Helm libraries

- _Helm client_: is a command-line tool (Helm is written in Go), and is responsible for chart creation, working with repositories, releases management, etc
- _Helm library_: is logic part of Helm responsible for work with Kubernetes API to manage charts, their release, installation to a cluster, etc

#### Helm Charts

So, _chart _— is a collection of files, describing some Kubernetes resources which can be used to create a single-pod application — or a whole composite web-service, including a web-server, a frontend ap and backend applications, caching services, etc.

#### Files structure

Charts are organized as a directories and files tree, where the top-directory name is a chart-name.

For example:

```
$ tree example-chart/
example-chart/
| — Chart.yaml
| — charts
| — templates
| | — NOTES.txt
| | — \_helpers.tpl
| | — deployment.yaml
| | — hpa.yaml
| | — ingress.yaml
| | — service.yaml
| | — serviceaccount.yaml
| ` — tests
| ` — test-connection.yaml
` — values.yaml
```

Here:

- example-chart: top-catalog, a chart name
- Chart.yaml: a chart's metadata describing the chart's purpose, its versions, dependencies, etc
- charts: a chart can contain multiply child-charts or _subcharts_ - they'll be stored here
- templates: contains template files to be applied for a Kubernetes cluster using [Go templating](https://golang.org/pkg/text/template/)
- NOTES.txt - help-text to be displayed for users
- deployment.yaml - an example Kubernetes Deployment manifest
- service.yaml - an example Kubernetes Service manifest
- values.yaml - contains default values for templates

Well, enough for theory — let’s go to practice!

#### Preparing the environment

In this will use Minikube, kubectl, and Helm v3:

- minikube v1.9
- Kubernetes v1.18
- kubectl v1.18.2
- helm-3.2.0

#### Minikube — a Kubernetes cluster

[Install the](https://rtfm.co.ua/kubernetes-zapusk-minikube-na-arch-linux/)[minikube](https://rtfm.co.ua/kubernetes-zapusk-minikube-na-arch-linux/):

```
$ sudo pacman -S minikube
```

Create a cluster:

```
$ minikube start
😄 minikube v1.9.2 on Arch rolling
…
🌟 Enabling addons: default-storageclass, storage-provisioner
🏄 Done! kubectl is now configured to use “minikube”
```

Check:

```
$ kubectl cluster-info
Kubernetes master is running at [https://192.168.99.100:8443](https://192.168.99.100:8443)
KubeDNS is running at [https://192.168.99.100:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy](https://192.168.99.100:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy)
```

Its nodes:

```
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready master 4m16s v1.18.0
```

#### Installing Helm

Arch Linux — from a repository:

```
$ sudo pacman -S helm
```

macOS — Homebrew:

```
$ brew install helm
```

Debian, etc — with Snap:

```
$ sudo apt install snapd
$ sudo snap install helm — classic
```

And really good HELP with helm help:

![](https://cdn-images-1.medium.com/max/1005/0*wER0QMkpk7zYTTbh.png)

#### Creating a Helm Chart

Now, let’s create own chart with our template and try to deploy it into the Kubernetes cluster.

Create a new chart:

```
$ helm create example-chart
Creating example-chart
```

We already saw its content:

```
$ tree example-chart/
example-chart/
| — Chart.yaml
| — charts
| — templates
| | — NOTES.txt
| | — \_helpers.tpl
| | — deployment.yaml
| | — hpa.yaml
| | — ingress.yaml
| | — service.yaml
| | — serviceaccount.yaml
| ` — tests
| ` — test-connection.yaml
` — values.yaml
3 directories, 10 files
```

![](https://cdn-images-1.medium.com/max/261/0*EV1TcW15KxwX45Q8.png)

Let’s inspect its Deployment file:

```
$ cat example-chart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include “example-chart.fullname” . }}
labels:
{{- include “example-chart.labels” . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
…
```

And Values:

```
$ cat example-chart/values.yaml
Default values for example-chart.
This is a YAML-formatted file.
Declare variables to be passed into your templates.
replicaCount: 1
…
```

Must be obvious enough — for the replicas: `{{ .Values.replicaCount }}` in the templates/deployment.yaml will be used the replicaCount: 1 value from the values.yaml.

But will not use those files — let’s create own chart.

Remove them:

```
$ rm -rf example-chart/templates/\*
```

And now add our ConfigMap.

#### Adding a template

Create a new file example-chart/templates/configmap.yaml, and here, for example, content for an index.html file:

```
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-configmap
data:
  index.html: "Hello, World
```

#### chart linter

Before installing a chart it’s good to check its syntax — use the helm lint for this:

```
$ helm lint example-chart/
==> Linting example-chart/
[INFO] Chart.yaml: icon is recommended
1 chart(s) linted, 0 chart(s) failed
```

#### chart install

Check one more time which cluster is configured in your kubectl:

```
$ kubectl config current-context
minikube
```

To install a chart use the helm install passing a release name as a first argument, then options, and a path to the chart's files.

But again, before running real actions it will be good to make a test-run with --dry-run and add --debug to see more details:

```
$ helm install example-chart — dry-run — debug example-chart/
install.go:159: [debug] Original chart version: “”
install.go:176: [debug] CHART PATH: /home/setevoy/Work/RTFM/example-chart
NAME: example-chart
LAST DEPLOYED: Sun May 3 13:17:07 2020
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
affinity: {}
autoscaling:
enabled: false
maxReplicas: 100
minReplicas: 1
targetCPUUtilizationPercentage: 80
fullnameOverride: “”
image:
pullPolicy: IfNotPresent
repository: nginx
tag: “”
…
 — -
Source: example-chart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configmap
data:
index.html: “Hello, World”
```

Okay — no errors, install it now:

```
$ helm install example-chart example-chart/
NAME: example-chart
LAST DEPLOYED: Sun May 3 13:20:52 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
```

Check its status:

```
$ helm get manifest example-chart
 — -
Source: example-chart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configmap
data:
index.html: “Hello, World”
```

And check with the kubectl:

```
$ kubectl describe cm nginx-configmap
Name: nginx-configmap
Namespace: default
Labels: app.kubernetes.io/managed-by=Helm
Annotations: meta.helm.sh/release-name: example-chart
meta.helm.sh/release-namespace: default
Data
====
index.html:
 — — 
Hello, World
```

#### chart uninstall

In the same way, you can delete a chart — use helm uninstall and a release name:

```
$ helm uninstall example-chart
release “example-chart” uninstalled
```

#### Template variables

Okay — everything seems to be working, but we have static data in our ConfgiMap with hardcoded values.

Let’s change it and apply the template engine.

For helm, you can use a set of pre-defined variables like Release.Name, see the full list in the [documentation](https://helm.sh/docs/topics/charts/).

Редактируем шаблон нашего ConfigMap:

```
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  index.html: "Hello, World"
```

Next, add own variables — remove the values.yaml:

```
$ rm example-chart/values.yaml
```

And create it over but with the only one line — user: "Username":

```
user: "Username"
```

Now, you can use it in the template via .Values.user:

```
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  index.html: "Hello, {{ .Values.user }}"
```

The .Values told to Helm to use the values,yaml to take the _user_ variables' value.

Apply:

```
$ helm install example-chart example-chart/
NAME: example-chart
LAST DEPLOYED: Sun May 3 13:35:49 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
Check:
kubectl get cm
NAME DATA AGE
example-chart-configmap 1 31s
```

Content:

```
$ kubectl describe cm example-chart-configmap
Name: example-chart-configmap
Namespace: default
Labels: app.kubernetes.io/managed-by=Helm
Annotations: meta.helm.sh/release-name: example-chart
meta.helm.sh/release-namespace: default
Data
====
index.html:
 — — 
Hello, Username
```

#### chart upgrade

Okay, but what if we want to change the _Username_ string?

You can delete the whole release and redeploy it with changed value in the values.yaml, or specify it directly with the --set option:

```
$ helm uninstall example-chart
release “example-chart” uninstalled
helm install example-chart example-chart/ — set user=NewUser
```

Check:

```
$ kubectl describe cm example-chart-configmap
…
Data
====
index.html:
 — — 
Hello, NewUser
```

Another way is to use the helm upgrade with the release name and new value:

```
$ helm upgrade example-chart example-chart/ — set user=AnotherOneUser
Release “example-chart” has been upgraded. Happy Helming!
…
```

The result is:

```
$ kubectl describe cm example-chart-configmap
…
Data
====
index.html:
 — — 
Hello, AnotherOneUser
```

#### helm package

To be able to share our chart with colleagues we can pack it to a tgz-file.

Use the helm package, which will create a new file named _chart-name-chart-verstion.tgz_.

The version helm will get from the chart's metadata:

```
$ cat example-chart/Chart.yaml | grep version:
version: 0.1.0
```

Pack it:

```
$ helm package example-chart/
Successfully packaged chart and saved it to: /home/setevoy/Work/RTFM/example-chart-0.1.0.tgz
```

Check the archive’s content:

```
$ tar tf example-chart-0.1.0.tgz
example-chart/Chart.yaml
example-chart/values.yaml
example-chart/templates/configmap.yaml
example-chart/.helmignore
```

#### Helm repositories

To share our packed charts the Helm repositories are used.

Earlier, you could use the helm serve to create one, but it was removed in Helm v3.

Now to work with repositories use the helm repo.

By default you’ll have already added repo from Google:

```
$ helm repo list
NAME URL
stable [https://kubernetes-charts.storage.googleapis.com/](https://kubernetes-charts.storage.googleapis.com/)
```

#### Running local Helm repo

To create own repository — it;’s enough to execute helm package for a chart, then generate the index.yaml file in a directory used to store the chart's archive.

As a backend-storage you can use almost anything — starting with Github Pages, and to AWS S3, see [The Chart Repository Guide](https://helm.sh/docs/topics/chart_repository/).

Here is an example of how to run a local Helm repository.

Create a directory, move your archived chart into it:

```
$ mkdir helm-local-repo
$ mv example-chart-0.1.0.tgz helm-local-repo/
```

Initialize the repository:

```
$ helm repo index helm-local-repo/
```

Check its content:

```
$ tree helm-local-repo/
helm-local-repo/
| — example-chart-0.1.0.tgz
` — index.yaml
```

To get access to it — run a web-server, for example, a common NGINX:

```
$ sudo docker run -ti -v $(pwd)/helm-local-repo/:/usr/share/nginx/html -p 80:80 nginx
```

Check connection:

```
$ curl localhost/index.yaml
apiVersion: v1
entries:
example-chart:
- apiVersion: v2
appVersion: 1.16.0
created: “2020–05–03T14:04:44.896115358+03:00”
description: A Helm chart for Kubernetes
digest: afa314247a03c4c85f339bda665659f3ab13a5e8656336e14ed37ed7f31b5352
name: example-chart
type: application
urls:
- example-chart-0.1.0.tgz
version: 0.1.0
generated: “2020–05–03T14:04:44.895678349+03:00”
```

Add this repository to your local Helm:

```
$ helm repo add example-chart [http://localhost](http://localhost)
“example-chart” has been added to your repositories
```

Check:

```
$ helm repo list
NAME URL
stable [https://kubernetes-charts.storage.googleapis.com/](https://kubernetes-charts.storage.googleapis.com/)
example-chart [http://localhost](http://localhost)
```

Try to search for a chart:

```
$ helm search repo example
NAME CHART VERSION APP VERSION DESCRIPTION
example-chart/example-chart 0.1.0 1.16.0 A Helm chart for Kubernetes
```

Install it:

```
$ helm install example-chart-from-repo example-chart/example-chart
NAME: example-chart-from-repo
LAST DEPLOYED: Sun May 3 14:15:51 2020
NAMESPACE: default
STATUS: deployed
```

Check in the Kubernetes cluster:

```
$ kubectl get cm
NAME DATA AGE
example-chart-configmap 1 34m
example-chart-from-repo-configmap 1 22s
```

That’s all in general.

_Originally published at_ [_RTFM: Linux, DevOps, and system administration_](https://rtfm.co.ua/en/helm-kubernetes-package-manager-an-overview-getting-started/)_._

* * *