Helm Dry Run: Guide and Best Practices
This article will take a closer look at Helm dry run concepts, including related Helm commands and how to use Helm dry run to troubleshoot templates.
Kubernetes, the de-facto standard for container orchestration, supports two deployment options: imperative and declarative.
Because they are more conducive to automation, declarative deployments are typically considered better than imperative. A declarative paradigm involves:
- Writing YAML manifest files that describe the desired state of your Kubernetes cluster
- Applying the manifest files
- Letting the Kubernetes controllers work out their magic
The issue with the declarative approach is that YAML manifest files are static. What if you want to deploy the same app in two different environments (for example, “staging” and “production”) with some slight changes (for instance, allocating resources to production)? Having two YAML files is inefficient. A single parameterized YAML file is ideal for this scenario.
Helm is a package manager for Kubernetes that solves this problem. It supports manifest templating and enables parameterization of otherwise static YAML configurations. A set of templated manifest files.
A Helm chart is a package consisting of templated manifest files and metadata that can be deployed into a Kubernetes cluster. A Helm chart takes input variables and uses them to process templated YAML files to produce a manifest that can be sent to the Kubernetes API.
Before deploying a Helm chart into your Kubernetes cluster, it’s
wise to understand how it will behave. Helm dry run — specifically the helm
install --dry-run
command — addresses this use case and enables a preview of
what a Helm chart will do without deploying resources on a cluster. Helm dry
run also streamlines troubleshooting and testing Helm charts.
This article will take a closer look at Helm dry run concepts, including related Helm commands and how to use Helm dry run to troubleshoot templates.
Summary of Key Helm Dry Run Concepts
The table below summarizes the Helm dry run concepts we will explore in this article.
CONCEPT |
DESCRIPTION |
Helm lint |
Performs some static analysis to check a Helm chart for potential bugs, suspicious constructs, and deviations from best practices. |
Helm template |
Generates the output manifest and prints it out. Only checks for YAML syntax and not whether the generated YAML is a valid Kubernetes manifest. |
Helm install --dry-run |
Generates the output manifest and sends it to the Kubernetes API for verification. |
Helm Dry Run and Related Helm Commands
The three Helm commands we will explore in this article are:
helm template
helm lint
helm install --dry-run
The helm template
command
renders the template but does not check the validity of the generated YAML
files beyond a simple YAML syntax check. It will stop generating the output
when it encounters invalid YAML. Use the --debug
flag
to force the helm template
command
to display full output, including invalid YAML.
The helm template
command
has the advantage of not needing a running cluster. Use cases for helm
template
include:
- To test the output of a Helm chart you are developing
- To see how certain values will change the output manifest file
The helm lint
command
runs a basic static analysis that checks a Helm chart for potential bugs,
suspicious constructs, and best practices deviations. This command is only
useful when writing a Helm chart.
The helm install --dry-run
command
requires a running Kubernetes cluster and will test the manifest against that
specific cluster. This is useful because a Helm chart may be compatible with
one cluster but not another. Potential differences across clusters include:
- Kubernetes version
- Custom resources
- Presence of required node types
How to Run “helm template”
Now let’s look at how to run the helm
template
command.
First, let’s create a simple Helm chart:
$ helm create mychart
This will create a simple chart deploying NGINX. Now let’s see
what the helm template
command
shows:
$ helm template mychart mychart
---
# Source: mychart/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: mychart
labels:
helm.sh/chart: mychart-0.1.0
app.kubernetes.io/name: mychart
app.kubernetes.io/instance: mychart
app.kubernetes.io/version: "1.16.0"
app.kubernetes.io/managed-by: Helm
<--- snip --->
Next, let’s introduce an error in one of the YAML manifest files. Edit the “mychart/templates/serviceaccount.yaml” file and add some invalid YAML like this:
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
invalid: yaml
metadata:
name: {{ include "mychart.serviceAccountName" . }}
labels:
<--- snip --->
Let’s see what the helm template
command
does now:
$ helm template mychart mychart
Error: YAML parse error on mychart/templates/serviceaccount.yaml: error converting YAML to JSON: yaml: line 3: mapping values are not allowed in this context
Use --debug flag to render out invalid YAML
As we can see, it failed because the YAML is invalid. We can
view the invalid output with the --debug
flag:
$ helm template mychart mychart --debug
install.go:178: [debug] Original chart version: ""
install.go:195: [debug] CHART PATH: /home/muaddib/Work/Square/tmp/mychart
<--- snip --->
---
# Source: mychart/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
invalid: yaml
metadata:
name: mychart
labels:
helm.sh/chart: mychart-0.1.0
app.kubernetes.io/name: mychart
app.kubernetes.io/instance: mychart
app.kubernetes.io/version: "1.16.0"
app.kubernetes.io/managed-by: Helm
<--- snip --->
Error: YAML parse error on mychart/templates/serviceaccount.yaml: error converting YAML to JSON: yaml: line 3: mapping values are not allowed in this context
helm.go:84: [debug] error converting YAML to JSON: yaml: line 3: mapping values are not allowed in this context
YAML parse error on mychart/templates/serviceaccount.yaml
helm.sh/helm/v3/pkg/releaseutil.(*manifestFile).sort
helm.sh/helm/v3/pkg/releaseutil/manifest_sorter.go:146
<--- snip --->
As you can see, the errors eventually cause Helm to crash. But
at least you should have gotten enough output to troubleshoot your problem.
Using helm template --debug
is
mostly useful when writing a Helm chart and you need to understand whether your
Helm chart is doing what you want.
Lastly, let’s explore the helm
template
command’s main limitation: it generates output even if the
result is not a valid Kubernetes manifest. To demonstrate, edit the previous
file, undo the error we introduced, and modify it like this:
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccountInvalid
metadata:
name: {{ include "mychart.serviceAccountName" . }}
labels:
There is no kind “ServiceAccountInvalid” in Kubernetes, so let’s
see what the helm template
command
will do:
$ helm template mychart mychart
<--- snip --->
---
# Source: mychart/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccountInvalid
metadata:
name: mychart
labels:
helm.sh/chart: mychart-0.1.0
app.kubernetes.io/name: mychart
app.kubernetes.io/instance: mychart
app.kubernetes.io/version: "1.16.0"
app.kubernetes.io/managed-by: Helm
<--- snip --->
As you can see, helm template
happily
generates the output, even though it is not a valid Kubernetes manifest file.
How to Run “helm lint”
The helm lint
command
tests whether a generated manifest can be deployed on a specific Kubernetes
cluster. This helps address issues such as helm
template
generating invalid manifest files and provides static
analysis during chart creation.
The helm lint
command
is run like this:
$ helm lint mychart
==> Linting mychart
[INFO] Chart.yaml: icon is recommended
1 chart(s) linted, 0 chart(s) failed
Helm will flag potential issues and make some recommendations related to best practices.
How to Use Helm Dry Run to Validate Helm Charts
In this tutorial, we’ll use the helm
install --dry-run
command to validate a Helm chart without actually
deploying it on a cluster.
To keep things simple for this tutorial, we’ll run a local minikube cluster, but you can use any compatible cluster deployment to follow along.
$ minikube start
minikube v1.25.2 on Ubuntu 22.04
Using the virtualbox driver based on user configuration
Starting control plane node minikube in cluster minikube
Creating virtualbox VM (CPUs=2, Memory=6000MB, Disk=20000MB) ...
Preparing Kubernetes v1.23.3 on Docker 20.10.12 ...
▪ kubelet.housekeeping-interval=5m
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
Verifying Kubernetes components...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
Enabled addons: default-storageclass, storage-provisioner
Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
If we run the helm install --dry-run
command
with the flawed Helm chart we used in the previous section, here is what
happens:
$ helm install mychart mychart --dry-run
Error: INSTALLATION FAILED: unable to build kubernetes objects from release manifest: unable to recognize "": no matches for kind "ServiceAccountInvalid" in version "v1"
As we can see, the helm install
--dry-run
command connects to the Kubernetes API and sends the
resulting manifest file for verification, which fails as expected. Now let’s
edit the “mychart/templates/serviceaccount.yaml” again and fix the error we
introduced.
After the edits, the command will succeed:
$ helm install mychart mychart --dry-run
NAME: mychart
LAST DEPLOYED: Sat Jul 22 09:57:03 2023
NAMESPACE: default
STATUS: pending-install
REVISION: 1
HOOKS:
---
# Source: mychart/templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
<--- snip --->
Finally, to demonstrate that the command connects to the Kubernetes API, let’s delete the minikube cluster and rerun the command:
$ minikube delete
Deleting "minikube" in virtualbox ...
Removed all traces of the "minikube" cluster.
$ helm install mychart mychart --dry-run
Error: INSTALLATION FAILED: Kubernetes cluster unreachable: Get "http://localhost:8080/version": dial tcp 127.0.0.1:8080: connect: connection refused
Conclusion
The helm template
command
generates a given Helm chart's output manifest and simulates output for input
variables. It checks the YAML syntax of the generated output but does not check
whether the output is a valid Kubernetes manifest. It is useful both when
writing a Helm chart and before deploying a Helm chart into an existing cluster.
We Provide consulting, implementation, and management services on DevOps, DevSecOps, DataOps, Cloud, Automated Ops, Microservices, Infrastructure, and Security
Services offered by us: https://www.zippyops.com/services
Our Products: https://www.zippyops.com/products
Our Solutions: https://www.zippyops.com/solutions
For Demo, videos check out YouTube Playlist: https://www.youtube.com/watch?v=4FYvPooN_Tg&list=PLCJ3JpanNyCfXlHahZhYgJH9-rV6ouPro
If this seems interesting, please email us at [email protected] for a call.
Relevant Blogs:
Recent Comments
No comments
Leave a Comment
We will be happy to hear what you think about this post