Helm - kamialie/knowledge_corner GitHub Wiki

Kubernetes package manager

Contents

General

Helm has a notion of 3 states: old chart, new chart and live state. 3rd party tools can also apply changes and helm will perform 3-way merge between states and won't touch changes applied by other tools, if they don't conflict with charts.

In Helm 3 configuration of the release is stored in the same namespace as the release. Helm uses default namespace if none specified. Release manifests are stored as secrets.

Helm 2 is using Tiller component (pod) to monitor live state. Helm command line utility communicates with it using gRPC protocol. Tiller manages releases and stores helm charts and installation history in a ConfigMap.

Deployment is called release in Helm.

To completely ignore some files put the patterns in .helmignore in the root directory of the chart.

Structure

Helm's create command sets up basic Charts structure, including templates, helper functions file, and so on:

$ helm create <chart_name>
chart-demo
|--- Chart.yml
|--- README.md
|--- requirements.yaml
|--- values.schema.json
|--- values.yml
|--- charts
     |--- mongodb-1.2.3.tgz
|--- templates
     |--- deployment.yml
     |--- _helpers.yml
     |--- NOTES.txt
     |--- ingress.yml
     |--- service.yml
	 |--- tests
	     |--- test-connection.yaml
  • chart-demo - Chart name
  • Chart.yml - Chart properties (f.e. name, version); dependencies are also listed here (or dependency chars can be added to charts folder as archive files)
  • templates - Kubernetes object definition files; customizable files with placeholders that are replaced by values in values.yml
  • NOTES.txt - descriptions (port numbers of services, etc), howto, other notes for the user of the chart; each time chart is installed, the contents are rendered to the console; subject to templating as well
  • values.schema.json - defines the structure of values in values.yml file
  • tests - pod definitions for testing
  • crds - Kubernetes custom resources definition (installed before other objects and are subjects to limitation)

Chart.yml:

apiVersion: v2
name: chart-demo
description: Learning helm
keywords:
- demo
type: application
appVersion: 1.16.0
version: 0.1.0
dependencies:
  - ...
  • apiVersion - v1 for Helm2, v2 for Helm3
  • keywords are used to find the chart in a repository
  • type can be either application or library; the latter is used when chart itself doesn't produce artifact, but rather serves as helper function
  • appVersion - application version that Helm installs
  • version - chart (files) version

Dependencies

In Helm3 dependencies block can be added to Chart.yaml, but also to requirements.yaml file for backward compatibility with Helm2.

condition key is used to determine if sub-chart should be downloaded. Values (boolean value) are taken from values.yaml file. Multiple conditions can be supplied as comma separated values (only first valid is evaluated). If no condition properties are found, condition is ignored. Conditions override tags.

On update all dependencies are installed (conditions and tags are ignored). They are evaluated only on install command.

Chart.yaml

dependencies:
  - name: backend
    version: ~1.2.2
    repository: http://127.0.0.1:8879/charts
    condition: backend.enabled
    tags:
      - api
  - name: frontend
    version: ^1.2.2
    repository: http://127.0.0.1:8879/charts
  - name: database
    version: 7.8.x
    repository: http://127.0.0.1:8879/charts
    tags:
      - api

values.yaml

backend:
  enabled: true
tags:
  api: true

Semver 2.0

# clone dependencies to local charts dir
$ helm dependency update CHART

# list dependencies
$ helm dependency list CHART

# do not update sub charts (gets versions from Chart.lock file)
$ helm dependency build CHART

Templates

Helm template engine is using Go template engine with some addons.

values.schema.json file (construction rules) is used by Helm each time template, install or upgrade command is run and validates the contents of values.yaml file. Only supported in Helm3.

Value sources:

  • values.yaml
  • other yaml files - helm install -f other.yaml
  • cli variables (overwrite values in yaml files above) - helm install --set foo=bar

Access values:

apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.service.name }}

values.yaml

service:
  type: NodePort
  name: myservice

Other special sources are chart and release. Chart relates to data in Chart.yaml file, while release to data about release. Use appropriate root key, f.e. for chat it would be {{ .Chart.Name }}. Variables are upper case. Capabilities root name gets data from k8s in the same fashion.

Parent chart can override child chart default values by specifying name of the chart as root property name (this is because internally Helm merges all values files into one, nesting children values under their name):

key: value
child_chart_name:
  key_one: value
  key_two: other_value

Global property (in values.yaml) is reserved to be accessible both in parent and in any children charts. Property name and values are lower-case. Passed downward, but not upward.

global:
  id: here_1t_1s
service:
  type: NodePort
  name: myservice

Scopes are used to avoid repeating long paths, when referring to a variable. Scope is identified by with keyword, inner value are referenced relative to scope value. Dashes are used to remove extra new lines, depending where it is places new line before or after is removed.

spec:
  {{ with .Values.service- }}
  type: {{ .type }}
  ports:
  - port: {{ .port }}
    targetPort: 80
  {{ -end }}

By default indentation is preserved as it is in the template, but can be changed using indent value function.

{{ indent 4 .Values.tcp }}

Helm template test:

# static check, works without k8s cluster
$ helm template CHART

# dynamic
$ helm install RELEASE CHART --dry-run --debug
$ helm install RELEASE CHART --dry-run --debug 2>&1 | less

Functions

Functions can also be referred as pipelines, depending on which syntax is used.

Function Pipeline
syntax function value `value
arguments function default_value value `value
default default default_value value `value
quote quote value `value
upper upper value `value
trunc trunc value 63 `value
trimSuffix trimSuffix "-" value `value
b64enc b64enc value `value
randomAlphaNum randomAlphaNum 10 `value
toYaml toYaml value `value

printf function works pretty much the same as in programming languages: takes the output format as the first parameter, and other parameters as values for the format:

{{ printf "%s-%s" .Values.key_one .Values.key_two }}

k8s letters are limited to 64 characters; also names can't end wish -, that's why trimSuffix function might be used.

Sources:

Logical operators are function and take two parameters, except not.

operator function
equal to eq
not equal to ne
greater than gt
lower that lt
or or
and and
not not

Helper function

Also called sub-template reuses code by defining custom function build from already defined ones, even possible to add logic. This is placed in _helpers.tpl (files prefixed with _ are not rendered as k8s object). define sets the name of the sub-template; name is global, thus, should be unique - recommended to prefix the name with the chart name.

{{- define "mychart.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}

Later it can be accessed with include function followed by the name and scope:

{{ include	"mychart.fullname" . }}

Go has similar functionality with template function, but it doesn't produce any output, thus, can't be passed to other functions (f.e. indent).

Flow control

Conditions:

{{ if .Values.service.name }}
{{ .Values.service.name | trimSuffix "-" }}
{{ else }}
{{ .Chart.Name }}
{{ end }}

Loop (values inside are scoped to the outer loop, all references are related to the scope):

values.yaml:

ingress:
  hosts:
  - hostname: frontend.local
    paths:
      - path: "/public"
        service: "frontend"
      - path: "/admin"
        service: "admin"
  - hostname: backend.local
    paths: []

Template:

{{ range .Values.ingress.hosts }}
    - host {{ .hostname | quote }}
      http:
        paths:
        {{ range .paths }}
          - path: {{ .path }}
            backend:
              serviceName: {{ .service }}
              servicePort: http
        {{ end }}
{{ end }}

Conditional inclusion of yaml template can be set by wrapping while file content in an if condition:

{{- if .Values.something -}}
content of yaml file
{{- end }}

Variable

In order to access values outside of with or range scope, define a variable outside the scope. This variable will be accessible from anywhere. Variable definition is preceded by $ sign. Variable is referenced the same way. To access built-in variable, like Release or Chart, also precede them with a $ sign (acts as global reference).

{{ $defaultPortName := .Values.defaultPortName }}
spec:
  {{ with .Values.service }}
  type: {{ .type }}
  ports:
  - port: {{ .port }}
    targetPort: 80
    name: {{ $defaultPortName }}
  {{ end }}

Best practice is to declare a variable inside a range function:

{{ range $currentHost := .Values.ingress.hosts }}

Deployment

Deployment instance is called a release. Multiple releases of the same chart can therefore coexist. Releases are stored as Kubernetes secrets, including redeployments and rollbacks (history events).

# Install a release
$ helm install <release> <chart>
# Local chart
$ helm install <release> <path_to_chart_directory>
# Chart from repo
$ helm install <release> <repo_name>/<chart_name>

# Display release status
$ helm status <release>
# List releases
$ helm list

# Upgrade a release revision
$ helm upgrade <release> <chart>

# Print release history
$ helm history <release>

# Rollback to a release revision
# Get revision number from history command output
$ helm rollback <release> <revision>

# Uninstall a release
$ helm uninstall <release>

Repository

# Add repository
# <name> is used as a reference in other commands
$ helm repo add <name> <url>
# Add official Helm repository
$ helm repo add stable https://charts.helm.sh/stable

# Update local index
# E.g. new Chart was pushed since last "helm repo add ..."
$ helm repo update

# Search Charts within
$ helm search repo <repo>/<chart>

# Get details on various components of the chart
$ helm show readme <repo>/<chart>
$ helm show values <repo>/<chart>

# Get all manifests in the chart with applied default values
$ helm get manifest <release>
# Show all information about the release
# Includes status, manifests and notes file
$ helm get all <release>

Fetch and examine Chart's contents:

$ helm fetch bitnami/apache --untar
$ cd apache

ChartMuseum is an open-source Helm Chart repository server.

# Push local chart to repository
$ curl --data-binary "@<chart>.tgz" http://<server>:<port>/api/charts

Packaging

$ helm package <path_to_chart_directory> \
	--destination <path_to_directory_to_place_tarball>

CLI

Helm uses the same configurations as the kubectl command. To double-check current configuration run kubectl config view.

# Info on caching data location on client side
$ helm env

helm diff plugin shows the preview of what changes would apply with helm upgrade.

# Show difference between existing release and local chart
$ helm diff upgrade <release_name> <path_to_chart>

# Show difference between existing releases
$ helm diff release <release_name_a> <release_name_b>

References

  • labs (from pluralsight course)
⚠️ **GitHub.com Fallback** ⚠️