#helmfile (2023-10)

https://github.com/helmfile/helmfile

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

OlGe404 avatar
OlGe404

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

yxxhero avatar
yxxhero

do helm support this feature? add custom labels for all resource?

OlGe404 avatar
OlGe404

helm does not, but kustomize does for sure

OlGe404 avatar
OlGe404

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

Matt Calhoun avatar
Matt Calhoun

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

CraigB avatar

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.

voron avatar

There is release attribute installed:, it will install release when true and remove the release when false , while issuing helmfile sync

1

2023-10-17

2023-10-18

z0rc3r avatar

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:
Dominique Dumont avatar
Dominique Dumont

This looks like a bug in goccy/go-yaml library. You should log a bug there.

z0rc3r avatar

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

z0rc3r avatar
#1079 Double escape backward slash with `HELMFILE_V1MODE=true`

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

#656

kallan.gerard avatar
kallan.gerard

Have you tried double escaping the input

kallan.gerard avatar
kallan.gerard

So put \ in the tmpl

This is just a guess,

z0rc3r avatar

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

Jim avatar

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…

Jim avatar

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 }}
Jim avatar

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
Jim avatar

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"
Jim avatar

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.

Jim avatar

I haven’t worked out how to get around it…

Jim avatar

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!

Jim avatar

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

Jim avatar

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
voron avatar

We just use .yaml instead of .yaml.gotmpl and it solves the problem

Jim avatar

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.

voron avatar

We don’t have to use any escaping with kube-prometheus-stack chart

Jim avatar

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

Tim avatar

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!

Ozzy Aluyi avatar
Ozzy Aluyi

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.

Tim avatar

Thanks, I have resolved it by mapping the entire external secret into files on a volume

1
Jim avatar

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
Jim avatar
$ 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
yxxhero avatar
yxxhero

@Jim please post a issue in to github issues.

2
Jim avatar

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.

yxxhero avatar
yxxhero

@Jim fixed

Jim avatar

Thank you.

Rameez avatar

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

andrew.j.gershman avatar
andrew.j.gershman

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

Tom Janson avatar
Tom Janson

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.

voron avatar

Did you consider to create a PR with documentation updates ?

Tom Janson avatar
Tom Janson

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.

Tom Janson avatar
Tom Janson
#602 Reset values flag

implemented --reset-values flag overriding .helmDefaults.reuseValues=true

as discussed: #593

1
Tom Janson avatar
Tom Janson

A --reset-values CLI flag has been added, but there’s no way to do the same via Helmfile’s YAML?

Tom Janson avatar
Tom Janson

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).

voron avatar


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 via reuseValues. 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.

z0rc3r avatar

Is strategicMergePatches suitable for adding new kubernetes resources (not just fields)?

Eamon Keane avatar
Eamon Keane

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.

https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md

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.
voron avatar

We use raw chart to do it helmfile-friendly. Yes, it’s another helm release, not an original one.

2023-10-30

Shawn avatar

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 ?

voron avatar

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
1
Shawn avatar

common are values that are used among all environments?

voron avatar

Yes. To keep things reasonably DRY.

1
    keyboard_arrow_up