Helm hooks - real use cases
Intro
Helm is a wonderful package manager with embedded features like powerful templating and it is a must have tool (at least to evaluate) in order to manage Kubernetes yaml by now.
As environments grow and together their complexity, it's inevitable to have a lot of Kubernetes yaml files of different applications.
Applications have usually different scopes and can be deployed separately but sometimes, for different reasons (ex. lift and shift from legacy applications), they need to be striclty coupled and need to respect a specific order of startup.
Helm can help with hooks feature even if it has some pitfalls where we can fall into.
I've used this feature (also in some production environments) and I'm here to show how they works with practical examples, where are potential pitfalls and how (IMHO) helm hooks can really help.
What below of course is related to the actual latest Helm release (v3.12.2
).
How they works
Helm hooks basically decide if, when and the order of the creations of some kubernetes resources (hooks) compared to resources without hooks.
In addition, hooks has a concept of readiness to allow a hook to raise errors and blocks the installation of the next.
As official doc says (https://helm.sh/docs/topics/charts_hooks), hooks can be easly configured with annotations
kind: Job
apiVersion: batch/v1
metadata:
name: pre-upgrade-job
namespace: test-hook-helm
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation
"helm.sh/hook-weight": "-5"
spec:
....
Unfortunately, the Helm hooks readiness is not related to the kubernetes readiness that we all know :-(
The concept of Helm hooks readiness is really simple and less powerful compared to the Kubernetes readiness:
- if the resorce is a job, it will be ready after its successfully completation.
If the job will end with error state, Helm will catch it. - for the other resources, they will become ready simply when Kubernetes API server accepts them.
Based on the above readiness definition, if you define hooks with deployments/statefulset you simply control the order on the resources creation which could differ on when these pods will become ready (kubernetes scheduler than decide it).
So, it could be not really useful.
Instead, by using job we have an interesting real use case of using Helm hooks because Helm will go on only if all hooked jobs will successfully complete.
Imagine to have configured some pre-upgrade
/ pre-install
jobs hooks in your helm chart beside some other resources that are not hooked.
After the helm upgrade -i ...
command, Helm will execute only your jobs and actively wait for completation.
If at least one job fails, all other next hooks will not executed at all as well for the all other helm resources.
See the below example where the failed hooked job will make the helm upgrade -i ..
command to fail and stop. No other resources are installed due to the prematuration exit of helm upgrade -i ...
command.
When instead all the hooked jobs are succesfully completed, also all the other helm resources will be installed.
In the following example you can see a set up of 2 hooked jobs and after their completation also the other helm resources are correctly installed.
Keep also in mind that all hooked resources will live outside your helm chart release.
So if you basically do a helm uninstall
of the chart that contains the hooks, these hooks will not be removed.
For this reason, helm.sh/hook-delete-policy
annotation controls when hooked resources has to be deleted automatically by Helm (ex. every time a hook succeded or retain only one).
Details here https://helm.sh/docs/topics/charts_hooks/#hook-deletion-policies
In conclusion, in my opinion, the only real interesting use case of using Helm hooks is by using it with Kubernetes Jobs resources and mainly with pre-install
and pre-ugrade
events.
For example it could be interesting to setup some jobs that must absolutely runned before any helm release and avoid to install the release if any job will not succesfully complete.