Kubernetes, the popular container orchestration system, is used extensively in DevOps. However, it can become very complex: you have to handle all of the objects (ConfigMaps, pods, etc.), and you also have to manage your releases. Both can be accomplished with Kubernetes Helm, the Kubernetes packaging solution.
This article discusses Helm packages (aka Helm charts), how they are created, and what you should be aware of when you create them for maximum reusability, code quality, and efficient deployments.
In a nutshell: How does Kubernetes work?
Kubernetes is an open-source container orchestration system. The containers that make up an application are grouped into logical units. To set up a single application, you have to create multiple independent resources – such as pods, services and deployments. Each requires you to write a YAML manifest file.
Helm: the Kubernetes Package Manager
Helm is a Kubernetes package manager designed to easily package, configure, and deploy applications and services onto Kubernetes clusters — it’s the apt/yum/homebrew for Kubernetes. It contains the resource definitions necessary to run an application, tool, or service inside of a Kubernetes cluster.
What is a Helm chart?
Charts are packages of Kubernetes resources. A Helm chart is basically a collection of files inside a directory. The directory name is the name of the chart (without the versioning information). Helm charts consist of a self-descriptor file – yaml file – and one or more Kubernetes manifest files called templates. The YAML file describes the default configuration data for the templates in a structured format. Helm Chart templates are written in the Go template language.
All template files are stored in a chart’s templates/ folder. When Helm renders the charts, it will pass every file in that directory through the template engine.
The values for the templates can be supplied in one of two ways:
Chart developers can supply a file called values.yaml inside of a chart. This file may contain default values.
Chart users can supply a YAML file that contains values. This can be provided in the command line with the helm install-command.
When a user supplies custom values, these values will override the values in the chart’s values.yaml file.
Here is the basic directory structure of a Helm chart:
package-name/ charts/ templates/ Chart.yaml LICENSE README.md requirements.yaml values.yaml
Helm charts are very useful when deploying your Kubernetes application. If you can’t find an existing chart for the application that you are deploying in the Helm catalog, you may want to create your own.
How do you create a Helm chart?
You can create your first Helm chart very easily with the Helm create command:
$ helm create mychart Creating mychart mychart
This will create a folder with the files and directories seen above, which gives you a base for developing your charts further.
As we noted earlier, the templates are the manifests of the Helm package, with configuration data that is either derived by default from the YAML file or customized by the author.
Best practices when creating Helm Charts:
Let’s review some of the key tips that you should be aware of when creating your Helm templates in order to ensure maximum reusability, code quality, and efficient deployments.
Respect the general conventions
Always be aware of the Helm rules to be applied when working with Helm charts. The chart name should be lower case letters and numbers. The words can be separated with dashes (-); for example:
wordpress docker aws-test1
When the directory contains a chart, the directory name must be the same as the chart name.
When versioning is applied, the version numbers follow the SemVer format.
YAML files should be indented using two spaces.
Helm refers to the project as a whole and the client-side command. The term “chart” should not be capitalized (with the exception of Chart.yaml), because the filename is case-sensitive.
Take care of the values
The name of a variable should begin with a lowercase letter, and words should be separated using camel case:
pea: true peaSoup: true
Due to YAML’s flexible format, values can be deeply nested or flattened. Flat is better for development because of its simplicity. On the other hand, you have to perform an existence check for every layer of nesting, and you should do a check for every nested value at every level. This is not recommended with flattening, because it will make the template less readable.
You should quote all strings for type conversion; that way, a code reader won’t be confused about whether or not it’s a string.
Every property defined in values.yaml should be documented. The documentation string should start with the property’s name and a one-sentence description.
Mind the template structure
The templates/ directory should be structured as follows:
- Template files should have the extension .yaml if they produce YAML output. The extension .tpl can be used for template files that produce no formatted content.
- Template file names should use dash notation, not camel case.
- Each resource definition should be in its own template file.
- Template file names should have the resource type in the name: test-pod.yaml, test2-svc.yaml
For a chart, you should use version ranges instead of referring to an exact version:
Version: ~ 1.2.3
If there are optional dependencies, you should add conditions or tags. The same tags can be applied to subcharts that contain features (optional).
Using labels and annotations
The metadata of an item should be used as a label when it is:
- used by Kubernetes to identify this resource.
- useful to expose to operators for the purpose of querying the system.
If an item of metadata is not used for querying, it should be set as an annotation. Helm hooks are always annotations.
Working with CRD
When working with Custom Resource Definitions (CRD), keep in mind that the CRD is declared for your chart (see the YAML file called CustomResourceDefinition).
If your CRD defines test.example.com/v2, every resource with apiVersion: test.example.com/v2 is a resource using the CRD.
Role-Based Access Control is important for the following resources in chart manifests:
- ServiceAccount (namespaced)
- Role (namespaced)
- RoleBinding (namespaced)
Keep in mind that the RBAC and ServiceAccount configurations should be done under separate keys in YAML, because they represent different functionality:
rbac: create: true serviceAccount: create: true
The RBAC resources should always be created by default (set to true).
We have discussed some of the main best practices for creating Helm charts, but there are many more that can help ensure maximum reusability, code quality, and efficient deployment. See the Chart Best Practices Guide for Helm for more tips.
Container orchestration is all about managing the lifecycles of containers, especially in large, dynamic environments. Through container orchestration, DevOps teams can control and automate many tasks such as the provisioning and deployment of containers.
Kubernetes is a very popular container orchestration system, but it can become very complex when handling objects and releases. Helm is a very useful packaging solution for making Kubernetes more manageable.