Skip to main content

Module: helm-release

This terraform-aws-helm-release module deploys a Helm chart with an option to create an EKS IAM Role for a Service Account (IRSA).

Usage

This module deploys a Helm chart with an option to create an EKS IAM Role for a Service Account (IRSA). It has many of the same features and limitations of Helm, and uses the Terraform Helm provider, specifically the helm_release resource.

NOTE: This module is just a convenient wrapper, packaging up 3 concepts:

  1. Deploying a Helm Chart to an EKS cluster
  2. Creating a Kubernetes namespace in the EKS cluster
  3. Creating an IAM role for a Kubernetes Service Account (which, in turn, is presumably created by deploying the Helm Chart)

Many issues may arise that are due to limitations of Helm, Kubernetes, EKS, Terraform, or the Terraform providers. Please address issues and complaints to the project that can potentially fix them, which will usually not be this module.

Provider requirements.

This module is unusual in that it requires you to configure 3 separate Terraform providers:

  1. AWS
  2. Helm
  3. Kubernetes

Cloud Posse maintains a provider-helm.tf file "mixin" for use in Cloud Posse components which you can also use as an example of how to configure the Helm and Kubernetes providers in your own component.

Creating a namespace

This module provides 2 options for creating the namespace the chart will be deployed to, for the case where you are deploying the chart into its own namespace that does not already exist.

  1. create_namespace_with_kubernetes will manage the namespace using a Terraform kubernetes_namespace resource. This is the recommended way to create the namespace, because it allows you to annotate (kubernetes_namespace_annotations) and label (kubernetes_namespace_labels) the namespace, and it provides proper sequencing of creation and destruction of deployments, resources, and IAM roles. When the deployment is destroyed with terraform destroy, the namespace will be deleted, too. This will delete everything else in the namespace (but never the Custom Resource Definitions, which themselves are non-namespaced), so if this is not the desired behavior, you should create the namespace in a separate Terraform component.
  2. create_namespace is the obsolete way to create a namespace, by delegating the responsibility to Helm. This is not recommended because it provides no control over the annotations or labels of the namespace, and when the deployment is destroyed with terraform destroy, the namespace will be left behind. This can cause problems with future deployments.

Note: You may have trouble deleting a release from within Terraform if the Kubernetes cluster has been modified outside of this module, for example if the namespace or the cluster itself has been deleted. You can delete the Terraform state if the resources are gone, using terraform state rm or even terraform workspace delete, or you can try using terraform destroy. In some cases, it may be helpful to set var.enabled to false while destroying:

terraform destroy -var enabled=false

For a complete example, see examples/complete.

module "helm_release" {
source = "cloudposse/helm-release/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"

name = "echo"

repository = "https://charts.helm.sh/incubator"
chart = "raw"
chart_version = "0.2.5"

create_namespace = true
kubernetes_namespace = "echo"

atomic = true
cleanup_on_fail = true
timeout = 300
wait = true

# These values will be deep merged
# values = [
# ]

# Enable the IAM role
iam_role_enabled = true

# Add the IAM role using set()
service_account_role_arn_annotation_enabled = true

# Dictates which ServiceAccounts are allowed to assume the IAM Role.
# In this case, only the "echo" ServiceAccount in the "echo" namespace
# will be able to assume the IAM Role created by this module.
service_account_name = "echo"
service_account_namespace = "echo"

# IAM policy statements to add to the IAM role
iam_policy = [{
statements = [{
sid = "ListMyBucket"
effect = "Allow"
actions = ["s3:ListBucket"]
resources = ["arn:aws:s3:::test"]
conditions = []
},
{
sid = "WriteMyBucket"
effect = "Allow"
actions = ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"]
resources = ["arn:aws:s3:::test/*"]
conditions = []
}]
}]
}

Typically, the prefix for the full name of the created IAM role for the service account ends with the name value, supplied either via the name or the context input. If service_account_name is set to something other than *, the service account name is then appended to this prefix. In the case where name and service_account_name are the same, this leads to a repetition, for a name like eg-echo-echo. For this reason, we recommend setting name to "" when it would otherwise be the same as service_account_name:

module "helm_release" {
source = "cloudposse/helm-release/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"

name = ""

create_namespace = true
kubernetes_namespace = "echo"

service_account_name = "echo"
service_account_namespace = "echo"

iam_role_enabled = true

service_account_role_arn_annotation_enabled = true

# ...
}

This will result in an IAM role with a name such as: eg-uw2-dev-echo@echo instead of eg-uw2-dev-echo-echo@echo. Additionally, if var.name is empty, the name used for the Helm Release will be that of var.chart.

Examples

Here is an example of using this module: