helmfile

When using helmfile, we first need to understand the use of helm and how to develop a helm chart. helm is a package management tool for kubernetes. In real life scenarios we need to deploy multiple charts at the same time, distinguish between different deployment environments, version control, etc. For this purpose, the helmfile tool can be used. helmfile helps users to manage and maintain multiple helm charts by means of helmfile files, which can be used to differentiate environments and implement version control.

Scenario Description

In our public cloud scenario or privatization scenario, the same product may involve multiple sets of environment configurations, for example, each set of environment deployment depends on different environment, the address and account password of the database, message queue middleware and other instances used are different. Therefore, for different environments we need to maintain the deployment files and secret key files of the development environment, test environment, pre-production environment, production environment and even multiple environments, and each small change will involve the modification of the configuration of multiple environments, which adds a great burden to the operation and maintenance staff, and how to maintain the uniformity of the configuration of multiple environments, which also greatly tests the meticulousness of the operation and maintenance staff and greatly increases the complexity. The storage of account passwords for the database middleware instances involved also adds a huge security risk to the O&M process. Based on the above, we can transform the service files of the business deployment into a helm chart, distinguishing between multiple environments and version control, and we use helmfile to unify the deployment management. We can use helm secrets to encrypt and decrypt the account passwords involved in the instance, as well as to ensure the security of operations and maintenance, thus greatly reducing the complexity of operations and maintenance. The use of helm secrets is described in detail in other articles.

Installation

helmfile offers a variety of installation options, see https://github.com/helmfile/helmfile/releases helmfile also supports running in containers and can be easily integrated into CICD’s pipeline.

1
2
3
4
5
# helm 2
$ docker run --rm --net=host -v "${HOME}/.kube:/root/.kube" -v "${HOME}/.helm:/root/.helm" -v "${PWD}:/wd" --workdir /wd quay.io/roboll/helmfile:v0.135.0 helmfile sync

# helm 3
$ docker run --rm --net=host -v "${HOME}/.kube:/root/.kube" -v "${HOME}/.config/helm:/root/.config/helm" -v "${PWD}:/wd" --workdir /wd quay.io/roboll/helmfile:helm3-v0.135.0 helmfile sync

Introduction to helmfile.yaml

helmfile.yaml is the core file of helmfile and is used to declare all the configuration. It will be briefly described below, and the official documentation can be consulted for specific instructions: https://github.com/roboll/helmfile#configuration

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# Declare repo configuration
repositories:
- name: <repo-name>
  # url: repo url
  # Basic configuration or tls authentication can be set
  # certFile: certificate file
  # keyFile: key file
  # username: username
  # password: password

# path to helm binary file
helmBinary: path/to/helm3

# These are the same as `helm SUBCOMMAND` and can be used to declare some, default, configurations
helmDefaults:
  tillerNamespace: tiller-namespace  #dedicated default key for tiller-namespace
  tillerless: false                  #dedicated default key for tillerless
  kubeContext: kube-context          #dedicated default key for kube-context (--kube-context)
  cleanupOnFail: false               #dedicated default key for helm flag --cleanup-on-fail
  # additional and global args passed to helm (default "")
  args:
    - "--set k=v"
  # verify the chart before upgrading (only works with packaged charts not directories) (default false)
  verify: true
  # wait for k8s resources via --wait. (default false)
  wait: true
  # time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks, and waits on pod/pvc/svc/deployment readiness) (default 300)
  timeout: 600
  # performs pods restart for the resource if applicable (default false)
  recreatePods: true
  # forces resource update through delete/recreate if needed (default false)
  force: false
  # when using helm 3.2+, automatically create release namespaces if they do not exist (default true)
  createNamespace: true
  ...

# Set the same label for all releases in the helmfile, which can be used to mark all releases with the same version
commonLabels:
  hello: world

# Set release configuration (multiple releases supported)
releases:
  # Remote chart example (chart already uploaded to remote repository)
  - name: vault                            # name of this release
    namespace: vault                       # target namespace
    createNamespace: true                  # helm 3.2+ automatically create release namespace (default true)
    labels:                                # Arbitrary key value pairs for filtering releases
      foo: bar
    chart: roboll/vault-secret-manager     # the chart being installed to create this release, referenced by `repository/chart` syntax
    version: ~1.24.1                       # the semver of the chart. range constraint is supported
    condition: vault.enabled               # The values lookup key for filtering releases. Corresponds to the boolean value of `vault.enabled`, where `vault` is an arbitrary value
    missingFileHandler: Warn # set to either "Error" or "Warn". "Error" instructs helmfile to fail when unable to find a values or secrets file. When "Warn", it prints the file and continues.
    # Values files used for rendering the chart
    values:
      # Value files passed via --values
      - vault.yaml
      # Inline values, passed via a temporary values file and --values, so that it doesn't suffer from type issues like --set
      - address: https://vault.example.com
      # Go template available in inline values and values files.
      - image:
          # The end result is more or less YAML. So do `quote` to prevent number-like strings from accidentally parsed into numbers!
          # See https://github.com/roboll/helmfile/issues/608
          tag: {{ requiredEnv "IMAGE_TAG" | quote }}
          # Otherwise:
          #   tag: "{{ requiredEnv "IMAGE_TAG" }}"
          #   tag: !!string {{ requiredEnv "IMAGE_TAG" }}
        db:
          username: {{ requiredEnv "DB_USERNAME" }}
          # value taken from environment variable. Quotes are necessary. Will throw an error if the environment variable is not set. $DB_PASSWORD needs to be set in the calling environment ex: export DB_PASSWORD='password1'
          password: {{ requiredEnv "DB_PASSWORD" }}
        proxy:
          # Interpolate environment variable with a fixed string
          domain: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com
          scheme: {{ env "SCHEME" | default "https" }}
    # Use `values` whenever possible!
    # `set` translates to helm's `--set key=val`, that is known to suffer from type issues like https://github.com/roboll/helmfile/issues/608
    set:
    # single value loaded from a local file, translates to --set-file foo.config=path/to/file
    - name: foo.config
      file: path/to/file
    # set a single array value in an array, translates to --set bar[0]={1,2}
    - name: bar[0]
      values:
      - 1
      - 2
    # set a templated value
    - name: namespace
      value: {{ .Namespace }}
    # will attempt to decrypt it using helm-secrets plugin
    
  # Example of a local chart (chart is saved locally)
  - name: grafana                            # name of this release
    namespace: another                       # target namespace
    chart: ../my-charts/grafana              # the chart being installed to create this release, referenced by relative path to local helmfile
    values:
    - "../../my-values/grafana/values.yaml"             # Values file (relative path to manifest)
    - ./values/{{ requiredEnv "PLATFORM_ENV" }}/config.yaml # Values file taken from path with environment variable. $PLATFORM_ENV must be set in the calling environment.
    wait: true

# Additional helmfiles can be nested to support pulling helmfiles from local and remote locations
helmfiles:
- path: path/to/subhelmfile.yaml
  # The label selector can filter the release to be overridden
  selectors:
  - name=prometheus
  # Override value
  values:
  # Overwriting with files
  - additional.values.yaml
  # Override separate key
  - key1: val1
- # Remote pull configuration
  path: git::https://github.com/cloudposse/helmfiles.git@releases/kiam.yaml?ref=0.40.0
# If it points to a path that does not exist, an alert error is printed
missingFileHandler: Error

# Multi-environmental management
environments:
  # When `--environment NAME` is not set, use default 
  default:
    values:
    # The content can be a file path or key:value
    - environments/default/values.yaml
    - myChartVer: 1.0.0-dev
  # "production" environment, when `helmfile --environment production sync` is set
  production:
    values:
    - environment/production/values.yaml
    - myChartVer: 1.0.0
    # disable vault release processing
    - vault:
        enabled: false
    ## `secrets.yaml` is decrypted by `helm-secrets` and available via `{{ .Environment.Values.KEY }}`
    secrets:
    - environment/production/secrets.yaml
    # When `environments.NAME.values` is not found, it can be set to "Error", "Warn", "Info", "Debug", the default is "Error"
    missingFileHandler: Error

# Hierarchical management, where all files can be merged in the following order: environments.yaml < - defaults.yaml < - templates.yaml < - helmfile.yaml
bases:
- environments.yaml
- defaults.yaml
- templates.yaml

# API functions
apiVersions:
- example/v1

helmfile debugging

Here, after compiling the relevant helmfile, we can use the following command to debug.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# View the catalogue structure
$ ls
README.org    environments  helm          helmfile      helmfile.yaml releases
# View helmfile.yaml
$ cat helmfile.yaml
environments:
  # If no environment is specified, the default test environment is used by default
  default:
    values:
       - environments/test/config.yaml
       - environments/test/versions.yaml
       - environments/test//namespaces.yaml
    secrets:
       - environments/test/secrets.yaml
  test:
    values:
      - environments/test/config.yaml
      - environments/test/versions.yaml
      - environments/test/namespaces.yaml
    secrets:
       - environments/test/secrets.yaml
helmDefaults:
  createNamespace: true
releases:
  - name: password-secrets
    kubeContext: {{ .Values.kubeContext.service }}
    namespace: {{ .Values.namespaces.service }}
    chart: helm/charts/secrets
    values:
      - releases/secrets.yaml.gotmpl
    labels:
      app: secrets

  - name: web
    kubeContext: {{ .Values.kubeContext.business }}
    namespace: {{ .Values.namespaces.business }}
    chart: helm/charts/web
    values:
      - releases/web.yaml.gotmpl
    labels:
      app: web
# helmfile debugging
$ helmfile -e test template 

Install chart

1
helmfile -e test sync

helmfile updates or removes a chart

Here you can specify the label to be updated or deleted by --selector.

1
2
3
4
# Updating web service
helmfile -e test --selector app=web sync
# Delete web service
helmfile -e test --selector app=web delete

View changes

1
2
3
4
# View the changes in the document.
helmfile -e test --selector app=web diff 
# View only the parts of the document that have changed.
helmfile -e test --selector app=web diff --context 4