⎈ helm
⚠️ These are notes taken from the book Learning Helm by Matt Butcher, Matt Farina and Josh Dolitsky on O'Reilly Please go read it and just use this as reference.
Introduction
Helm is the package manager for k8s. Let us do a super quick dive into what k8s is an all that just to give the context necessary to understand helm.
Context for Helm (containers & k8s)
Sometime ago someone thought of a new way of making apps, instead of them being a big monolithic service, we could split everything into small discrete standalone services. Then we could join those services using API over the network and build the application that way. That is how microservices were born.
Containers
To help with this the concept of containers was introduced, it is different of a VM because the VM runs an entire OS on on a host machine. On the other hand, a container has its own file system, but it uses the same OS kernel as the host.
A container is a program together with its dependencies and environment, they are packaged together into a container image which can be build based on a file where you specify the packages you want to run, and how to set the environments. The cool part is that all those instructions are not compiled into a binary or anything, but they are packaged into discrete layers.
So if a host has an image with five layers, and there is another host that needs the same image, it will just fetch the layers it does not already have.
Say you have three images using fedora-minimal:37
, well it would reuse that
layer on all those three.
Those images are stored in a registry, the registry tells hosts which layers compose an image. So the host can only download the layers it need from the registry.
A registry identifies an image by three things:
- name: basically a string
fedora
orfedora-minimal
- tag: usually the version
latest
orv1
- digest: a hash of the image, since the tags are mutable.
They look like name:tag@digest
.
Kubernetes (or k8s like the cool kids call it)
So with all these container stuff, some questions begin to arise:
- How do we best execute lots of containers?
- How can they work together?
- How do we manage memory, cpu, network and storage?
Well a bunch of companies tried to create this orchestration of containers technology to answer those questions, at the end as per 2024 seems like Google won, and we now all use ⛵️ K8s.(which is greek for ship's capitan or something like that)
K8s won because it introduced two concepts that people really liked.
-
Declarative infrastructure Basically you tell k8s what your desired state of the cluster is, and it will work to make that happen.
-
Reconciliation loop How does k8s work behinds the scenes to reach the declarative configuration we set? Using a reconciliation loop.
In a reconciliation loop, the scheduler says: "Here is what the user wrote as his/her desired state. Here is the current state. They are not the same, lets reconcile them."
Say you specified storage, and the scheduler sees that we do not have storage yet, it will create units of storage and attach them to your containers.
Pods
We do not deal directly with containers when setting up our k8s cluster.
We use a pods. A pod which is basically a group of containers. These are
defined in a manifest (yaml
or json
, but most people use yaml
)
apiVersion: v1 # we can see that this will be a v1 Pod
kind: Pod
metadata:
name: example-pod
spec:
containers:
- image: "fedora-minimal:latest"
- name: example-fedora
A Pod can have 1 or more containers. The containers that help preconfigurate stuff for the main one, are called init containers.
The ones that run alongside the main container are called sidecar containers
ConfigMaps
Basically in a pod you describe the configuration the containers need, like
network ports files system mount points. You can store configuration
information for k8s in ConfigMaps
and password and stuff like that in
Secret
.
Here is an example:
apiVersion: v1
kind: ConfigMap
metadata:
name: configuration-data
data: # inside here we will declare aribitrary key/value stuff
backgroundColor: blue
title: Learning Helm
For Secret
is pretty much the same as for ConfigMaps
but the values in data
must be Base64 encoded.
Pods then can be linked to the ConfigMaps like this:
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
volumes:
# note that this is not the metadata name you used in the ConfigMap
- name: my-configuration
configMap:
name: configuration-data # same name as in metadata of ConfigMap
containers:
- image: "fedora-minimal:latest"
name: example-fedora
env:
- name: TITLE # the env variable will be title
valueFrom:
configMapKeyRef:
name: configuration-data # name for the volume
key: title # key in the actual ConfigMap
Deployments
Pretty cool stuff, but we might not just one to run one instance of our
container, therefore we can use something called Deployments
.
A Deployment
describe an application as a collection of identical pods,we can
tell k8s to create our app with a single pod and scale it up to five pods.
apiVersion: apps/v1 # apps/v1 Deployment
kind: Deployment
metadata:
name: example-deployment
labels:
app: my-deployment
spec:
replicas: 3 # we want three replicas of the following template
selector:
matchLabels:
app: my-deployment
template:
metadata:
labels:
app: my-deployment
spec:
containers :
-image: "fedora-minimal"
name: "example-fedora"
Service
A Service
is a persistent network resource, that persists even if the pod or
pods attached to it go away.
apiVersion: v1
kind: Service
metadata:
name: example-service
spec:
selector:
app: my-deployment
ports:
- protocol: TCP
port: 80
targetPort: 8080
Here we define a service for the pods with the app: my-deployment
, telling
that traffic port 80 of this Service
will be routed to 8080.
Helm's Goal
So we have seen the building block of K8s, say you want to deploy a WordPress
app, you would need a Deployment
for the containers, then a ConfigMap
and
Secret
for the password, maybe some Service
objects and so on. That sounds
like a lot of yaml
.
The core idea of Helm is that all those objects can be packaged to be
installed
, updated
and deleted
together.
Basically helm is the package manger of kuberentes. Helm will allow you to spin up all the k8s objects necessary for an app by just using a few commands.
Here are some of the things that helm can do:
- Provide package repos (similar to
dnf
orapt
). - Familiar install, upgrade, delete commands.
- Helm has a method for configuring the packages before installing them.
- Helm can also let you know what already is installed.
You can also limit the installation of packages to a specific namespace, so you can install the same package in different namespaces in the same k8s cluster. (What is a namespace?)
Helm also provides reusability, it uses charts for this. A chart provides a pattern for producing the same k8s manifests. But the cool part is that you can also add more configuration to those charts.
Helm provides patterns for storing the initial configuration plus the changes
you did. Helm encourages k8s users to package their yaml
into charts so that
these descriptors can be reused.
One last thing, keep in mind that helm is not a configuration tool, it helps but it there are software specialized on that like ansible, puppet or chef.
Helm Architecture
Here are the main components that helm uses.
K8s Resource/Object
These are the Pods
, ConfigMap
, Deployment
, we have seen throughout the
chapter. K8s has a lot of these objects, you can even define custom ones using
custom resource definition (CRD).
All the resources share some elements
apiVersion: apps/v1 # api and version of the resource
kind: Deployment # resource type
metadata: # top-level data on the resource/object
name: example-deployment # req for all objects
labels: # used for creating query-able handles
some-name: some-value
annotations: # authors to attach their own keys and values
some-name: some-value
Charts
A package is called a chart. The idea es that k8s meaning captian, helm being the steering mechanism of the ship. The chart plots the way k8s apps should be installed.
A Chart is a set of files and directories that describe how to install the different k8s resource/objects
A chart contains
Chart.yaml
: describes the chart (name, description, authors)templates
directory: Inside all the k8s manifests potentially annotated with templating directivesvalues.yaml
file that provides the default configuration. You can override during installation.
These are the basic stuff for an unpacked chart, a packed chart is just a tar ball with all this inside.
Resources, Installations and Releases
When a helm chart is installed:
- helm reads the charts (will download if necessary)
- It sends the values into the templates generating the k8s manifests
- The manifests are sent to k8s
- K8s creates the requested resources inside the cluster
One last concept release. A release is created each time we use helm to modify the installation
Using Helm
Helm is a cli, you can install it with your favorite package manger or build it from source it is written in golang.
You can check the version by
helm version
Helm will use the same KUBECONFIG file you have configured for kubectl
, it
will look in the same places, though you can specify a path for one.
The most common workflow is:
- Add a chart repo
- Find a chart to install
- Install a Helm chart
- See the list of what is installed
- Upgrade your installation
- Delete your installation
Adding a Chart Repo
A Helm Chart is an individual package that can be installed into your k8s cluster. You can find then at chart repositories.
You can find popular repositories in the artifact hub
By default helm
does not have any repo added, so you need to look for one
there.
Bitnamis's official Helm charts are one of the best well-curated charts repos. (Some Bitnami devs are among the core contributors who design the helm repo system)
To add a repo you do helm repo add
so:
% helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories
Now if you do
% helm repo list
NAME URL
bitnami https://charts.bitnami.com/bitnami
You will see it there. After that we can look for specific charts.
% helm search repo drupal
NAME CHART VERSION APP VERSION DESCRIPTION
bitnami/drupal 18.0.2 10.2.5 Drupal is one of the most versatile open source...
You can also search label and descriptions
% helm search repo content
NAME CHART VERSION APP VERSION DESCRIPTION
bitnami/drupal 18.0.2 10.2.5 Drupal is one of the most versatile open source...
bitnami/harbor 21.1.2 2.10.2 Harbor is an open source trusted cloud-native r...
bitnami/nginx 16.0.6 1.25.5 NGINX Open Source is a web server that can be a...
bitnami/owncloud 12.2.11 10.11.0 DEPRECATED ownCloud is an open source content c...
bitnami/wordpress 22.2.2 6.5.2 WordPress is the world's most popular blogging ...
The chart version is the version of well, the chart. On the other hand the app version is the version of the software it would install.
Installing a package
% helm install mysite bitnami/drupal
NAME: mysite
LAST DEPLOYED: Wed May 1 16:40:16 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
# more text
Typical stuff, just a few things to keep in mind.
-
Difference between an installation and a chart.
An installation of a chart is a specific instance of the chart One chart may have many installations
-
You can repeat instance names (
mysite
), but it must be on different namespaces.
You can set values specific to your installation, you can set them directly
from the command line with --set
for example. (this works with both set
install
and upgrade
)
% helm install mysite bitnami/drupal --set drupalUsername=admin
You can also have them in a yaml
file, which is the recommended approach.
% helm upgrade mysite bitnami/drupal --values values.yaml
For example values.yaml
would look like this:
drupalUsername: admin
drupalEmail: [email protected]
mariadb:
db:
name: "my-database"
Listing your Installations
% helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
mysite default 1 2024-05-01 16:40:16.50636 -0600 CST deployed drupal-18.0.2 10.2.5
Not much to say here, does what expected.
Upgrading an Installation
So there are two types of changes:
- upgrade version of the chart
- upgrade configuration of the chart
Every time we perform an upgrade we are doing a new release of the same installation.
Helm will attempt to to alter only the bare minimum, so if you only changes one simple configuration variable, it will not like restart everything and all that.
To restart stuff just use kubectl
.
To update your chart with a new version you can
% helm repo update
% helm upgrade mysite bitnami/drupal
Configuration Values
If you do this:
% helm install mysite bitnami/drupal --values values.yaml
% helm upgrade mysite bitnami/drupal
Chances are you lost your values, so it is good to always send the yaml
% helm install mysite bitnami/drupal --values values.yaml
% helm upgrade mysite bitnami/drupal --values values.yaml
You can use helm get values mysite
to see the values sent on the last install
or upgrade.
You could also use:
% helm upgrade mysite bitnami/drupal --reuse-values
But it is not recommended
Uninstalling charts
Not much to say here
% helm uninstall mysite
Works as you would expect, if you would do
% helm list
You will not see it there.
Lastly, you can see a special record that contain release information.
% k get secret
Helm stores there the info.
If you uninstall you loose the history, so be careful. You could helm uninstall --keep-history
. Good if you plan on doing helm rollback
.
That is pretty much the basics on helm.