Helmfile : Deploy multiple charts in your cluster k8S
Tags: kubernetes, devops, productivity, webdev
Published: 2021-03-06 17:07:09

## Prerequisites

* Cluster K8S

* Helmfile

* Docker (helmfile image container, optional)

## Concepts

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fghhtyi8xi2wl09tksug.png)

Helmfile allows to declare specification for deploying multiple Helm charts. All information is saved in the helmfile.yaml file. 

Here is the advantages of using Helmfile :

* Keep a directory of chart value files and maintain changes in version control.

* Apply CI/CD to configuration changes.

* Environmental chart promotion.

* Periodically sync to avoid skew in environments.

## Installation

* Dowload Helmfile Release : [https://github.com/roboll/helmfile/releases](https://github.com/roboll/helmfile/releases)

* Download via Brew : brew install helmfile

* Use a docker container : 

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

* Use a docker container (cablespaghetti/helmfile-docker) : 

```bash
docker run --rm --net=host -v "${HOME}/.kube:/root/.kube" -v "${HOME}/.config/helm:/root/.config/helm" -v "${PWD}:/data" --workdir /data cablespaghetti/helmfile-docker helmfile 
```

## Getting Started

Suppose the helmfile.yaml representing the desired state of your helm releases looks like:

```yaml
releases:
- name: prom-norbac-ubuntu
  namespace: prometheus
  chart: stable/prometheus
  set:
  - name: rbac.create
    value: false
```

Sync your Kubernetes cluster state to the desired one by running:

```bash
# Sync all your chart releases
helmfile sync

# OR
# Apply all your chart releases
helmfile apply

# OR
# Sync all your chart releases (offline)
helmfile charts
```

## Advanced Usage

### Multiple values (for multiple environments)

Dev Environment

```yaml
# helmfile-dev.yaml
repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: my-postgres
    namespace: my-namespace-dev
    chart: bitnami/postgres
    values:
      - ./values/postgres-dev-1.yaml
      - ./values/postgres-dev-2.yaml
```

```
# Sync all your chart releases
helmfile -f helmfile-dev.yaml sync
```

Prod Environment

```yaml
# helmfile-prod.yaml
repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: my-postgres
    namespace: my-namespace-production
    chart: bitnami/postgres
    values:
      - ./values/postgres-prod-1.yaml
      - ./values/postgres-prod-2.yaml
```

```
# Sync all your chart releases
helmfile -f helmfile-prod.yaml sync
```

### Environment Variables

```yaml
# helmfile-prod.yaml
repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: {{ requiredEnv "NAME" }}-postgres
    namespace: {{ requiredEnv "NAME" }}
    chart: bitnami/postgres
    set:
    - name: image
      value: {{ requiredEnv "DOCKER_IMAGE" }}
    - name: version
      value: {{ requiredEnv "VERSION" }}
    values:
      - ./values/postgres-prod.yaml
```

```
# Sync all your chart releases
NAME=my-project VERSION=1 DOCKER_IMAGE=postgres:latest helmfile -f helmfile-prod.yaml sync
```

### Templates

```
# helmfile.yaml
releases:
  - name: {{ requiredEnv "NAME" }}-vault
    namespace: {{ requiredEnv "NAME" }}
    chart: roboll/vault-secret-manager
    values:
    - values.yaml.gotmpl
```

```
# values.yaml.gotmpl
db:
  username: {{ requiredEnv "DB_USERNAME" }}
  password: {{ requiredEnv "DB_PASSWORD" }}
proxy:
  domain: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com
  scheme: {{ env "SCHEME" | default "https" }}
```

### Environement Files

```yaml
# helmfile.yaml
environments:
  production:
    values:
    - production.yaml

releases:
- name: myapp
  values:
  - values.yaml.gotmpl
```

```yaml
# production.yaml
domain: prod.example.com
releaseName: prod
```

```yaml
# values.yaml.gotmpl
domain: {{ .Values | get "domain" "dev.example.com" }}
```

### Secrets

```yaml
# helmfile.yaml
environments:
  production:
    secrets:
    - environments/production/secrets.yaml

releases:
- name: myapp
  chart: mychart
  values:
  - values.yaml.gotmpl
```

```yaml
# environments/production/secrets.yaml
foo.bar: "mysupersecretstring"
```
The value can be used  in your values.yaml.gotmpl like : 

```yaml
{{ .Values.foo.bar }}
```

## Examples

```yaml
repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: my-nginx
    namespace: my-namespace-production
    chart: bitnami/nginx
    values:
      - ./values/nginx-production.yaml
  - name: my-postgres
    namespace: my-namespace-production
    chart: bitnami/postgres
    values:
      - ./values/postgres-production.yaml
```

## Links

[https://github.com/roboll/helmfile](https://github.com/roboll/helmfile)

[https://github.com/roboll/helmfile/tree/master/examples](https://github.com/roboll/helmfile/tree/master/examples)

[https://lyz-code.github.io/blue-book/devops/helmfile/#:~:text=Helmfile%20is%20a%20declarative%20spec,Environmental%20chart%20promotion.](https://lyz-code.github.io/blue-book/devops/helmfile/#:~:text=Helmfile%20is%20a%20declarative%20spec,Environmental%20chart%20promotion.)

[https://github.com/wkrzywiec/k8s-helm-helmfile](https://github.com/wkrzywiec/k8s-helm-helmfile)

[https://hub.docker.com/r/cablespaghetti/helmfile-docker](https://hub.docker.com/r/cablespaghetti/helmfile-docker)

[https://alexsimonjones.medium.com/helmfile-post-v3-helm-519c82a29c6a](https://alexsimonjones.medium.com/helmfile-post-v3-helm-519c82a29c6a)