Helm Quick Start

Concepts

Now, let’s understand the basic concepts of Helm: https://helm.sh/docs/intro/using_helm/

Official Document To install helm in the control node, download the corresponding binary and untar to execution path, or using container and mount necessary k8s credentials.

Package manager analogy:

  • helm (charts)
  • apt (deb)
  • yum (rpm)
  • maven (Jar)
  • npm (node modules)
  • pip (python packages)

Helm v3.2.0

Helm3 does not have Tiller server, see what’s new in Helm 3

Plugins

十六种实用的 Kubernetes Helm Charts工具

Tillerless

For helm2, Tiller server in cluster may not stable and secure, another workaround is run it locally, it talks to remote k8s cluster via kuebctl config.

1
2
## install tillerless plugin
helm plugin install https://github.com/rimusz/helm-tiller

A good practice is to have helm, helm plugin, kubectl and cloud SDK in one container, for example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
FROM python:3.7.7-alpine3.11

USER root

## version number
ENV KUBCTL_VER="1.16.11"
ENV KUBCTL="/bin/kubectl"
ENV HELM_VER="v2.17.0"
ENV HELMFILE_VER="v0.119.0"
ENV HELMDIFF_VER="v3.1.1"
ENV GCLOUD_SDK_VER="318.0.0"

# Install fetch deps
RUN apk add --no-cache \
ca-certificates \
bash \
jq \
git \
curl \
unzip \
tar \
libgit2 \
openssl-dev \
libffi-dev \
gcc \
musl-dev \
python3-dev \
make \
openssh \
tini \
shadow \
su-exec \
vim


RUN curl -L https://storage.googleapis.com/kubernetes-release/release/v${KUBCTL_VER}/bin/linux/amd64/kubectl \
-o $KUBCTL && chmod 0755 $KUBCTL

# install helm && plugins && helmfile
RUN curl -L https://storage.googleapis.com/kubernetes-helm/helm-${HELM_VER}-linux-amd64.tar.gz | tar xz \
&& cp linux-amd64/helm /bin && rm -rf linux-amd64 \
\
&& curl -O -L https://github.com/roboll/helmfile/releases/download/${HELMFILE_VER}/helmfile_linux_amd64 \
&& mv helmfile_linux_amd64 /usr/local/bin/helmfile && chmod 755 /usr/local/bin/helmfile


# Install GCloud SDK
RUN curl -L https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-${GCLOUD_SDK_VER}-linux-x86_64.tar.gz | tar zx \
&& mv google-cloud-sdk /usr/local/ && /usr/local/google-cloud-sdk/install.sh -q \
&& /usr/local/google-cloud-sdk/bin/gcloud components install beta --quiet

ENV PATH="/usr/local/google-cloud-sdk/bin:${PATH}"

RUN helm init -c \
&& helm plugin install https://github.com/chartmuseum/helm-push \
&& helm plugin install https://github.com/databus23/helm-diff --version ${HELMDIFF_VER} \
&& helm plugin install https://github.com/rimusz/helm-tiller

#Test
Run kubectl version --client \
&& helm version --client \
&& helm plugin list \
&& helmfile -v \
&& gcloud version

ENTRYPOINT ["/bin/bash","-c", "tail -f /dev/null"]

Note that HELM_VER < 2.17.0 does not work anymore, the default stable repo is gone, so upgrade to 2.17.0 in environment variable.

Then run it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# go to tillerless folder that with the dockerfile above
docker build -f tillerless.dockerfile -t tillerless:1.0 .

docker run -d --name=xxx \
## something you want to mount
## gcloud config
-v ~/.config:/root/.config \
## kubectl connect
-v ~/.kube:/root/.kube \
-v $(pwd)/../envoy-proxy:/envoy-proxy \
# default workspace path
-w /envoy-proxy \
## tillerless env vars
## by default tiller uses secret
-e HELM_TILLER_STORAGE=configmap \
-e HELM_HOST=127.0.0.1:44134 \
--entrypoint=/bin/bash \
tillerless:1.0 \
-c "tail -f /dev/null"

When first time exec into docker container, run kubectl may not work, try exit out and run kubectl on host and exec log in again.

If switch k8s context, please stop and restart tillerless to adopt change.

1
2
3
4
5
6
7
8
9
10
## export if they are gone
export HELM_TILLER_STORAGE=configmap
export HELM_HOST=127.0.0.1:44134
## by default tiller namespace is kube-system
helm tiller start [tiller namespace]
helm list
helm install..
helm delete..

exit

or

1
2
3
4
5
6
7
8
9
10
## export if they are gone
export HELM_TILLER_STORAGE=configmap
export HELM_HOST=127.0.0.1:44134
## by default tiller namespace is kube-system
helm tiller start-ci [tiller namespace]
helm list
helm install..
helm delete..

helm tiller stop

or

1
helm tiller run <command>

Overview

helm3 does not have default repo, usually we use https://kubernetes-charts.storage.googleapis.com/ as our stable repo. helm2 can skip this as it has default stable repo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
## add stable repo to local repo
## 'stable' is your custom repo name
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
## display local repo list
helm repo list
## remove repo 'stable'
helm repo remove stable

## create charts sacffold
helm create <chart name>

## install charts
## Make sure we get the latest list of charts
helm repo update
helm install stable/mysql --generate-name
helm install <release name> stable/mysql -n <namespace>
helm install <path to unpacked/packed chart>

## show status of your release
helm status <release name>

Whenever you install a chart, a new release is created. So one chart can be installed multiple times into the same cluster. Each can be independently managed and upgraded.

1
2
3
4
5
6
7
## show deployed release
helm ls -n <namespace>

## uninstall
## with --keep-history, you can check the status of release
## or even undelete it
helm uninstall <release name> [--keep-history] -n <namespace>

Install order

Install in certain order, click to see. Or you can split the chart into different part or using init container.

Chart file structure

https://helm.sh/docs/topics/charts/#the-chart-file-structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<chart name>/
Chart.yaml # A YAML file containing information about the chart
LICENSE # OPTIONAL: A plain text file containing the license for the chart
README.md # OPTIONAL: A human-readable README file
values.yaml # The default configuration values for this chart
values.schema.json # OPTIONAL: A JSON Schema for imposing a structure on the values.yaml file, values.yaml 必须遵守这个结构, 否则不会通过
charts/ # other dependent
requirements.yaml # other dependent (for helm2)
crds/ # Custom Resource Definitions
templates/ # A directory of templates that, when combined with values,
# will generate valid Kubernetes manifest files.
xxx.yaml
_xx.tpl # functions
NOTES.txt # show description after run helm install
templates/NOTES.txt # OPTIONAL: A plain text file containing short usage notes

To drop a dependency into your charts/ directory, use the helm pull command

  1. Chart.yaml apiVersion, helm3 is v2, helm2 is v1 appVersion, application verion version, charts version, for example, chart file/structure changed keywords field is used for helm search type, we have application and library chart

Managing dependencies

Package the charts to archive, you can use tar but helm has special command for this purpose:

1
2
3
4
## it will create .tgz suffix
## and append chart verion to archive name
## chart version is from Chart.yaml
helm package <chart_name>

Publishing chart in repos, chartmuseum (like docker hub…), just like private docker registry, you can create a private chartmuseum in your host (有专门的安装包).

1
2
3
4
5
6
7
8
9
## go to the dir that contains chart archive
## this will generate a index.yaml file
helm repo index .
## for security can be signed and verified
## for verification, we need provenance file
helm package --sign
helm verify <chart>
## verify when install
helm install --verify ...

关于dependency,甚至可以只有charts文件夹,里面放所有的chart archive,外面也不需要templates了。 但这样不好管理版本,还是在Chart.yaml中定义依赖比较好。 在定义中还可以指定版本的范围,用的是semver语法: ~1.2.3, ^0.3.4, 1.2-3.4.5

1
2
3
4
5
## will download dependency charts archive to your charts folder
## according to the definition in Chart.yaml
helm dependency update <chart name>
## list dependency, their version, repo and status
helm dependency list <chart name>

You can also use conditions and tags to control which dependency is needed or not, for example, in Chart.yaml file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v2
name: guestbook
appVersion: "2.0"
description: A Helm chart for Guestbook 2.0
version: 1.2.2
type: application
dependencies:
- name: backend
version: ~1.2.2
repository: http://localhost:8080
condition: backend.enabled
tags:
- api
- name: frontend
version: ^1.2.0
repository: http://localhost:8080
- name: database
version: ~1.2.2
repository: http://localhost:8080
condition: database.enabled
tags:
- api

Then in values.yaml file:

1
2
3
4
5
6
7
## can be true or false
backend:
enabled: true
database:
enabled: true
tags:
api: true

Using existing charts

Helm web: https://hub.helm.sh/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
## add and remove repo
helm add repo ...
helm remove repo ...
## list repo's name and URL
helm repo list

## search chart you want,for example
## mysql, nfs, mongodb, prometheus, redis, dashboard, wordpress

## for mysql, you need to specify storage provisioner
## see inspect readme or values
helm search [hub | repo] <keyword>

## inspect the chart, like docker inspect
## readme: usage 去网上看更清晰
## values: default config
## chart: Chart.yaml
helm inspect [all | readme | values | chart] <chart name>

## the same as 'helm inspect values'
helm show values

## download chart without dependencies
## for example, looking into the source code
helm fetch <chart name>

## download dependencies specified in Chart.yaml
## specify char name unpacked
helm dependency update <chart name>

Customizig existing charts

if you want to override child chart’s values.yaml, then in your partent chart values.yaml, 这是常用的,比如你有个dependency 是 mongodb chart, 要改它的默认配置:

1
2
3
4
## 'mongodb' is child chart name
mongodb:
persistence:
size: 100Mi

还可以child chart中的values.yaml override parent的,但很少这样用,用法很tricky.

Chart template guide

https://helm.sh/docs/chart_template_guide/getting_started/ Helm Chart templates are written in the Go template language, with the addition of 50 or so add-on template functions from the Sprig library and a few other specialized functions.

Template and values

https://helm.sh/docs/topics/charts/#templates-and-values

Where are the configuration values from, precdence low to high from top to bottom:

  1. values.yaml (default use)
  2. other-file.yaml: helm install -f <other-file.yaml> ...
  3. command: helm install --set key=val ...

Helm template built-in objects:

  1. Chart.yaml: .Chart.Name (use upper case)
  2. Release data: .Release.Name
  3. K8s data: .Capabilities.KubeVersion
  4. File data: .Files.Get. conf.ini
  5. Template data: .Template.Name

In values.yaml:

  1. use _ instead of -
  2. decimal number wrapped by "", "2.0", integer number no need

使用placeholder 是最基本的操作,let’s see functions and logic.

  1. use functions and pipelines, they are interchangeable https://helm.sh/docs/chart_template_guide/functions_and_pipelines/ commonly used functions and correspinding pipelines
1
2
3
4
5
6
7
8
9
10
11
      function usage         --       pipeline usage
================================================================
default default_value value -- value | default default_value
quote value -- value | quote
upper value -- value | upper
trunc value 20 -- value | trunc 20
trimSuffix "-" value -- value | trimSuffix "-"
b64enc value -- value | b64enc
randAlphaNum 10 -- value | randAlphaNum 10
toYaml value -- value | toYaml
printf format value -- list value | join "-"
  1. modify scope using with to simpify the directives,就不用写一长串引用了
  2. control whitespaces and indent use - to remove whitespace (newline is treated as white space!)
1
2
3
4
5
{{- with ... -}}
...
{{- end}}
## indent 6 space ahead
{{ indent 6 .Value.tcp }}
  1. logical operators and flow control if-else and loop
  2. use variables define the variable
1
2
3
4
{{- $defaultPortNum := .Values.defaultPortNum -}}
{{ $defaultPortNum }}
## . means global scope
{{ $.Release.Name}}
  1. use sub-template define function in _helper.tpl file then use include:
1
{{ include "fun_name" . | indent 4}}

Debug template

Locally rendering template: https://helm.sh/docs/helm/helm_template/ https://helm.sh/docs/chart_template_guide/debugging/

Usually first use the static check then dynamic check.

1
2
3
4
5
6
7
8
9
10
11
## static
## works without k8s cluster
## you can also specify which values yaml file
helm template <chart dir or archive file> [--debug] | less
## for helm2
helm template --tiller-namespace tiller --values ./xxx/values.second.yaml --debug <chart dir or archive file> |less

## dynamic
## real helm install but without commit
## can generate a release name as [release]
helm install [release] <chart> --dry-run --debug 2>&1 | less

Helm commands

https://helm.sh/docs/helm/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
## install with specified release name
helm install [release name] [chart] -n <namespace> --values <path to values yaml>
## check release status
helm list -n <namespace>
## display yaml files
helm get manifest [release] -n <namespace> | less

## check release specification and revision numbers
helm status [release] -n <namespace>

## get all info
## helm2: helm get [release]
helm get all [release] -n <namespace>

## upgrade
helm upgrade [release] [chart] -n <namespace>
## check revision
helm history [release] -n <namespace>
## rollback
## revision number can get from helm history
helm rollback [release] [revision] -n <namespace>

## if abort the helm install, check helm list then uninstall the broken release
## helm2: helm delete --purge [release]
helm uninstall [release] -n <namespace>

PluralSight Supplement

github: https://github.com/phcollignon/helm3

Helm context

Helm use the same configuration as kubectl

1
2
3
4
5
6
## helm env, repos, config, cache info
helm env
## check helm version
helm version --short
## helm uses the same current context
kubectl config view

Helm stores release configuration and history in k8s as secrets. In helm3, it is stored in each corresponding namepsace.

1
2
3
4
## in your working namespace
kubectl get secret -n <ns>
## helm secret is something like:
sh.helm.release.v1.demomysql.v1 helm.sh/release.v1 1 110s

Improved Upgrade Strategy: 3-way Strategic Merge Patches In Helm3, Helm considers the old manifest, its live state, and the new manifest when generating a patch.

In helm2, helm client uses gRPC protocol to access Tiller server (in production secure connection is required, set TLS/SSL), then Tiller (need service account with privilege) will call K8s API to instantiate the charts. In helm3, no Tiller no security issue.

0%