Getting familiar with Helm
Helm is way of managing pre-configured software installations - which are known as charts in the Helm community.
Helm builds upon Kubernetes, which itself builds upon Docker.
As of March, 2019 Helm is a Cloud Native Computing Foundation (CNCF) incubation project (Kubernetes was the first project to graduate from CNCF incubation, in March 2018).
Having thoroughly investigated Docker and Kubernetes, of course I had heard of Helm.
So it seemed like it was finally time to try it out.
The contents are as follows:
- Prequisites
- Helm Components
- Installing Helm
- Helm Charts
- Development Life Cycle
- Deployment Life Cycle
- Preparation for Rancher
- Versions
- Reference
- To Do
- Docker
- kubectl
- minikube
Minikube requires a Hypervisor.
In order to be able to run locally, we will use minikube
for our Kubernetes environment:
$ kubectl config current-context
minikube
$
[This step requires a started minikube
.]
Helm consists of two components:
helm
tiller
[Following the Kubernetes ("helmsman") metaphor, we have a helm and one or more tillers.]
The client, helm
, is used to manage Helm charts and to manage one or more tillers.
The server, tiller
, runs inside one or more Kubernetes clusters and manages the Helm releases.
Instructions for installing Helm may be found at:
http://docs.helm.sh/using_helm/#installing-helm
In general it is only necessary to install helm
as helm itself will deploy tiller
as needed.
Helm Charts define Kubernetes resources that will be released to Kubernetes Clusters.
The Chart.yaml
file should provide a high-level summary of the chart.
Important values (apart from secrets) should be stored in the values.yaml
file.
Useful runtime information should go in the templates/Notes.txt
file (these notes
will be displayed once the chart is installed).
Chart directories should have roughly the following structure:
package-name/
charts/
templates/
.helmignore
Chart.yaml
OWNERS
LICENSE
README.md
requirements.lock
requirements.yaml
values.yaml
The charts/
folder and the requirements.yaml
and requirements.lock
files may or
may not be needed.
Much like a requirements.txt
file in a Python project, the requirements.yaml
file is used to list project dependencies (if there are any - which there may not be).
Running a helm dep update mychart command will generate a requirements.lock
file (which should be checked into any code repositories along with the requirements.yaml
file).
Any specified chart packages will be fetched and stored in the /charts/
folder. In general
this folder should not be checked into any code repositories, however it may be a site
practice to do so.
In order to be able to search the Bitnami charts, we will add their chart repo.
This should look as follows:
$ helm repo add bitnami https://charts.bitnami.com
"bitnami" has been added to your repositories
$
We can see the Bitnami charts as follows:
$ helm search bitnami
And now our search results will include the Bitnami charts.
Find stable charts here:
http://github.com/helm/charts/tree/master/stable
Or search the Bitnami charts (many of which have been upstreamed to helm/charts):
https://github.com/bitnami/charts
Or at the Helm Hub:
http://hub.helm.sh
Or by using helm search, as follows:
$ helm search redis
NAME CHART VERSION APP VERSION DESCRIPTION
bitnami/redis 6.4.3 4.0.14 Open source, advanced key-value store. It is often referr...
stable/prometheus-redis-exporter 1.0.2 0.28.0 Prometheus exporter for Redis metrics
stable/redis 6.4.2 4.0.14 Open source, advanced key-value store. It is often referr...
stable/redis-ha 3.3.2 5.0.3 Highly available Kubernetes implementation of Redis
stable/sensu 0.2.3 0.28 Sensu monitoring framework backed by the Redis transport
$
[Note that the bitnami/redis
chart seems to be more up-to-date than the stable/redis
chart.]
Helm Chart values can be overridden at helm install
time via the --set option.
Helm can be used to inspect Helm Charts via helm inspect.
[If the Helm chart is not available in the local cache, helm will fetch it and store it in the cache.]
This should look as follows:
$ helm inspect values stable/redis
## 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
<...>
$
Helm can be used to create Helm Charts:
- helm create mychart
- [Optional] helm dep update mychart
- helm lint mychart
- helm test mychart
- helm package mychart
- helm install mychart
- [Optional] helm update mychart
- [Optional] helm delete mychart
- [Optional] helm rollback mychart
- [Optional] helm ls --deleted
- [Optional] helm delete --purge mychart
The create command can be used to create a base set of Chart files.
This should look as follows:
$ helm create test-chart
Creating test-chart
$
The files that helm create
will produce may be viewed at /test-chart/.
The create command can take an optional --starter parameter for specifying a "starter chart".
Starter Charts are regular charts, but in template form - and must be stored in the ~/.helm/starters/
directory.
This step is only needed if there are any project dependencies. These may be specified in a requirements.yaml file.
Running a helm dep update mychart command will then generate a requirements.lock
file (this file should be checked into any code repositories along with the requirements.yaml
file).
Any specified chart packages will be fetched and stored in the /charts/
folder. In general
this folder should not be checked into any code repositories, however it may be a site
practice to do so.
This should look as follows:
$ helm dep update test-chart
Hang tight while we grab the latest from your chart repositories...
...Unable to get an update from the "local" chart repository (http://127.0.0.1:8879/charts):
Get http://127.0.0.1:8879/charts/index.yaml: dial tcp 127.0.0.1:8879: connect: connection refused
...Successfully got an update from the "rancher-stable" chart repository
...Successfully got an update from the "bitnami" chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈Happy Helming!⎈
Saving 1 charts
Downloading redis from repo https://kubernetes-charts.storage.googleapis.com
Deleting outdated charts
$
The lint command can be used to check for possible errors and/or omissions.
For our simple test chart, this looks as follows:
$ helm lint test-chart
==> Linting test-chart
[INFO] Chart.yaml: icon is recommended
1 chart(s) linted, no failures
$
[As our chart has no serious issues, we can "dry run" an install (requires a started minikube
):
$ helm install --dry-run --debug test-chart
[debug] Created tunnel using local port: '42227'
[debug] SERVER: "127.0.0.1:42227"
[debug] Original chart version: ""
[debug] CHART PATH: /home/owner/Documents/Kubernetes/Helm/helm-test/test-chart
NAME: nobby-parrot
REVISION: 1
RELEASED: Mon Mar 25 09:06:57 2019
CHART: test-chart-0.1.0
USER-SUPPLIED VALUES:
<...>
$
[As our chart will install, we can install and test it.]
$ helm install --name mychart --debug test-chart
The install should look as follows:
$ helm install --name mychart --debug test-chart
[debug] Created tunnel using local port: '46214'
[debug] SERVER: "127.0.0.1:46214"
[debug] Original chart version: ""
[debug] CHART PATH: /home/owner/Documents/Kubernetes/Helm/helm-test/test-chart
NAME: mychart
REVISION: 1
RELEASED: Mon Mar 25 09:41:00 2019
CHART: test-chart-0.1.0
<...>
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=test-chart,app.kubernetes.io/instance=mychart" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
$
Once our chart is installed, we can test it:
$ helm test my-chart
This should look as follows:
$ helm test mychart
RUNNING: mychart-test-chart-test-connection
PASSED: mychart-test-chart-test-connection
$
Once we have successfully tested our chart, we can bundle it up for community use.
The package command creates a .tgz
archive of the chart. It can take an optional
--dependency-update parameter to update any dependencies (it is probaably a
best practice to specify this - even if there aren't any dependencies).
This should look as follows:
$ helm package --dependency-update test-chart
Hang tight while we grab the latest from your chart repositories...
...Unable to get an update from the "local" chart repository (http://127.0.0.1:8879/charts):
Get http://127.0.0.1:8879/charts/index.yaml: dial tcp 127.0.0.1:8879: connect: connection refused
...Successfully got an update from the "rancher-stable" chart repository
...Successfully got an update from the "bitnami" chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈Happy Helming!⎈
Saving 1 charts
Downloading redis from repo https://kubernetes-charts.storage.googleapis.com
Deleting outdated charts
Successfully packaged chart and saved it to: /home/owner/Documents/Kubernetes/Helm/helm-test/test-chart-0.1.0.tgz
$
[The actual file location itself will depend upon where your code is located.]
This archive may be examined at test-chart-0.1.0.tgz.
Helm tracks revisions so that updates can be rolled-back.
The ls or list command can take an optional --deleted parameter for viewing uninstalled charts.
The delete [Uninstall] command can take an optional --purge parameter for purging uninstalled charts.
Much like Docker containers, Helm Charts have a life cycle.
Having chosen a chart to deploy, the life cycle is as follows:
Steps 2 and 3 can be repeated as necessary. Step 4 should always be preceded by Step 3.
This is a one-time requirement and serves to create a local Helm cache.
It should look as follows:
$ helm init --history-max 200
Creating /home/owner/.helm
Creating /home/owner/.helm/repository
Creating /home/owner/.helm/repository/cache
Creating /home/owner/.helm/repository/local
Creating /home/owner/.helm/plugins
Creating /home/owner/.helm/starters
Creating /home/owner/.helm/cache/archive
Creating /home/owner/.helm/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /home/owner/.helm.
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!
$
The --history-max
option is specified to prevent the helm history from growing too large.
Note that this propogates tiller
to the Kubernetes Cluster.
We can query for the presence of a running tiller
as follows (requires a started minikube
):
$ kubectl get deployments --namespace kube-system
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
coredns 2 2 2 2 3d
kubernetes-dashboard 1 1 1 1 3d
tiller-deploy 1 1 1 1 3d
$
And there we see a running tiller-deploy.
If tiller
should not be deployed, this may be specified as follows:
$ helm init --client-only
Or:
$ helm init -c
Use helm version to check the local version of Helm.
In order to verify that helm
is installed and working, we will check it's version:
$ helm version
Client: &version.Version{SemVer:"v2.13.0", GitCommit:"79d07943b03aea2b76c12644b4b54733bc5958d6", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.13.0", GitCommit:"79d07943b03aea2b76c12644b4b54733bc5958d6", GitTreeState:"clean"}
$
[This step requires a started minikube
- or else the Server will be unreachable.]
Just to be on the safe side, lets update our list of charts:
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈
$
[This should be carried out from time to time.]
Use helm install to release a Helm Chart.
This should look something like the following (depending upon the chart):
$ helm install stable/redis
NAME: crazy-kudu
LAST DEPLOYED: Thu Mar 21 12:20:56 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
crazy-kudu-redis 3 0s
crazy-kudu-redis-health 3 0s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
crazy-kudu-redis-master-0 0/1 ContainerCreating 0 0s
crazy-kudu-redis-slave-767ccd5df4-bsm9v 0/1 ContainerCreating 0 0s
==> v1/Secret
NAME TYPE DATA AGE
crazy-kudu-redis Opaque 1 0s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
crazy-kudu-redis-master ClusterIP 10.104.133.165 <none> 6379/TCP 0s
crazy-kudu-redis-slave ClusterIP 10.110.217.7 <none> 6379/TCP 0s
==> v1beta1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
crazy-kudu-redis-slave 0/1 1 0 0s
==> v1beta2/StatefulSet
NAME READY AGE
crazy-kudu-redis-master 0/1 0s
NOTES:
** Please be patient while the chart is being deployed **
Redis can be accessed via port 6379 on the following DNS names from within your cluster:
crazy-kudu-redis-master.default.svc.cluster.local for read/write operations
crazy-kudu-redis-slave.default.svc.cluster.local for read-only operations
To get your password run:
export REDIS_PASSWORD=$(kubectl get secret --namespace default crazy-kudu-redis -o jsonpath="{.data.redis-password}" | base64 --decode)
To connect to your Redis server:
1. Run a Redis pod that you can use as a client:
kubectl run --namespace default crazy-kudu-redis-client --rm --tty -i --restart='Never' \
--env REDIS_PASSWORD=$REDIS_PASSWORD \
--image docker.io/bitnami/redis:4.0.14 -- bash
2. Connect using the Redis CLI:
redis-cli -h crazy-kudu-redis-master -a $REDIS_PASSWORD
redis-cli -h crazy-kudu-redis-slave -a $REDIS_PASSWORD
To connect to your database from outside the cluster execute the following commands:
kubectl port-forward --namespace default svc/crazy-kudu-redis 6379:6379 &
redis-cli -h 127.0.0.1 -p 6379 -a $REDIS_PASSWORD
$
Note that the installation is called crazy-kudu
and that our pods are starting.
Also, the installation displays a number of useful comments (these vary depending upon the chart).
[It may take some time before everything is up and running.]
The install command also has --dry-run and --debug options.
The install command also allows for overriding default values via the --set option, such as:
$ helm install testchart --set replicaCount=3
Use helm list or helm ls (the short form) to see what has been released.
This should look as follows:
$ helm ls
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
crazy-kudu 1 Thu Mar 21 12:20:56 2019 DEPLOYED redis-6.4.2 4.0.14 default
$
[Like Docker, Helm will randomly assign a name to the installation if one is not specified.]
The details for this redis chart may be found at:
http://github.com/helm/charts/tree/master/stable/redis
For information purposes, the actual Chart from this repo is included here.
Use helm ls --deleted to see what has been uninstalled:
$ helm ls --deleted
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
crazy-kudu 1 Thu Mar 21 12:20:56 2019 DELETED redis-6.4.2 4.0.14 default
$
Use helm delete to uninstall a Helm Chart.
This should look something like the following (depending upon the chart):
$ helm delete crazy-kudu
release "crazy-kudu" deleted
$
Once the release has been uninstalled, it will show as DELETED
.
[The release may still be rolled-back at this point.]
Use helm delete --purge to completely purge the uninstalled Helm Chart.
This should look as follows:
$ helm delete --purge crazy-kudu
release "crazy-kudu" deleted
$
[The release can no longer be rolled-back.]
Rancher offers a nice GUI for Multi-Cluster Kubernetes Management.
Under the covers Rancher actually uses helm
, but sometimes a dashboard is handy.
To allow for the use of Rancher we will add their stable charts:
$ helm repo add rancher-stable https://releases.rancher.com/server-charts/stable
This should look as follows:
$ helm repo add rancher-stable https://releases.rancher.com/server-charts/stable
"rancher-stable" has been added to your repositories
$
- Docker (Client and Server) - 18.09.3
- helm v2.13.0
- kubectl v1.10.7
- Kubernetes v1.13.4
- minikube v0.35.0
- virtualbox 5.1.38
Installing Helm:
http://docs.helm.sh/using_helm/#installing-helm
Helm Charts:
http://github.com/helm/helm/blob/master/docs/charts.md
[This should be considered definitive.]
Creating Helm Charts:
http://docs.bitnami.com/kubernetes/how-to/create-your-first-helm-chart/
Testing Helm Charts:
http://github.com/helm/helm/blob/master/docs/chart_tests.md
[This should be considered definitive.]
Signing Helm Charts:
http://github.com/helm/helm/blob/master/docs/provenance.md
[This should be considered definitive.]
- Further testing