helm
"The Kubernetes Package Manager" - https://github.com/kubernetes/helm
These notes are all about helm version 3. Charts that require helm 3 should use apiVersion: v2
, though helm 3 does support v1.
Links
Tips
List all versions of a chart in a given repo
helm search repo repo_name/chart_name --devel --versions
Include pre-release versions in all versions
You have to use mastermind/semver constraints with helm, which dictate that you have to include a pre-release component if you want to match against prereleases:
helm search repo repo_name/chart_name --devel --versions --version '^1.5-0'
This would show all versions including prereleases before or equal to 1.5.x. If you only want to show the latest version even if it is a prerelease, leave off --versions
.
Get values of a deployed chart
This only shows values that were passed in, not default values.
$release_name
is the NAME column in helm list
helm get values -o yaml "$release_name" > values.yaml
To get a list of all values, use
helm get values --all -o yaml "$release_name" > values.yaml`
Show notes for a deployed service
Notes are printed when you install a service, but they can be viewed again by running helm status <release_name>
where <release_name>
is one of the releases from helm list
.
Install the stable repo
helm repo add stable https://charts.helm.sh/stable
Install the incubator repo
https://github.com/helm/charts#how-do-i-enable-the-incubator-repository
helm repo add incubator https://charts.helm.sh/incubator
Show metadata about a specific release in json
You can find the revision in a few places, like helm list -A
. Default is to store data about the last 10 releases per release_name.
helm history -n "$NS" "$RELEASE_NAME" -o json | jq '.[] | select(.revision == 157)'
Show raw data about what helm sent to the k8s server for a recent release
First, find the secret that you will want to search. You can get the release number from helm history -n "$NS" foo
or dig in kubectl -n $NS get secret
$ k -n "$NS" get secret | grep sh.helm.release | tail -n 3 | column -t
sh.helm.release.v1.foo.v338 helm.sh/release.v1 1 14d
sh.helm.release.v1.foo.v339 helm.sh/release.v1 1 13d
sh.helm.release.v1.foo.v340 helm.sh/release.v1 1 4d23h
Then send that secret into the following command to get the full manifest that was sent to the k8s api:
k -n "$NS" get secret "$SECRET" -o go-template='{{ .data.release | base64decode | base64decode }}' |
gzip -d
The result is a json blob with all the details of how the helm chart was applied, including hook manifests, app manifests, and other metadata.
Splay cron jobs
Splaying cron jobs avoids the thundering herd problem by spreading the jobs out over time with deterministic randomness.
The functions available when using Helm templates are not as plentiful and general purpose like you would expect in a normal programming language, so we have to get creative for some things. One thing that would be great is if Helm provided a deterministic random feature. It does have randomness, but there is no way to seed the random number generator. To work around this, we can use other functions that do take inputs in order to generate deterministic random-ish numbers. One such example is using adler32sum
, which returns a base-10 hash value of an input.
The following example splays a cron job that runs every 15 minutes from 3-12 inclusive, which should avoid high-demand minutes at the beginning of 0/15, and still give a few minutes for work to complete before coming back around to the next 0/15 interval.
'{{- add 3 (regexFind ".$" (adler32sum .Release.Name)) -}}-59/15 * * * *'
This bit of code aler32sums the .Release.Name
value, which is expected to be unique for every deployment but may not be in your environment, takes only the right-most digit, which is 0-9, and adds 3 to it, then uses that number as the starting minute in the cron schedule, EG: 7-59/* * * * *
.
Here is a python script that shows what minute number would be generated for 235,976 inputs:
#!/usr/bin/env python3
from zlib import adler32
from pathlib import Path
_input = Path("/usr/share/dict/words").read_text().split()
output = {x + 3: 0 for x in range(10)}
for item in _input:
cksum = adler32(str.encode(item))
splay_minute = int(str(cksum)[-1]) + 3
output[splay_minute] += 1
for k, v in output.items():
print(f"{k:2d}: {v}")
And the output shows a pretty even splay across all minutes, with each minute containing roughly 1/10th of the input lines:
$ ./test-adler32sum.py
3: 23483
4: 23523
5: 23699
6: 23628
7: 23464
8: 23750
9: 23435
10: 23833
11: 23605
12: 23556
Surely there is more rigorous statistical analysis needed to better understand exactly how the inputs are being spread, but if you care that much about it, you are probably better off submitting a pr with your desired behavior to https://github.com/Masterminds/sprig, which is where the helm template functions come from.
Detect helm resources that do not have proper annotations
Helm requires that certain annotations exist. This this check will return all deployments that do not contain the required anntoations:
kubectl get deployments -A -o json |
jq '.items[] | select((.metadata.annotations."meta.helm.sh/release-name" == null) or (.metadata.annotations."meta.helm.sh/release-namespace" == null)) | .metadata.name'
Links
- https://github.com/databus23/helm-diff: "This is a Helm plugin giving your a preview of what a helm upgrade would change."
- https://blog.flant.com/advanced-helm-templating