12.3. Create a chart
In this lab we are going to create our very first Helm chart and deploy it.
Task 12.3.1: Create Chart
First, let’s create our chart. Open your favorite terminal and make sure you’re in the workspace for this lab, e.g. cd ~/<workspace-kubernetes-training>
:
helm create mychart
You will now find a mychart
directory with the newly created chart. It already is a valid and fully functional chart which deploys an nginx instance. Have a look at the generated files and their content. For an explanation of the files, visit the Helm Developer Documentation
. In a later section you’ll find all the information about Helm templates.
The default image freshly created chart deploys is a simple nginx image listening on port 80
.
Since OpenShift doesn’t allow to run containers as root by default, we need to change the default image to an unprivileged one (docker.io/nginxinc/nginx-unprivileged
) and also change the containerPort to 8080
.
Change the image in the mychart/values.yaml
...
image:
repository: docker.io/nginxinc/nginx-unprivileged
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "latest"
...
And then change the containerPort in the mychart/templates/deployment.yaml
...
ports:
- name: http
containerPort: 8080
protocol: TCP
...
Task 12.3.2: Install Release
Before actually deploying our generated chart, we can check the (to be) generated Kubernetes resources with the following command:
helm install --dry-run --debug --namespace <namespace> myfirstrelease ./mychart
Finally, the following command creates a new release and deploys the application:
helm install --namespace <namespace> myfirstrelease ./mychart
With oc get pods --namespace <namespace>
you should see a new Pod:
NAME READY STATUS RESTARTS AGE
myfirstrelease-mychart-6d4956b75-ng8x4 1/1 Running 0 2m21s
You can list the newly created Helm release with the following command:
helm ls --namespace <namespace>
Task 12.3.3: Expose Application
Our freshly deployed nginx is not yet accessible from outside the OpenShift cluster. To expose it, we have to make sure a so called ingress resource will be deployed as well.
Also make sure the application is accessible via TLS.
A look into the file templates/ingress.yaml
reveals that the rendering of the ingress and its values is configurable through values(values.yaml
):
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "mychart.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
Thus, we need to change this value inside our mychart/values.yaml
file. This is also where we enable the TLS part:
Note
Make sure to replace the <namespace>
and <appdomain>
accordingly.
[...]
ingress:
enabled: true
className: ""
# as we learned in previous labs, OpenShift uses Routes instead of Ingresses
# to let OpenShift automatically generate the corresponding Route, we need the following annotation. more information:
# https://docs.openshift.com/container-platform/latest/networking/routes/route-configuration.html#nw-ingress-creating-a-route-via-an-ingress_route-configuration
annotations:
route.openshift.io/termination: "edge"
hosts:
- host: mychart-<namespace>.<appdomain>
paths:
- path: /
pathType: ImplementationSpecific
[...]
Note
Make sure to set the proper value as hostname.<appdomain>
will be provided by the trainer.Apply the change by upgrading our release:
helm upgrade --namespace <namespace> myfirstrelease ./mychart
This will result in something similar to:
Release "myfirstrelease" has been upgraded. Happy Helming!
NAME: myfirstrelease
LAST DEPLOYED: Wed Dec 2 14:44:42 2020
NAMESPACE: <namespace>
STATUS: deployed
REVISION: 2
NOTES:
1. Get the application URL by running these commands:
https://<namespace>.<appdomain>/
Check whether the ingress was successfully deployed by accessing the URL https://mychart-<namespace>.<appdomain>/
Task 12.3.4: Overwrite value using commandline param
An alternative way to set or overwrite values for charts we want to deploy is the --set name=value
parameter. This parameter can be used when installing a chart as well as upgrading.
Update the replica count of your nginx Deployment to 2 using --set name=value
Solution
helm upgrade --namespace <namespace> --set replicaCount=2 myfirstrelease ./mychart
Values that have been set using --set
can be reset by helm upgrade with --reset-values
.
Task 12.3.5: Values
Have a look at the values.yaml
file in your chart and study all the possible configuration params introduced in a freshly created chart.
Task 12.3.6: Remove release
To remove an application, simply remove the Helm release with the following command:
helm uninstall myfirstrelease --namespace <namespace>
Do this with our deployed release. With oc get pods --namespace <namespace>
you should no longer see your application Pod.