Helm & Kustomize
In this lab exercise we will use Helm to create a Chart for our Website project called website and then use Kustomize to customize it.
The website will be an nginx Pod that will serve a static HTML page, which will be modified by the values that we provide. We will be able to change the color and icons of the displayed webpage.
We will use a ConfigMap to store the HTML content of the webpage.
Helm
First we will start by creating a Helm chart.
Create an empty Helm template
Bootstrap a Helm Chart for our website project website
helm create website
Info
A new folder called website will be created in your current working directory. The folder contains all the necessary files to create a Helm Chart. Check out its content.
1. Adjust the Chart.yaml file
The Chart.yaml contains all meta data about your Helm chart. The version of the chart is currently set to 0.1.0. The version is important because it is used to determine if an upgrade should be performed or not.
We will replace the content of the Chart.yaml file with the following content:
apiVersion: v2
name: website
description: A simple static website that can change color and icons by configuration
version: 0.1.0
2. Adjust the values.yaml file
The values.yaml file contains the (default) variables that will be used in the templated Kubernetes yaml files (you can find them in templates).
We can see that a deployment.yaml, ingress.yaml, service.yaml, and serviceaccount.yaml was generated.
Take a look at the parameters and the templates that were generated and then replace content of the values.yaml file with the following:
backgroundColor: red
color: blue
logo: https://helm.sh/img/helm.svg
text: "Deployed by a Helm Chart"
3. Add the Kubernetes templates
In the last step we have viewed the generated Kubernetes templates. We will delete all files in the template folder and add our own templates. We will add the following files:
- Deploment (
templates/deployment.yaml): This file contains the deployment definition. - Config Map (
templates/configmap.yaml): This stores the ConfigMap that stores the HTML content of the website and will be used by the deployment. - Service (
template/service.yaml) This file contains a load-balancer service that exposes the deployment on port 80.
deployment.yaml
# helm-site-chart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: site
spec:
replicas: 1
selector:
matchLabels:
app: site
template:
metadata:
labels:
app: site
spec:
containers:
- name: web
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: site-html
configmap.yaml
# helm-site-chart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: site-html
labels:
app: site
chart: site
managed-by: Helm
data:
index.html: |
<html>
<head>
<title>{{ .Values.title }}</title>
</head>
<body style="background-color: {{ .Values.backgroundColor }}; color: {{ .Values.color }}; text-align: center; font-family: sans-serif;">
<img src="{{ .Values.logo }}" alt="Logo" style="width:150px; margin-top: 50px;" />
<h1>{{ .Values.title }}</h1>
<p>{{ .Values.text }}</p>
</body>
</html>
service.yaml
# helm-site-chart/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: site
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: site
Install the Chart
Congratulations! We have created our first Helm Chart now. It time to install the chart.
Go outside the chart folder and install the chart by
helm install website ./website
If you experience errors then it is most likely due to wrong indentation during copy and pasting. Please check your files for correct indentation. If everything goes well it looks like
NAME: website
LAST DEPLOYED: Wed Apr 23 10:16:22 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
Check your installation by running
helm list
Now, find the resources that were installed by Helm: The deployment, the pod, the ConfigMap and the service.
kubectl get pod
kubectl get deployment
kubectl get service
kubectl get configmap
You can access the website by opening the IP at “EXTERNAL-IP” in your browser. You can copy/paste it from the previous check. If you just want to get the IP directly with kubectl, you could use JsonPath as well:
kubectl get svc site -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
and call it on your browser via http://ip:80
Upgrade the Helm Chart
When updating the values or template files, we can use the helm upgrade command to apply them in the Cluster.
Modification of the default values
Change the text variable in the values.yaml to
text: "Upgraded by Helm"
and run
helm upgrade website ./website
Check what changes were applied to the Kubernetes resources and check your website again.
kubectl get pod
kubectl get deployment
kubectl get service
kubectl get configmap
You will see that the website has not changed yet. This is due to the fact, that we updated the ConfigMap but Kubernetes did not reload the new ConfigMap into the Pod. This is only done at the start of the Pod. Therefore, If you want to see the changes, you have to restart the pod either by deleting it or by scaling the deployment to 0 and back to 1.
Solution
$ kubectl scale deployment/site --replicas=0
$ kubectl scale deployment/site --replicas=1
At next check your helm version history to see what changes were made until now.
helm list
helm history website
Setting values on the CLI
While providing and using the default values from the chart (values.yaml), the main idea of Helm is to change values of a templated application on our demand. In real-world scenarious many parameters can be adjusted to modify the deployed application. It is possible to provide own values files or override default values directly on the command line by using the --set flag.
For example, let’s change the background color of our website to blue.
helm upgrade website ./website --set backgroundColor=blue
Check your Website if it changed the color. Remember what was necessary to see the changes.
Rolling back a release
However the old color was much better, so let’s role back to an older version of our deployment.
helm history website
helm rollback <release-name> <revision-number>
helm rollback website 1
Kustomize
In this section we will use kustomize to archive the same modification as done before. While Helms templating engine is very powerful, it can be overwhelming for simple static and plain configuration changes. We will use Helm to generate the base configuration (rendered yaml files by using the default values of the chart) and then use Kustomize to apply patches on top of it.
Create the Kustomize base
First we need all Kubernetes Yaml files that are already deployed. We will create a new subfolder base in the folder kustomize.
mkdir -p kustomize/base
and extract definitions from the Helm chart into this folder by the using helm template command.
helm template ./website > kustomize/base/all.yaml
check if the file contains all resources. Optionally, you can split them into three files like in the Helm chart template folder. Then add the ‘kustomization.yaml’ with the following content into the base folder.
resources:
- all.yaml
Create a patch
If we like to update or patch a existing resource we basically create a copy of the resource and change it. Kustomize will take care that exactly this resource is updated.
We will call our patch custom and need to create a folder for it in the overlay folder (which needs to be created as well).
mkdir -p kustomize/overlays/custom
Now create a new kustomization.yaml in this folder with the following content:
resources:
- ../../base
patches:
- path: configmap-patch.yaml
target:
kind: ConfigMap
name: site-html
and the actual new config map called configmap-patch.yaml. You can change the title of the page e.g. to your first name.
apiVersion: v1
kind: ConfigMap
metadata:
name: site-html
data:
index.html: |
<html>
<head><title>Alex Website</title></head>
<body style="background-color: #88E788; color: #6A89A7; text-align: center; font-family: sans-serif;">
<img src="https://redhat-scholars.github.io/argocd-tutorial/argocd-tutorial/_images/kustomize_logo.png" alt="Logo" style="width:150px; margin-top: 50px;" />
<h1>Alex Website</h1>
<p>Patched with Kustomize</p>
</body>
</html>
Now apply the kustomization with
kubectl apply -k kustomize/overlays/custom
Don’t forget to restart your pod again to see the changes.
There are different possibilities to check which version of the patch is currently installed, but it is not as elegant as in Helm. E.g you can look at the difference to the base
kubectl diff -k kustomize/base
A limited scenario
Please note that Helm and Kustomize are capable of much more patching and templating options. This was just a basic example to get started.