Getting Started
Prerequisites
| Requirement | Minimum version |
|---|---|
| Terraform | ≥ 1.0.0 |
AWS provider (hashicorp/aws) | ≥ 3.72 |
Helm provider (hashicorp/helm) | ≥ 2.0 |
Kubernetes provider (hashicorp/kubernetes) | ≥ 2.0 |
| An existing EKS cluster | — |
Provider Configuration
The module requires AWS, Helm, and Kubernetes providers configured against your EKS cluster:
# versions.tf
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.72"
}
helm = {
source = "hashicorp/helm"
version = ">= 2.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = ">= 2.0"
}
}
}
# Configure Helm and Kubernetes providers against your EKS cluster
data "aws_eks_cluster" "cluster" {
name = var.cluster_name
}
data "aws_eks_cluster_auth" "cluster" {
name = var.cluster_name
}
provider "helm" {
kubernetes {
host = data.aws_eks_cluster.cluster.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
token = data.aws_eks_cluster_auth.cluster.token
}
}
provider "kubernetes" {
host = data.aws_eks_cluster.cluster.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
token = data.aws_eks_cluster_auth.cluster.token
}
Basic Usage
module "eks_addons" {
source = "git::https://github.com/clouddrove/terraform-aws-eks-addons.git?ref=0.0.7"
# Required inputs
eks_cluster_name = module.eks.cluster_name
data_plane_wait_arn = module.eks.data_plane_wait_arn
# Tags applied to all IRSA IAM resources
tags = {
Environment = "production"
ManagedBy = "terraform"
}
# Enable add-ons
metrics_server = true
cluster_autoscaler = true
aws_load_balancer_controller = true
certification_manager = true
external_secrets = true
external_dns = true
}
data_plane_wait_arn is an output from the CloudDrove EKS module that signals when the node group is ready. If using the AWS EKS module directly, set it to the node group ARN or leave it empty ("").
The Add-on Variable Pattern
Every add-on follows the same three-variable pattern:
# 1. Enable the add-on (bool, default = false)
metrics_server = true
# 2. Override Helm values (any, default = null — uses bundled defaults)
metrics_server_helm_config = {
version = "3.12.0"
values = [file("${path.module}/helm-values/metrics-server.yaml")]
}
# 3. Override the helm_release Terraform resource attributes (any, default = {})
metrics_server_extra_configs = {
timeout = 600
cleanup_on_fail = true
recreate_pods = false
}
When <addon>_helm_config is null, the module uses its own bundled default values. You only need to set it when overriding chart version or values files.
Helm Value Overrides
To pin a chart version or supply a custom values.yaml:
# Pin version only
cluster_autoscaler_helm_config = {
version = "9.29.0"
}
# Full values file override
ingress_nginx_helm_config = {
version = "4.9.0"
values = [
<<-EOT
controller:
replicaCount: 3
service:
type: LoadBalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
defaultBackend:
enabled: true
EOT
]
}
IRSA — IAM Roles for Service Accounts
Add-ons that call AWS APIs (Cluster Autoscaler, External Secrets, FluentBit, etc.) use IRSA — each add-on gets its own IAM role bound to its Kubernetes service account via an OIDC trust policy. The module creates this role automatically.
No extra IAM configuration is needed unless you want a custom policy.
To use a custom IAM policy instead of the built-in one:
# Custom IAM policy for External Secrets (e.g., restrict to specific secret paths)
external_secrets_iampolicy_json_content = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret"]
Resource = "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/*"
},
{
Effect = "Allow"
Action = ["ssm:GetParameter", "ssm:GetParameters"]
Resource = "arn:aws:ssm:us-east-1:123456789012:parameter/prod/*"
}
]
})
Add-ons that support custom IRSA policies: cluster_autoscaler, aws_load_balancer_controller, aws_efs_csi_driver, aws_ebs_csi_driver, karpenter, external_secrets, fluent_bit, velero, external_dns, aws_xray, prometheus_cloudwatch_exporter.
Add-on Dependencies
Some add-ons depend on others being installed first. The module handles this internally, but you must enable the prerequisite when enabling the dependent:
| Add-on | Requires |
|---|---|
kiali_server | istio_ingress = true |
grafana | aws_load_balancer_controller = true |
istio_ingress | aws_load_balancer_controller = true |
actions_runner_controller | certification_manager = true |
GitOps Mode
Set manage_via_gitops = true to skip Helm chart installation — the module will only create IRSA roles and output configuration, leaving the actual chart deployment to Flux or ArgoCD.
module "eks_addons" {
source = "git::https://github.com/clouddrove/terraform-aws-eks-addons.git?ref=0.0.7"
eks_cluster_name = module.eks.cluster_name
data_plane_wait_arn = module.eks.data_plane_wait_arn
manage_via_gitops = true # ← skip Helm installs
# These will create IRSA roles but not install charts
cluster_autoscaler = true
aws_load_balancer_controller = true
external_secrets = true
}
Common Variables
| Variable | Type | Description |
|---|---|---|
eks_cluster_name | string | Name of the EKS cluster |
data_plane_wait_arn | string | ARN to wait on before installing add-ons |
tags | map(string) | Tags applied to all IAM resources |
irsa_iam_role_path | string | IAM role path for IRSA roles (default /) |
irsa_iam_permissions_boundary | string | Permissions boundary ARN for IRSA roles |
manage_via_gitops | bool | Skip Helm installs; create IRSA only |
Outputs
Each installed add-on exposes:
# Namespace the add-on was installed into
output "metrics_server_namespace" {}
# Helm chart version installed
output "metrics_server_chart_version" {}
# Helm chart repository URL
output "metrics_server_repository" {}
IRSA-enabled add-ons additionally expose:
# Kubernetes service account name
output "cluster_autoscaler_service_account" {}
# IAM policy name created for IRSA
output "cluster_autoscaler_iam_policy" {}
Reference: terraform-aws-eks-addons on GitHub →