Recently I wrote my first Helm chart, well technically copy pasted someone's else and make my modifications from there, but hey finally a good time to write something about Helm.
Helm chart in a nutshell is bunch of Kubernetes resource templates that we can inject with values dynamically. Additionally, Helm also provides many killer features that made it industry standard such as ability to install/update/uninstall, chart repos/registries, JSON validation, tests, dependency management, subchart, and vice versa.
Those sounds daunting, but let's try to write a simple chart for now. We can
start with helm create NAME
command to generate the initial template.
k8s:minikube:default ~/tmp> helm create giovanism-chart
Creating giovanism-chart
k8s:minikube:default ~/tmp> tree
.
└── giovanism-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
4 directories, 10 files
k8s:minikube:default ~/tmp>
Here we have our Chart.yaml
that contains information about the chart,
values.yaml
that holds the default values that will be injected, charts/
dir
and a bunch of things inside templates/
dir. For now we can just delete the
charts/
dir and other files inside templates/
that aren't NOTES.txt
or
_helpers.tpl
so that our chart now looks like this.
.
└── giovanism-chart
├── Chart.yaml
├── templates
│ ├── NOTES.txt
│ └── _helpers.tpl
└── values.yaml
This is pretty bare bone it does the job. Next we want to write our Kubernetes
resource inside the templates/
dir. Let's start with a simple config map and
put it in giovanism-chart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: giovanism-chart-configmap
data:
evil-dev: "Goodbye, World!"
k8s:minikube:default ~/tmp> helm install foo ./giovanism-chart
NAME: foo
LAST DEPLOYED: Mon Oct 25 10:14:02 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=giovanism-chart,app.kubernetes.io/instance=foo" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT
The leftover NOTES.txt
still contains the generated message. We'll remove it
later. Now we can try to run helm get manifest foo
this command to get the
applied manifests.
---
# Source: giovanism-chart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: giovanism-chart-configmap
data:
evil-dev: "Goodbye, World!"
We can also check the config map directly using kubectl get configmaps giovanism-chart-configmap -oyaml
.
apiVersion: v1
data:
evil-dev: Goodbye, World!
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: foo
meta.helm.sh/release-namespace: default
creationTimestamp: "2021-10-25T03:14:02Z"
labels:
app.kubernetes.io/managed-by: Helm
name: giovanism-chart-configmap
namespace: default
resourceVersion: "25683"
uid: fe640659-dd02-4a1e-84dd-902f85c562fb
Templating
We can make changes to our existing template to make it generate different names for each installation using the templating syntax.
--- a/giovanism-chart/templates/configmap.yaml
+++ b/giovanism-chart/templates/configmap.yaml
@@ -1,6 +1,6 @@
apiVersion: v1
kind: ConfigMap
metadata:
- name: giovanism-chart-configmap
+ name: {{ .Release.Name }}-configmap
data:
evil-dev: "Goodbye, World!"
Then we do another install using different name using helm install bar ./giovanism-chart
and see the result with helm get manifest bar
.
---
# Source: giovanism-chart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: bar-configmap
data:
evil-dev: "Goodbye, World!"
This way templating enable us to have unique Kubernetes resource names and have both of our releases side by side.
k8s:minikube:default git:master ! ~/tmp> helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
bar default 1 2021-10-26 03:02:16.77455 +0700 WIB deployed giovanism-chart-0.1.0 1.16.0
foo default 1 2021-10-25 10:14:02.184255 +0700 WIB deployed giovanism-chart-0.1.0 1.16.0
I think that's all. For now I just want to keep up writing regularly rather than focusing too much on the content. I do hope that in the future I can more exciting and sophisticated contents.