Default Helm Template
Tags: devops, helm, kubernetes
Published: 2024-02-03 09:13:02

Helm is my favorite way to deploy to Kubernetes. I got a little sick of making the same changes to the default files that `helm create` creates, so here is my go-to default helm template for simple apps, services, and microservice. 

# TL;Dr 

Find the chart in my template repository [here](https://github.com/chrburmeister/templates/tree/main/helm/app/chart). 

# Introduction 

In general, if you want to create a Helm chart for your app or whatever, `helm create <app name>` is a great place to start. It comes with almost everything you need to make basic deployment, however, if you want to be a little more flexible and explicit, you need to make some changes.

For once, the `Ingress` resource still has a version check for Kubernetes below version `1.18.` or even `1.14.`. If you still run Kubernetes in that version, stop everything and upgrade now! :wink:

Also, the `Deployment` and `Service` need some rework to make changes to the source and target ports in the `values.yaml`. 

In the following chapters, I go over the changes I made. You can follow along and crate a chart locally using `helm create app` and see what needs to be changed. 

# Testing 

I remove the testing folder because I usually do not need it, I to use liveness- and readiness probes because its more accurate and has even more advantages. 

# Helper 

Helm allows you to define helper functions to create values, such as names. If you have a look at the built-in helper it shows you how to define names for the resources you use, create a selection of labels, annotations, and selectors. I made some minor changes to create the name for the resources based on the parameter `appName` in the  `values.yaml`. 

Other resources will be named by that name plus the suffix of the type. So the appName `mail` will create a service called `mail-svc`. Same goes for the HPA - `mail-hpa`. The only exception are deployments, or pretty much anything that creates and manages pods, because their name depends on the name of the managing resource. 

I would urge to expend the list if you add other resources, because it makes referencing them much easier and will reduce later confusion for you (when you come back to this), or your colleagues.

The file is called `_helpers.tpl`.

# Service 

The server needs to be edited to specify all of the parameters you see below: 

```yaml 
apiVersion: v1 
kind: Service 
metadata: 
  name: {{ include "app.serviceName" . }} 
  labels: 
    {{- include "app.labels" . | nindent 4 }} 
spec: 
  type: {{ .Values.service.type }} 
  ports: 
    - port: {{ .Values.service.port }} 
      targetPort: {{ .Values.service.targetPort }} 
      protocol: {{ .Values.service.protocol }} 
      name: {{ .Values.service.name }} 
  selector: 
    {{- include "app.selectorLabels" . | nindent 4 }} 
``` 

This implies we need to change the `values.yaml` to include those information as well: 

```yaml 
service: 
  type: ClusterIP 
  port: 8080 
  targetPort: 80 
  protocol: TCP 
  name: http 
``` 

but also the `deployment.yaml` to include the service changes: 

```yaml 
ports: 
  - name:  {{ .Values.service.name }} 
    containerPort: {{ .Values.service.targetPort }} 
    protocol:  {{ .Values.service.protocol }} 
``` 

Check the files in the repo mentioned above.

# Deployment

The heart of the deployment of an application is the Pod managing entity, which is usually the `deployment` object. Others like `Stateful Sets`, `Daemon Sets`, `Jobs` or `CronJobs` are also possible. The deployment has the name of the value `appName` provided in the values.yaml. In addition to the by default created properties, I have added the following specs:

- Init Containers
- Liveness and Readiness probes are now passed in by the values.yaml and must be set.
- Environment Variables can be passed into deployment in many different ways - either a direct value assignment, or as a secret- or config map key reference. This can be used in combination with a tool like [external-secrets](https://external-secrets.io/latest/).

# HPA 

For the HPA, I only added the new variable of the deployment. 

# Service Account 

Same thing as for the HPA, name change only. 

# PodDisruptionBudget

The `PodDisruptionBudget` ensures the desired number of pods that is available during voluntary disruptions - for instance by scaling down nodes. Involuntary disruptions like an outage can not be considered. When the HPA is enabled, the minimum number of pods will be used, otherwise, the `PodDisruptionBudget.minAvailable` will be used. 

# New Resources

You can add new resources like certificates, keda-scaler, whatever the case might be, I would suggest the following points:

- create a name in the `_helpers.tpl` with an appropriate suffix
- add metadata as shown in all objects of this template
  - do not include the namespace!
- use helm template functions if necessary

# Next 

Please feel free to use the template and make changes as you like, this is my baseline whenever I need to deploy something and it has never let me down.