Terraform + Helm = ❤️
Tags: kubernetes, devops, terraform
Published: 2020-09-20 14:53:54

If you ever tried to manage IaC with Terraform you might end up with “Well, the cloud resources are fine, but how am I going to deal with my Kubernetes cluster???”

In this post, I want to share a simple and functional example of how you can integrate Helm with Terraform using the best of each tool.

The setup of this integration became much easier after Helm v3 was released. Now, you can simply pass your Kubernetes credentials to the Helm Provider and start deploying your charts using Terraform!

```terraform
provider "helm" {
  kubernetes {
    config_path = "/path/to/kube_cluster.yaml"
  }
}
```

You can now deploy Charts using the `helm_release` resource 🎉. 

```terraform
resource "helm_release" "example" {
  name       = "my-redis-release"
  repository = "https://kubernetes-charts.storage.googleapis.com" 
  chart      = "redis"
  version    = "6.0.1"

  values = [
    "${file("values.yaml")}"
  ]

  set {
    name  = "cluster.enabled"
    value = "true"
  }

  set {
    name  = "metrics.enabled"
    value = "true"
  }

  set_string {
    name  = "service.annotations.prometheus\\.io/port"
    value = "9127"
  }
}
```

Ok, that's fine Lucas, but you have basically shown the Helm provider [page](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release)... Am I wasting my time here?

![hold-up](https://i.kym-cdn.com/entries/icons/original/000/029/433/holdup.jpg)

In this post, I want to deal with all this excessive `set {}` parameters in the helm_relase resource. There must be an easier way to manage these variables.

![thinking](https://media.giphy.com/media/lKXEBR8m1jWso/giphy.gif)

Actually, the tutorial has already shown us how! We can use the `values` parameter and pass all our variables in a YAML format.

```terraform
values = [
  "${file("values.yaml")}"
]
```

Instead of using the file function, we can also pass in EOF format:

{% gist https://gist.github.com/souzaxx/c59ad91872ea0e9fef00c72b900e32e3 file=yaml-into-values.tf %}

Lucas...

![am-i-joke-to-you?](https://media.giphy.com/media/cA9nwFy2pVXmU/giphy.gif)

Okay, okay, I'm sorry! I'm getting into the point, wait a little longer!

## templatefile

In terraform, we can create dynamic templates using the `templatefile` [function](https://www.terraform.io/docs/configuration/functions/templatefile.html). Combe this function with the `values` parameter in the helm_release resource and we get a lot of flexibility!

The templatefile function has a slite different syntax than Terraform, but you can easily adapt to it.

An example would be:

backends.tmpl
```terraform
%{ for addr in ip_addrs ~}
backend ${addr}:${port}
%{ endfor ~}
```

And to render this template:

```terraform
templatefile("${path.module}/backends.tmpl", { port = 8080, ip_addrs = ["10.0.0.1", "10.0.0.2"] })
```

Giving the output:

```
backend 10.0.0.1:8080
backend 10.0.0.2:8080
```

And yes, we can also use if statements if you wondered.

We can use all this flexibility right into the values parameter, and here is an example of how to create a dynamic `values.yaml`:

{% gist https://gist.github.com/souzaxx/c59ad91872ea0e9fef00c72b900e32e3 file=aws-vpc-cni.yaml.tpl %}

Templatefile also accept terraform objects making our life easier

{% gist https://gist.github.com/souzaxx/c59ad91872ea0e9fef00c72b900e32e3 file=helm_relase_example.tf %}

If you want to follow the complete example:
{% github souzaxx/Eks-on-Steroids no-readme %}

![thats-all](https://media.giphy.com/media/V2ZrZfHghzSNi/giphy.gif)

In my next post, I'll explain in more detail about this project and how it can help eks clusters running out IPs address.

Thank you for your reading,

Stay safe; stay well.

Lucas.