Introduction to Helm

In this lab, you will build your own Helm chart. Helm simplifies the deployment and management of applications on Kubernetes by providing a template engine and a robust release management system. You will create a Helm Chart that includes a Deployment, Service, and Ingress object to deploy and expose your application.

To begin, create a dedicated directory for this lab and switch into it:

cd ~

mkdir helm-charts && cd helm-charts

Creating the Initial Scaffolding #

Let’s create scaffolding for the chart with the following command:

helm create random-facts-app

This will create the structure for your chart and some initial templates. For this lab, we are going to remove all of the templates that were created for us and start from scratch. You can remove them with the following command:

rm -rf random-facts-app/templates/*
rm random-facts-app/values.yaml

In the templates directory, create the first template called deployment.yaml.

# random-facts-app/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-deployment
  namespace: {{ .Release.Namespace }}
  labels:
    lab: {{ .Release.Name }}-helm
spec:
  selector:
    matchLabels:
      lab: {{ .Release.Name }}-helm
  template:
    metadata:
      labels:
        lab: {{ .Release.Name }}-helm
    spec:
      containers:
      - name: {{ .Release.Name }}
        image: {{ .Values.image.repository }}:{{ .Values.image.tag | default "latest" }}
        ports:
        - containerPort: {{ .Values.service.port }}
      serviceAccountName: {{ .Release.Name }}-sa

Here is the break down of the template directives used:

  • {{ .Release.Name }}: injects the release name into the template
  • {{ .Release.Namespace }}: injects the namespace name into the template
  • {{ .Values.* }}: injects the values specified in the values.yaml file

Now let’s create a ServiceAccount template called serviceaccount.yaml:

# random-facts-app/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ .Release.Name }}-sa

Next, let’s create a Service template called service.yaml:

# random-facts-app/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}-service
  namespace: {{ .Release.Namespace }}
  labels:
    lab: {{ .Release.Name }}-helm
spec:
  selector:
    lab: {{ .Release.Name }}-helm
  ports:
  - name: http
    port: {{ .Values.service.port }}
    protocol: TCP
    targetPort: {{ .Values.service.targetPort }}
  type: {{ .Values.service.type }}

Next, let’s create a Service template called ingress.yaml:

# random-facts-app/templates/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Release.Name }}-ingress
  namespace: {{ .Release.Namespace }}
  annotations:
    cert-manager.io/cluster-issuer: {{ .Values.ingress.clusterIssuer }}
spec:
  ingressClassName: {{ .Values.ingress.className }}
  rules:
  - host: {{ .Values.ingress.hostName }}
    http:
      paths:
      - path: {{ .Values.ingress.path }}
        pathType: {{ .Values.ingress.pathType }}
        backend:
          service:
            name: {{ .Release.Name }}-service
            port:
              number: {{ .Values.service.port }}
  tls:
    - hosts:
        - {{ .Values.ingress.hostName }}
      secretName: {{ .Release.Name }}-tls

Default Values File #

With our templates in place, we can build out the default values.yaml. The values object provides access to values passed into the chart. Use the following YAML file as a starting point to build a values.yaml file that will live at random-facts-app/values.yaml.

Note: Ensure that you create a value for all .Values specified in the above templates. You do not need to set default values for .Release.Name or .Release.Namespace.

Hint: Leverage your already created objects from the Understanding Kubernetes Networking and Ingress and Understanding Kubernetes Deployments to feed your default values.

# random-facts-app/values.yaml
ingress:
  className: nginx
  hostname: random-facts-app.example.com
  path: '/' 

Once completed, you can test that your Helm chart properly renders with the following command:

helm template --namespace random-facts-app-helm random-facts-app random-facts-app/

Sift through the Kubernetes manifests that are generated and validate that all fields are filled out. You can then deploy your app via your Helm chart with the following command:

helm install --create-namespace \
--namespace random-facts-app-helm \
random-facts-app random-facts-app/

You can now view your Helm install with the following command:

helm status random-facts-app --namespace random-facts-app-helm

Overriding Your Default Values #

In the previous exercise, you defined a default values.yaml in your Helm chart. This provides a convenient way to set defaults for your Helm chart but in most cases, consumers of your Helm chart will need to override these defaults.

Ensure you are at the root of your helm-charts directory and create a new values.yaml beside your Helm chart. In your new values.yaml, override the Ingress hostname to your appropriate domain name (ie. random-facts-app-helm.<YOUR_STUDENT_ID>.<RANDOM_ID>.workshops.acceleratorlabs.ca).

Once done, you can first uninstall your previous Helm deployment with the following command:

helm uninstall random-facts-app --namespace random-facts-app-helm

You can then redeploy your application with the override values:

helm install --create-namespace \
--namespace random-facts-app-helm \
random-facts-app random-facts-app/ \
--values values.yaml

Validate your Helm Chart and deployment with an instructor before proceeding to the next lab.