#helmfile (2022-07)

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/

2022-07-04

Balazs Varga avatar
Balazs Varga

hello all, I have a question. I have 2 charts and I move 1 secret from 1 chart to another. I do the kubectl patch and change the annotations to able to do helmfile apply on the chart where I copied the secret. when I do the apply on the chart from I moved the secret I see it deletes the secret does not check the annotation. Is it a bug or known issue ?

mumoshu avatar
mumoshu

hey! which annotation are you referring?

mumoshu avatar
mumoshu

thanks! does it work if you tried it without helmfile? i mean, does it reproduce if you upgraded the release which is the new owner of the secret, by running helm upgrade rather than helmfile apply?

mumoshu avatar
mumoshu

a bit more context- helmfile calls helm upgrade for upgrading releases. so if one thing doesn’t work with helm upgrade, it won’t work with helmfile apply.

Balazs Varga avatar
Balazs Varga

Will check. It works if I delete all sh.helm.release.v1.appname.vx file. that contains the last deployed data and I gues that i sthe problem as well. so if I delete a secret but diff will find it in the release file on cluster it will delete that secret…

2022-07-05

Ayoub Mrini avatar
Ayoub Mrini

Hello,

Are we still using [quay.io/roboll/helmfile](http://quay.io/roboll/helmfile) for docker images? I cannot find v0.145.0 (released 6 days ago). Am I missing something?

mumoshu avatar
mumoshu

our release automation was messed up! it’s now fixed and you should see images uploaded since v0.145.2 https://github.com/helmfile/helmfile/issues/207#issuecomment-1175798519

z0rc3r avatar

Actually quay.io isn’t used anymore. New org releases available at ghcr.io https://github.com/helmfile/helmfile/pkgs/container/helmfile

1

2022-07-06

Andrew Nazarov avatar
Andrew Nazarov

I’m wondering if release templates work with environments: I tried all possible syntaxes - nothing seems to work. Probably, I’m wrong conceptually.

mumoshu avatar
mumoshu

You can even use helmfile templates to render release templates from environment values. So probably you are conflating the two- like you are trying to refer to environment values from a release template?

Andrew Nazarov avatar
Andrew Nazarov

I think you are right. It seems it’s not the problem of environments: itself. Tried without it - still have some unmarshall errors.

I’m not sure if gotpl is supported in release templates. This is more likely the thing

My template is

templates:
  sharedService: &sharedService
    chart: chartmuseum/{{ .Release.Name }}
    namespace: {{ .Environment.Name }}
    missingFileHandler: Warn
    labels:
      tier: service
      type: shared-service
    values:
      - config/{{ .Release.Name }}/values.yaml.gotpl

And in values.yaml.gotpl I have {{ .Values }} and {{ .Environments }} references

Andrew Nazarov avatar
Andrew Nazarov

What we are trying to achieve is to improve readability and maintainability of our helmfile by reducing the number of lines (we have ~4000 lines of code). Trying out different approaches. But we need to keep environments: functionality and environments files as they are basically the interface for developers. We tried the first when each release has its own helmfile. From one hand it looks better, from another - if we need to fix a common thing we need to jump from file to file and we have like 50 of them. And to deploy them all at once we need either helmfiles: and a list of all the references or helmfile.d . We keep environments values in one file per environment when each release has its own key:

service1:
 parameter1: value1

service2:
 parameter1: value1

...

The second approach is to utilise the release template functionality and to put release values to separate files and keep environmnets values as it is.

Andrew Nazarov avatar
Andrew Nazarov


You can even use helmfile templates to render release templates from environment values.
Could you, please, elaborate. I think I didn’t get this right:)

mumoshu avatar
mumoshu

Thanks! A quick response to only a part of your info
config/{{ .Release.Name }}/values.yaml.gotpl
This will never work as you ight have intended. Such helmflie-level template expressions are rendered even before each so-called release template is rendered. At the time of helmfile-level templating, there’s no Release.Name… as it’s rendering the tempalte in the context of the whole helmfile.yaml, not each release defined inside it. So you saw config/{{ .Release.Name }}/values.yaml.gotpl to be actually translated to config//valules.yaml.gotmpl? Then yes, it’s working as intended at least.

mumoshu avatar
mumoshu

You may have some luck if it was written like

    valueTemplates:
      - {{` config/{{ .Release.Name }}/values.yaml.gotpl `}}

The key: Don’t let the helmfile-level template to evaluate {{.Release.Name}} yet.

{{

`

mumoshu avatar
mumoshu

// After probably two years since the feature had been implmemented, this two-phase go template rendering pipeline turned out to be too hard for anyone to understand fully That’s why I’m currently investigating possibilities to add Starlark support for writing dynamic helmfile config. With that you use a regular python-like program that is run once to produce a helmfile.yaml of your preference, instead of two-phase go template + yaml that is hard to understand

Andrew Nazarov avatar
Andrew Nazarov

Sorry, my example might confuse you. My templates: block in the recent try was located in the separate file and then in helmfile I had {{ readFile "template.yaml" }} . Before that I also tried to define templates: in helmfile with the following syntax

templates:
  sharedService: &sharedService
    chart: chartmuseum/{{`{{ .Release.Name }}`}}
    namespace: {{`{{ .Environment.Name }}`}}
    missingFileHandler: Warn
    labels:
      tier: service
      type: shared-service
    values:
      - config/{{`{{ .Release.Name }}`}}/values.yaml.gotpl

But no luck.

1
mumoshu avatar
mumoshu

In that case I think it worked only for chart(Did it?

mumoshu avatar
mumoshu

I slightly remember that someone contributed valuesTemplate and namespaceTemplate that are rendered by release template

1
mumoshu avatar
mumoshu

so i guess this may work

    chart: chartmuseum/{{`{{ .Release.Name }}`}}
    namespaceTemplate: {{`{{ .Environment.Name }}`}}
    missingFileHandler: Warn
    labels:
      tier: service
      type: shared-service
    valuesTemplate:
      - config/{{`{{ .Release.Name }}`}}/values.yaml.gotpl
Andrew Nazarov avatar
Andrew Nazarov

Cool. It seems valuesTemplate: is the solution. However namespaceTemplate doesn’t work:

err: failed to read helmfile.yaml: reading document at index 1: yaml: unmarshal errors:
  line 5: field namespaceTemplate not found in type state.TemplateSpec
  line 5: field namespaceTemplate not found in type state.ReleaseSpec
  line 5: field namespaceTemplate not found in type state.ReleaseSpec
  line 5: field namespaceTemplate not found in type state.ReleaseSpec

helmfile version v0.145.2

And I also had to add this yaml separator --- to make it work:

helmDefaults:
  verify: false
  wait: false
  timeout: {{ env "WAIT_TIMEOUT" | default 600 }}
  recreatePods: false
  force: false

environments:
  default:
    values:
      - default.yaml

---

{{ readFile "template.yaml" }}

releases:
...
mumoshu avatar
mumoshu


And I also had to add this yaml separator — to make it work:
Nice! Yeah it’s generally recommended to always add --- betwen environments and other configs

mumoshu avatar
mumoshu


owever namespaceTemplate doesn’t work:
Sorry Not sure where my memory came from!

Andrew Nazarov avatar
Andrew Nazarov


Yeah it’s generally recommended to always add --- betwen environments and other configs
Good to know. We had never had any problems without it before these experiments:)

mumoshu avatar
mumoshu

You’d ever get bitten by it only after you start using environments to dynamically generate releases Maybe that’s the case for you too?

Andrew Nazarov avatar
Andrew Nazarov

Not sure what you mean by dynamically generate. We have plenty of {{ if .Environment.Name }} and templetized installed: blocks:)

1
mumoshu avatar
mumoshu

Without ---, helmfile renders the whole helmfile.yaml using the empty Environments for the first time, so that it can finally read environments defined in your templated helmfile.yaml. It then “re-render”s the helmfile.yaml template by using the environments loaded by the prev step, so that the template result might be what you expected.

This breaks when the helmfile.yaml template is “half” broken, in a way so that it doesn’t generate a valid YAML document after the first rendering step. Then environments used for the second step becomes empty and you won’t get a valid result…

mumoshu avatar
mumoshu

We call this “double-rendering”. I added it due to a community demand. 2 years later, the more I think about it, I cant stop saying it’s fundamentally broken.

mumoshu avatar
mumoshu

With --- you basically avoid relying on this double-rendering so everything is ok

mumoshu avatar
mumoshu

and that’s why I proposed to deprecate using it without --- in helmfile 1.0 https://github.com/helmfile/helmfile/blob/main/docs/proposals/towards-1.0.md#the-changes-in-10

mumoshu avatar
mumoshu

I really don’t know who other than I and the original requestor of this feature knows how its supposed to work

mumoshu avatar
mumoshu

IMHO, the most robust way to write a dynamic helmfile.yaml is, to not use templates and release templates together. With all that said, your config would be more robust and easy to reason about if it’s rewritten like:

environments:
  default:
    values:
      - default.yaml

---

{{ define "r" }}
- name: {{ .name }}
    chart: chartmuseum/{{ .name }}
    namespace: {{ .env }}
    missingFileHandler: Warn
    labels:
      tier: service
      type: shared-service
    values:
      - config/{{ .name }}/values.yaml.gotpl
  {{* defaults *}}
  verify: false
  wait: false
  timeout: {{ getOrNil . "timeout" | default 600 }}
  recreatePods: false
  force: false
{{ end }}

releases:
{{ template "r" (dict "name" "myapp" "env" .Environment.Name "timeout" 300) }}
{{ template "r" (dict "name" "mydb" "env" .Environment.Name) }}
{{ template "r" (dict "name" "mylogagent" "env" .Environment.Name) }}
mumoshu avatar
mumoshu

or

r.tpl:

- name: {{ .name }}
    chart: chartmuseum/{{ .name }}
    namespace: {{ .env }}
    missingFileHandler: Warn
    labels:
      tier: service
      type: shared-service
    values:
      - config/{{ .name }}/values.yaml.gotpl
  {{* defaults *}}
  verify: false
  wait: false
  timeout: {{ getOrNil . "timeout" | default 600 }}
  recreatePods: false
  force: false

helmfile.yaml:

environments:
  default:
    values:
      - default.yaml

---

releases:
{{ tpl (readFile "r.tpl") (dict "name" "myapp" "env" .Environment.Name "timeout" 300) }}
{{ tpl (readFile "r.tpl")  (dict "name" "mydb" "env" .Environment.Name) }}
{{ tpl (readFile "r.tpl")  (dict "name" "mylogagent" "env" .Environment.Name) }}
Andrew Nazarov avatar
Andrew Nazarov

Thanks for the info. At the same time double-rendering allows us to achieve some things that are not possible without it:)

Probably we hadn’t faced issues with it before because we use double-rendering inside strings like

values:
  - extEnv:
      JAVA_OPTS: >
        -Dserver.port={{`{{ .Values.container.port }}`}}
1
Andrew Nazarov avatar
Andrew Nazarov


IMHO, the most robust way to write a dynamic helmfile.yaml is, to not use templates and release templates together.
You meant not to use environments and release templates together, right?

mumoshu avatar
mumoshu

Yep. Of course it’s just my recommendation- but you should be able to achieve anything that is possible with release template with define/template or readFile/tpl.

1
Andrew Nazarov avatar
Andrew Nazarov

I tried both options and neither works if I want to have templates in

values:
  - config/{{ .name }}/values.yaml.gotpl

For example if I have

environments:
  default:
    values:
      - test: value

and in values.yaml.gotpl

test:
  myVar: {{ .Values.test }}

then helmfile lint executing helm lint myrelease shows

Error: failed to parse /var/folders/pl/k4wqlgfj3cjf6b2p7qblq1200000gn/T/helmfile3449615217/default-print-service-values-57f59bc64: error converting YAML to JSON: yaml: invalid map key: map[interface {}]interface {}{".Values.test":interface {}(nil)}
Andrew Nazarov avatar
Andrew Nazarov

For inline values second-pass rendering fails with

error calling tpl: template: stringTemplate:11:25: executing "stringTemplate" at <.Values.test>: map has no entry for key "Values"
sohaibahmed98 avatar
sohaibahmed98
bridgecrewio/AirIAM

Least privilege AWS IAM Terraformer

2022-07-08

2022-07-10

2022-07-25

Moath avatar

:wave: Hello, team! I’m a helmfile newbie, and I’m having a hard time using diff :picard_fail: On a helm, I used to do it this way: helm diff upgrade grafana grafana/grafana --values grafana-values.yaml How can I do such thing in helmfile ?

Thank you^

Balazs Varga avatar
Balazs Varga

helmfile -l name=grafana diff

1
Moath avatar

keep getting this error:

Balazs Varga avatar
Balazs Varga

what version of helmfile and helm and diff you have ?

Moath avatar

Helmfile: v0.145.2 diff: 3.1.3

Balazs Varga avatar
Balazs Varga

use latest diff

Balazs Varga avatar
Balazs Varga

helm plugin install https://github.com/databus23/helm-diff –version v3.5.0 and I had to set

export HELM_DIFF_COLOR=true
databus23/helm-diff

A helm plugin that shows a diff explaining what a helm upgrade would change

Moath avatar

Works! Thanks a lot

1

2022-07-27

Jonathan Monnet avatar
Jonathan Monnet

hi everyone ! newbie on Helmfile i’ve started with this wonderful tools on sunday night.

atm i’m struggling with an issue about diffand my values.yaml

#helmfile.yaml
templates:
  default: &default
    cleanupOnFail: true
    chart: "{{`{{ .Release.Name }}`}}/{{`{{ .Release.Name }}`}}"
    namespace: "{{`{{ .Release.Name }}`}}"
    missingFileHandler: Warn
    # This section allows the destruction of the namespaces when: helmfile destroy
    hooks:
      - events: ["postuninstall"]
        showlogs: true
        command: "kubectl"
        args: ["delete", "namespaces", "{{`{{.Release.Namespace}}`}}"]
    values:
      - "environments/{{`{{ .Release.Name }}`}}/{{`{{ .Environment.Name }}`}}.yaml"
releases:
  # - name: cert-manager
  #   <<: *default
  #   namespace: certs

  - name: traefik
    <<: *default
    namespace: traefik
---

#environments/traefik/dev.yaml

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: traefik-dashboard
  namespace: traefik
spec:
  entryPoints:
    - web
    - websecure
  routes:
    - match: Host(`machin.com`) # Hostname to match
      kind: Rule
      services: # Service to redirect requests to
        - name: api@internal # Special service created by Traefik pod
          kind: TraefikService

first time i deploy everything seems good,, but the next time i deploy with something changed into my dev.yamlfile helmfiledo not sow any diff and i see nothing in K8S

=> $ helmfile -e dev apply --skip-deps

any idea ?

voron avatar

On the first look, releases: section should be placed into helmfile.yaml instead of environments/traefik/dev.yaml

Jonathan Monnet avatar
Jonathan Monnet

my bad , the section

releases:
  # - name: cert-manager
  #   <<: *default
  #   namespace: certs

  - name: traefik
    <<: *default
    namespace: traefik

is already in helmfile.yaml

voron avatar

do helm get values traefik relfect dev.yaml changes after applying ?

voron avatar

When it is so -> issue is with chart + values combo. When no changes -> issue is somewhere in helmfile-related staff

Jonathan Monnet avatar
Jonathan Monnet
(base) jmonnet in ~/Documents/CI/conccourse/ci-next/stack-k8s on jmonnet/confif-traefik-cert-manager ● ● λ kubectl get namespaces
NAME              STATUS   AGE
concourse-main    Active   11h
kube-system       Active   11h
kube-public       Active   11h
kube-node-lease   Active   11h
default           Active   11h
monitoring        Active   11h
portainer         Active   11h
metallb-system    Active   87m
traefik           Active   52s
(base) jmonnet in ~/Documents//CI/conccourse/ci-next/stack-k8s on jmonnet/confif-traefik-cert-manager ● ● λ helm get values traefik
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/jmonnet/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/jmonnet/.kube/config
Error: release: not found
Jonathan Monnet avatar
Jonathan Monnet

strange nothing in helm release

voron avatar

just add a namespace -n traefik

voron avatar

or use kubens to switch current k8s context to this namespace

Jonathan Monnet avatar
Jonathan Monnet

i forgot about my namespace ahah sorry ><

$ helm get values -n traefik traefik
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/jmonnet/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/jmonnet/.kube/config
USER-SUPPLIED VALUES:
ingressRoute:
  dashboard:
    enabled: false
ports:
  web:
    port: 80
  websecure:
    port: 443
securityContext:
  capabilities:
    add:
    - NET_BIND_SERVICE
    drop:
    - ALL
  readOnlyRootFilesystem: true
  runAsGroup: 0
  runAsNonRoot: false
  runAsUser: 0
voron avatar

now it’s time to introduce changes into dev.yaml, run helmfile apply and check if these changes hit to helm get values result

Jonathan Monnet avatar
Jonathan Monnet

change done on

websecure:
    port: 444

in this case , diffl plugin work , and i see my change in helm get values -n traefik traefik

but when i change

- match: Host(`toto.com`) # Hostname to match

there is no change in helmfile -e dev apply and nothin in helm get values -n traefik traefik

voron avatar

I think dev.yaml is invalid. You cannot put raw yaml manifest into helm values usually

voron avatar

You have to find in the chart source code what helm chart variable corresponds to what you need to change. Then you’re ready to set this variable via helm values. Helmfile is a helm wrapper in the first place. Try to run helm directly with --values pointing to dev.yaml , w/o helmfile

Jonathan Monnet avatar
Jonathan Monnet

ok will dig with this informations, thank you @voron

1
voron avatar

when you’re good with plain helm - you’re ready to put these values into helmfile, with some additional templating, env-specific variables and all the rest of helmfile nice features

2022-07-28

Balazs Varga avatar
Balazs Varga

hello all, any idea about this issue?

panic: runtime error: slice bounds out of range [:1451] with capacity 729
jrade avatar

The command(s) that were executed might be helpful. As far as code goes, it’s a Golang error where it is trying to get more indexes from an arr of smaller length

2022-07-29

Brandon avatar
Brandon

Is there a way to apply labels to a namespace without using hooks?

steenhoven avatar
steenhoven

Wondering the same thing.

Andrew Nazarov avatar
Andrew Nazarov

Kyverno (https://kyverno.io/) + a Policy defined as a release in helmfile Recently they’ve added a possibility to mutate existing objects.

Actually, here is the link to an announcement with exactly this use case: https://nirmata.com/2022/06/03/kyverno-v1-7-0-mutate-and-generate-existing-resources-is-here/

Kyverno

Kyverno is a policy engine designed for Kubernetes

Kyverno v1.7.0 - Mutate and Generate Existing Policy Resources

Nirmata announces the release of Kyverno v1.7.0 with the functionality of mutation and generation for existing policy resources for managing Kubernetes for DevOps efforts!

    keyboard_arrow_up