Getting Started with Helm: Templates and SLOs

August 03, 2020
Written by
Ashley Carroll
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by
Diane Phan
Twilion

Getting Started with Helm: Templates and SLOs

As many companies in the tech industry shift towards smaller, more independent microservices, tools like Kubernetes, Docker, and Helm are becoming essential in facilitating the development and deployment of these microservices.

While Kubernetes is used to manage available resources and orchestrate deployments, Helm is a tool that allows developers to coordinate the information sent to Kubernetes clusters. Helm runs on top of Kubernetes and outlines how an application will be structured.

Let’s take a closer look at Helm and its template files. You’ll want to install Helm first if you’d like to follow along and test Helm templating locally. If you have Homebrew, you can run the command brew install helm in your terminal. Otherwise, follow the Helm Installation tutorial.

Understanding Helm Charts

In general, Helm operates in a chart format. A chart is a collection of files in a directory that relate to some set of Kubernetes resources. When you set up a chart for your microservice, you should see this basic structure of files and directories:

name-of-microservice/
  Chart.yaml
  charts/
  values.yaml
  templates/

The Chart.yaml file contains information about the chart and the charts directory contains any chart dependencies. The values.yaml file sets up the default configuration values. The templates directory contains templates that generate Kubernetes manifest files when combined with values.

NOTE: As Helm evaluates a chart, the files inside the templates directory will be processed in a template rendering engine before being sent to Kubernetes.

To set up a chart locally, run the following command in your terminal:

helm create name-of-microservice

Let’s dive right into some example code to better understand how these files relate.

man typing on his keyboard with focus

Understanding Helm Templates

Below is an example of a .tpl file, also known as a template file. The apiVersion field specifies the Kubernetes API version of the object. The kind field describes what type of object you’d like to create. The values under metadata serve to provide annotations and labels used by Kubernetes to identify the resource.

apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}
  namespace: team-name
  labels:
    app: {{ .Values.appName }}
    release: {{ .Release.Name }}
spec:
   {{- /* more code here! - this is a comment */ -}}

Once you have these descriptive fields set, the remaining template code outlines what you want the application to do. Check out the next section to learn more about real use cases for Helm templates.

One thing that can be confusing about templates is their bracket notation, known as template directives. For example, {{ .Release.Name }} is a template directive. Helm templates use this notation to access objects or values that can be passed into templates.

The Release and Values objects are built-in for Helm; however, the Values object is associated with the values.yaml file. In other words, whatever variables you fill your values.yaml file with can be referenced in template files. Here is a simplified example of a values.yaml file:

appName: name-of-microservice
prometheusLabel: name-of-label
slo:
  latency:
    percentage: 98
  availability:
    percentage: 99

From a template file, you can call {{ .Values.appName }} to render the name-of-microservice value in the template. The indentation in any kind of value file is important as it indicates how values are nested. If you wanted to access the value 98 in your template file, you would call {{ .Values.slo.latency.percentage }}. While this phrase is longer than just typing the number 98, it allows you to avoid hardcoding, which is especially useful if a value repeats itself in a template.

If you’ve been following along and editing the values.yaml file, you can run the following command to build your templates locally.

helm template .

Using Helm Templates to Guarantee SLOs

In addition to the aforementioned template and yaml files needed to get Helm running, templates can also be used for other purposes.

To illustrate a real life application, consider a database in which you need to retrieve and insert data. You’d like to measure the latency, or response time, of the database so that you can determine its performance as it relates to your customers’ satisfaction. This is where the idea of using templates to implement SLOs comes into play.

SLOs Explained

Service Level Objectives (SLOs) are a component of Site Reliability Engineering which set benchmarks for quantitative measurements of a service. In other words, after assessing what your team can achieve, what your service can provide, and analyzing the data available, objectives are formed to keep teams accountable and mindful of customer’s needs.

Oftentimes, you might see conversations around SLOs come up in a DevOps context. Using the example of database latency, let’s say one of your SLOs is to ensure that “X%” of requests take less than 1 second. To make sure you are in compliance with your SLO, you can use templates to set up alerts to notify when this threshold is not met.

Configuring Alerts with Helm Templates

Throughout my internship at Twilio this summer, I was able to produce alerts for the above scenario. I simplified the code and redacted some of the team-sensitive material for this article, but you can see how I achieved using Helm Templates to configure alerts below.

I used the open-source systems monitoring and alerting toolkit, known as Prometheus, to query on existing metrics and coordinate alerts. You can see this defined in line 2, kind: PrometheusRule.

Instances in which “X%” of requests did not take less than 1 second would trigger the critical alert below, and be sent to our team’s incident response platform. This way, the team was more equipped to monitor our services’ performance.

apiVersion: v1
kind: PrometheusRule
metadata:
  labels:
    prometheus: {{ .Values.prometheusLabel }}
    role: alert-rules
  name: {{ .Release.Name }}-slo-alerts
  namespace: team-name
spec:
  groups:
  - name: {{ .Release.Name }}-slo-alerts
    rules:
    - alert: {{ .Release.Name }}-perc{{ .Values.slo.latency.percentage }}-latency-slo-critical
      annotations:
        description: "Microservice Latency SLO - Critical Condition"
      expr:  {{- /* INSERT QUERY HERE ex. (sum(rate(metricA_totalSeconds)) / sum(rate(metricA_totalCount))) > 0.99 */ -}}
            {{- /* remember you can pull in values from values.yaml to avoid hardcoding !! */ -}}
      for: 0m
      labels:
        app: microservice
        namespace: team-name
        severity: critical

Using helm templates to set up SLO alerts can help you identify if an issue needs to be declared as an outage, so you can focus on putting out those fires when the time comes.

man angrily smashes the fire alarm at school

Wrapping Up

Congrats on getting started with Helm! Hopefully by looking at Helm templates and SLOs, you’ve gained some insight into why Helm is such a helpful addition to Kubernetes. While this article has overviewed some of the basics of Helm and one real life application, there are many more ways in which Helm continues to shape modern development practices.

To learn more about how to set up Kubernetes with Helm, check out these resources!

Ashley Carroll is a Software Engineer intern on the SendGrid Email Infrastructure Statistics team. She is a rising senior at the University of Michigan studying Computer Science and Spanish. You can learn more about the author or contact her at acarroll [at] twilio.com.