#helmfile (2023-10)
Questions and discussion around helmfile https://github.com/roboll/helmfile and https://github.com/cloudposse/helmfiles
Archive: https://archive.sweetops.com/helmfile/
2023-10-05
heyho! we’re redesigning our ci/cd using helmfile + argocd. we want to use helmfile to describe/compose our deployments and render them with “helmfile template” into a dir where argocd picks up the result and deploys it.
is there a good way to specify labels that are applied to all k8s manifests during “helmfile template”? we need to add those to collect usage statistics for cost optimizing purposes. I’ve searched the docs and haven’t found a solution, so I’d appreciate any help/hints
do helm support this feature? add custom labels for all resource?
helm does not, but kustomize does for sure
IMHO would the best solution be to include something like a “labels.yaml.gotmpl” file in the environments values section. haven’t managed to get that to work yet, hence my question
Yes, you can use the commonLabels config entry to add a set of labels to everything and can use that in helmfile templates.
2023-10-06
2023-10-12
Can anyone explain what “installed” means when you run helmfile list
?
I can see how the enabled attribute can change based on the condition but installed always seems to be true.
There is release attribute installed:
, it will install release when true
and remove the release when false
, while issuing helmfile sync
2023-10-17
2023-10-18
goccy/go-yaml in v1 mode is giving me hard time by double escaping backward slash and this breaks intended behaviour. sample helmfile.yaml.gotmpl:
repositories:
- name: open-telemetry
url: <https://open-telemetry.github.io/opentelemetry-helm-charts>
releases:
- name: opentelemetry-collector
namespace: opentelemetry
chart: open-telemetry/opentelemetry-collector
version: 0.72.0
disableValidationOnInstall: true
values:
- mode: deployment
config:
processors:
tail_sampling:
policies:
- name: drop_noisy_traces_by_url
type: string_attribute
string_attribute:
key: http.url
values:
- \.(js|css|json) # <--- this line is problematic
enabled_regex_matching: true
invert_match: true
with HELMFILE_V1MODE=true HELMFILE_GOCCY_GOYAML=false helmfile template |grep css -A5 -B5
resulting config map value is okay:
string_attribute:
enabled_regex_matching: true
invert_match: true
key: http.url
values:
- \.(js|css|json)
type: string_attribute
receivers:
jaeger:
protocols:
grpc:
but with HELMFILE_V1MODE=true HELMFILE_GOCCY_GOYAML=true helmfile template | grep css -A5 -B5
it’s double escaped for some reason and isn’t what i need
string_attribute:
enabled_regex_matching: true
invert_match: true
key: http.url
values:
- \\.(js|css|json)
type: string_attribute
receivers:
jaeger:
protocols:
grpc:
This looks like a bug in goccy/go-yaml library. You should log a bug there.
Even though, I don’t know all helmfile’s logic around parsing yamls, and in order to pinpoint the issue I need help from someone who knows helmfile codebase
I filled my findings at https://github.com/helmfile/helmfile/issues/1079
Operating system
MacOS 14.0
Helmfile Version
v0.157.0
Helm Version
v3.13.1
Bug description
With HELMFILE_V1MODE=true HELMFILE_GOCCY_GOYAML=false helmfile template | grep css -A5 -B5
result is okay:
string_attribute:
enabled_regex_matching: true
invert_match: true
key: http.url
values:
- \.(js|css|json)
type: string_attribute
receivers:
jaeger:
protocols:
grpc:
With HELMFILE_V1MODE=true HELMFILE_GOCCY_GOYAML=true helmfile template | grep css -A5 -B5
result is not okay, double escape \\.
is generated:
string_attribute:
enabled_regex_matching: true
invert_match: true
key: http.url
values:
- \\.(js|css|json)
type: string_attribute
receivers:
jaeger:
protocols:
grpc:
I wasn’t able to find how wrap or escape this string to avoid double escaping and preserve single slash. I tried single quotes, double quotes and go template literals like:
{{` \.(js|css|json) `}}
to no avail.
Example helmfile.yaml
It’s helmfile.yaml.gotmpl
repositories:
- name: open-telemetry
url: <https://open-telemetry.github.io/opentelemetry-helm-charts>
releases:
- name: opentelemetry-collector
namespace: opentelemetry
chart: open-telemetry/opentelemetry-collector
version: 0.72.0
disableValidationOnInstall: true
values:
- mode: deployment
config:
processors:
tail_sampling:
policies:
- name: drop_noisy_traces_by_url
type: string_attribute
string_attribute:
key: http.url
values:
- \.(js|css|json) # <--- this line is problematic
enabled_regex_matching: true
invert_match: true
Error message you’ve seen (if any)
None
Steps to reproduce
See Bug description
example helmfile
Working Helmfile Version
v0
Relevant discussion
Have you tried double escaping the input
So put \ in the tmpl
This is just a guess,
How do I explain that I don’t want this double escape? I already tried single and double quotes for this string, they didn’t have any effect. Also tried some esoteric escaping like
{{` \.(js|css|json) `}}
to no avail.
2023-10-19
2023-10-21
2023-10-22
I’m having escaping problems too.
Prometheus rules are a pain because they also use {{
and }}
as well as variables using like $labels.blah
.
In theory you can surround the lot by {{ and
}} however this still fails where you encounter Helm charts that use the tpl
and toYaml
functions…
As an example. there is a chart that renders a PrometheusRule
CRD; and cutting out the parts that aren’t of interest to the problem, like metadata
and other stuff in the spec
, the helm template file looks like:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
spec:
groups:
{{- range .Values.prometheusRules.extraAlertGroups }}
- {{ tpl (toYaml .) $ | indent 4 | trim }}
{{- end }}
And an unescaped version of the helmfile values file would have something like:
prometheusRules:
extraAlertGroups:
- name: custom.rules
rules:
- alert: CertificateError
annotations:
description: Certificate could not be decoded {{if $labels.secret_name }}in
Kubernetes secret "{{ $labels.secret_namespace }}/{{ $labels.secret_name
}}"{{else}}at location "{{ $labels.filepath }}"{{end}}
summary: Certificate cannot be decoded
expr: x509_cert_error > 0
for: 15m
labels:
severity: warning
Would result in the error:
in ./helmfile.yaml: failed processing release x509-certificate-exporter: failed to render values files "helm/vars/x509-certificate-exporter.yaml.gotmpl": failed to render [helm/vars/x509-certificate-exporter.yaml.gotmpl], because of template: stringTemplate:21: undefined variable "$labels"
Changing it to use {{ and
}} for the description like so
rules:
- alert: CertificateError
annotations:
description: {{` Certificate could not be decoded {{if $labels.secret_name }}in
Kubernetes secret "{{ $labels.secret_namespace }}/{{ $labels.secret_name
}}"{{else}}at location "{{ $labels.filepath }}"{{end}} `}}
summary: Certificate cannot be decoded
expr: x509_cert_error > 0
for: 15m
labels:
severity: warning
still results in the exact same error.
I haven’t worked out how to get around it…
Ughhh.. This works.
- alert: CertificateError
annotations:
description: '{{`{{`}}{{printf "\x60"}}{{`Certificate could not be decoded {{if $labels.secret_name }}in
Kubernetes secret "{{ $labels.secret_namespace }}/{{ $labels.secret_name
}}"{{else}}at location "{{ $labels.filepath }}"{{end}}`}}{{printf "\x60"}}{{`}}`}}'
summary: Certificate cannot be decoded
expr: x509_cert_error > 0
for: 15m
labels:
severity: warning
You have the innermost {{ and
}} which keeps things from expanding the first time.
Then you have
{{`{{`}}{{printf "\x60"}}
which produces a
{{
` and
{{printf "\x60"}}{{`}}`}}
to produce
`}}
I couldn’t just use
{{`{{
` and
`}}`}}
Finally I had to put a single quote at the start and the end to stop a error converting YAML to JSON: yaml: line 20: did not find expected key
error.
As far as I can tell it didn’t like the raw backtick appearing without it being quoted.
The above is a nightmare… Surely there’s an easier way? I even had trouble trying to render those things how I want to in Slack!
If I try:
description: '{{`{{`Certificate could not be decoded {{if $labels.secret_name }}in
Kubernetes secret "{{ $labels.secret_namespace }}/{{ $labels.secret_name
}}"{{else}}at location "{{ $labels.filepath }}"{{end}}`}}`}}'
then I get the error: failed to render [helm/vars/x509-certificate-exporter.yaml.gotmpl], because of template: stringTemplate:32: unexpected "Certificat"... in operand
The nicest way I could find to format the rule was:
- alert: CertificateError
annotations:
description: >
{{`{{`}}{{printf "\x60"}}
{{`
Certificate could not be decoded
{{if $labels.secret_name }}
in Kubernetes secret "{{ $labels.secret_namespace }}/{{ $labels.secret_name }}"
{{else}}
at location "{{ $labels.filepath }}"
{{end}}
`}}
{{printf "\x60"}}{{`}}`}}
summary: Certificate cannot be decoded
expr: x509_cert_error > 0
for: 15m
labels:
severity: warning
We just use .yaml
instead of .yaml.gotmpl
and it solves the problem
Thank you. I knew I had to be overlooking something that should be obvious. Now I just have to escape once with {{
}} to protect the rule from the tpl
function that’s used in the chart.
We don’t have to use any escaping with kube-prometheus-stack chart
Yeah, that chart doesn’t have tpl
used within its templates/prometheus/additionalPrometheusRules.yaml
where it applies the additionalPrometheusRulesMap
and additionalPrometheusRules
values.
2023-10-23
Hey Team, I am sure this is quite an easy task for an experienced helmfile writer but I could not figure it out: How do I reference all external secrets that I load with
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: "{{ .Release.Name }}-external-secrets"
spec:
secretStoreRef:
kind: ClusterSecretStore
name: vault
target:
name: "{{ .Release.Name }}-vault-secrets" # name of the Kubernetes `Secret` resource that will be created
creationPolicy: Owner
dataFrom:
- extract:
key: some/path/in/our/vault/{{ required "Namespace is required" $.Release.Namespace }}/{{required ".Values.clusterEnvironment not set" $.Values.clusterEnvironment}} # path to the secrets in Vault
I would like to add all secrets in vault as key value pairs to the following list:
externalSecrets:
clusterEnvironment: {{ .Values.clusterEnvironment }}
labelEnvironment: {{ .Values.labelEnvironment }}
VaultSecrets:
{{ .Values.{{ .Release.Name }}-external-secrets | expandSecretRefs | toYaml | indent 4 }}
this does not work but I have no idea how to deal with the helmfile/helm templating at this point.. Any suggestions greatly appreciated!
hey @Tim, I don’t think this line is valid {{ .Values.{{ .Release.Name }}-external-secrets | expandSecretRefs | toYaml | indent 4 }}
when referencing variable dynamically. Also, it might be worth creating a script to dynamically retrieve the secrets.
Thanks, I have resolved it by mapping the entire external secret into files on a volume
I’m wondering why I’m getting the following warning when I’m pretty sure I have adjusted it in my helmfile.yaml
file:
WARNING: environments and releases cannot be defined within the same YAML part. Use --- to extract the environments into a dedicated part
$ helmfile version
▓▓▓ helmfile
Version 0.158.0
Git Commit 9596790
Build Date 23 Oct 23 10:57 AWST (1 day ago)
Commit Date 23 Oct 23 05:51 AWST (1 day ago)
Dirty Build no
Go version 1.21.3
Compiler gc
Platform linux/amd64
https://github.com/helmfile/helmfile/issues/1093
Note that removing the first ---
document start marker solves the warning, however having that is valid YAML (and by default yamllint
will warn if you don’t have it.
@Jim fixed
Thank you.
We have a legacy system which uses kustomize
and new setup which uses helm/helmfile. We are trying to create a single values.yaml
for both setups where we can define e.g. image tags, and most of our services use the common tag with few exceptions. I know templates are a big no for Kustomize
but we want to add a values variable for image tag which can be overridden by helmfile. At the moment chartify only allows patch in values.yaml but we have flexibity to add vars in kustomize yaml files e.g. {{ .Values.NewTag }}
. Unfortunately, this doesn’t work because chartify when creating chart adds it to files/
. My question is, Is it possible to change this behaviour i.e. can we somehow direct chartify to unpack kustomize files in temaplates/
folder?
- name: mysql
2023-10-24
2023-10-25
Wondering if anyone has worked through a solution for helm-diff not supporting a means of selectively ignoring parts of a diff that will perpetually show a change (e.g. ca bundles)?
2023-10-27
Hi, I found an old issue where --reset-values
is added by default to helmfile sync
(and presumably apply
) (roboll/helmfile#63). I found that interesting and I fully agree with the reasoning.
The only suggestion I have is to document this more visibly. The only hint at it seems to be the reuseValues
option, however, it is not documented there (or elsewhere, as far as I can tell), that Helmfile deliberately differs from Helm’s default behavior.
Did you consider to create a PR with documentation updates ?
To be honest, I don’t feel comfortable adding a description of current behavior to the docs, because I’m not sure exactly what happens.
I’m confused by this: https://github.com/helmfile/helmfile/pull/602
implemented --reset-values
flag overriding .helmDefaults.reuseValues=true
as discussed: #593
A --reset-values
CLI flag has been added, but there’s no way to do the same via Helmfile’s YAML?
I guess this is how it works: reset
is the default. This can be overridden in Helmfile via reuseValues
. This can again be overridden via CLI flag --reset-values
.
However, that’s not the whole truth, because they can be used together (see comment).
A --reset-values
CLI flag has been added, but there’s no way to do the same via Helmfile’s YAML?
reset-values
is the default behaviour of helmfile imo. That’s why there is no need to do it via yaml. Introduced CLI flag --reset-values
allows to override reuseValues
yaml option to get back to default behaviour.
I guess this is how it works:
reset
is the default. This can be overridden in Helmfile viareuseValues
. This can again be overridden via CLI flag--reset-values
. Correct.
However, that’s not the whole truth, because they can be used together (see comment). And reset will win in this case, same as with helm.
To be honest, I don’t feel comfortable adding a description of current behavior to the docs, because I’m not sure exactly what happens. It may be a good point to create a PR to improve docs to look clear for yourself, and let reviewers to fix issues if any.
Is strategicMergePatches
suitable for adding new kubernetes resources (not just fields)?
not sure how helmfile implements it, but I think the recommended way to handle all creation and updates of kubernetes is now the equivalent of kubectl apply --server-side=true
.
This document is old and probably obsolete. Server-side Apply is the new solution and is the recommended way to go. It doesn't require any client-side logic.
We use raw
chart to do it helmfile-friendly. Yes, it’s another helm release, not an original one.
2023-10-30
hi folks, new to helmfile.. thanks for having me whats going to be a good/best practice for breaking out my releases into a well designed directory structure ?
It’s up to you, and let it evolve with your helmfile experience. A couple of refactors are ok here. Keep it simple and clear for you. The most used layout from our side is the following:
.
├── .sops.yaml
├── common
│ ├── helm-defaults.yaml
│ ├── repositories.yaml
│ ├── templates.yaml
│ └── values
│ └── ingress-nginx.yaml.gotmpl
├── environments
│ ├── asia
│ │ ├── .envrc
│ │ ├── helmfile.yaml
│ │ ├── secrets
│ │ │ └── ingress-nginx.yaml
│ │ └── values
│ │ └── ingress-nginx.yaml.gotmpl
│ ├── europe
│ │ ├── .envrc
│ │ ├── helmfile.yaml
│ │ ├── secrets
│ │ └── values
│ └── us
│ ├── .envrc
│ ├── helmfile.yaml
│ ├── secrets
│ └── values
└── helmfile.yaml
common are values that are used among all environments?