What Are Helm Charts and How Can They Help with Kubernetes?
Through dangerous tides of cloud, chart the wind as you helm your sailing vessel.
Kubernetes is the industry standard to manage containerized applications. As workloads in the cluster grow in complexity, it will provide great value by managing the applications as reusable packages. Helm is the open source tool Kubernetes uses to enable this.
In this article, we’ll discuss what Helm is and how Helm charts work.
What is Helm?
Helm is the package manager for Kubernetes. Kubernetes manages containers similar to how operating systems manage processes. They provide an environment for the given unit, either pods or processes, to run. This is why after Kubernetes was released, the community soon realized the need for a package manager and Helm was founded.
What is a Helm Chart?
A Helm chart is what describes a package that can be installed on a Kubernetes cluster. It’s a packaging format used by Helm, and is a collection of files structured in a certain format. The files will describe a related set of Kubernetes resources, and if the directory can be accessed by Helm through HTTP, Helm can use it to install and manage the specified resources.
This hosted directory will then be called a Helm repository.
In this article, we’ll use Kubescape to evaluate the security risks of the packages.
Kubescape is an open source tool that can be used for Kubernetes hardening. It does things such as risk analysis, security compliance, RBAC visualizer and image vulnerability scanning.
With its simple CLI and adaptable output format, it can be easily integrated into CI/CD pipelines. It also natively supports various devops tools such as Jenkins, CircleCI, GitHub workflows and Prometheus. This allows developers to place it early in the pipeline and catch any violations before the system is impacted. It also provides a SaaS offering to help you meet security compliance and manage K8s RBAC.
To get Helm charts from the repository:
helm repo add kubescape https://kubescape.github.io/helm-charts/
helm repo update
Helm charts also provide methods for templating. Default configuration values can be stored in a file and then, when the manifests are to be generated, values can be provided by the user or taken from the file. This file is then used to replace placeholders in the chart. Let’s explore a sample chart provided by Helm.
# Create sample chart
helm create sample-chart
# Show directory structure
tree sample-chart
# sample-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
cat sample-chart/values.yaml | head -n 15
The values.yaml file is what contains the default values for the chart. The values can later be overridden by using the --set
argument.
With this, a configurable and reusable set of manifests can be generated by Helm. This ensures reusability of the package across clusters and time.
Investigate Kubescape Helm Charts
Instead of creating a chart from scratch, let’s learn top-down style and investigate a production-ready Helm chart. Fortunately, Helm makes this simple.
# Add and index the repo
helm repo add kubescape https://kubescape.github.io/helm-charts/
helm repo update
# Download the chart
helm pull kubescape/kubescape-cloud-operator --untar
# Explore
tree kubescape-cloud-operator
First take a look at README.md. It talks about how to install and use the chart. This file is optional, but nonetheless one of the most important. It also describes how to configure the chart when installing, and gives an architecture diagram of the application. For example, configure the installation with --set
:
helm upgrade --install kubescape kubescape/kubescape-cloud-operator -n kubescape --create-namespace --set account=<my_account_ID> --set cluster-name=`kubectl config current-context` --set clientID=<generated client id> --set secretKey=<generated secret key>
In Chart.yaml, you store the primary information of the chart. apiVersion
is the chart API version. The latest version for Helm 3 is now v2
while that of Helm 2 is v1
. They are not incremented in lock step. An interesting point here is the appVersion
field is the version of the application that the chart will install, while the version
field is the version of the chart.
Every time you update your chart, the version
should increment but not necessarily the appVersion
. Refer to their official documentation for details on all the fields.
apiVersion: v2
appVersion: v1.8.3
description: Kubescape is an E2E Kubernetes cluster security platform
home: https://www.armosec.io/
maintainers:
- email: ......
name: kubescape-cloud-operator
type: application
version: 1.8.3
Here’s an example for understanding the two different version values. Notice how multiple charts can have the same app version.
helm search repo nginx -l
# NAME CHART VERSION APP VERSION DESCRIPTION
# ingress-nginx/ingress-nginx 4.3.0 1.4.0 Ingress controller for Kubernetes using NGINX a...
# ingress-nginx/ingress-nginx 4.2.5 1.3.1 Ingress controller for Kubernetes using NGINX a...
# ingress-nginx/ingress-nginx 4.2.4 1.3.1 Ingress controller for Kubernetes using NGINX a...
# ingress-nginx/ingress-nginx 4.2.3 1.3.0 Ingress controller for Kubernetes using NGINX a...
Next is the values.yaml file. This file contains all the default values that will be used to configure the chart when installing, if they are not overridden by the user. The values in this file will be referenced by keys in the chart templates. It’s quite useful for not just package maintainers but also users to read this file as it provides information about how to customize the package and optimize it for the user’s needs.
Last but not least is the templates
directory. The files in here are manifests for the resources that should be created to bring up the application. They will contain tags like {{ .Values.ksNamespace }}
, which means it will be replaced with value for ksNamespace
in the values.yaml file, or value in --set ksNamespace=xxxxx
if it’s provided by the user.
Those are the important bits that you need to know when building a Helm chart. And with that, you are good to go. Always refer to the official documentation for more information. Below, I have given a command you can use to install the package we downloaded above.
# Add --dry-run argument to see the generated manifests instead of really installing
helm install test-kubescape ./kubescape-cloud-operator/ --set account=XXXXX --set clusterName=$(kubectl config current-context)
Install Kubescape CLI and Check Security
Over time, as the complexity of your application grows, the chart grows and it gets increasingly difficult to avoid any exploitation. Here, we demonstrate how to use Kubescape to help.
# Install kubescape
curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | /bin/bash
# Output the manifest to a file
helm install test-kubescape ./kubescape-cloud-operator/ --dry-run --set account=XXXXX --set clusterName=$(kubectl config current-context) > kubescape-manifest.yaml
# Scan the file with kubescape. Let it test it's own poison
kubescape scan kubescape-manifest.yaml
A 16.04% final risk score. I would say that’s pretty good. Understand that your cluster security is an on-going work and there’s no silver bullet for it. Here’s another Helm chart for homework.
# Get the manifest
helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx -n ingress-nginx --create-namespace --dry-run > nginx-manifest.yaml
# Scan it
kubescape scan nginx-manifest.yaml
Summary
In this article, we’ve described Helm and Helm charts, and have also given an overview on creating Helm charts. We also learned how to scan our Helm charts to evaluate its security risks using Kubescape.
Hope you enjoyed the read. Please comment if you have any questions.