A module allows you to group resources together and reuse this group later, possibly many times to avoid starting from scratch again and again. Having as much as possible can be a real time saver when writing code and trying to get your cloud infrastructure to work.
We took a look at the most popular Terraform Modules by the number of downloads from the Terraform registry. There are 12 modules for AWS, 5 for Google, and 3 from CloudPosse.
We hope this ranking will help you learn more about some modules you may not already know.
A Terraform module which creates VPC resources on AWS.
Example:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = true
tags = {
Terraform = "true"
Environment = "dev"
}
}
A Terraform Module to define a consistent naming convention by (namespace, tenant, environment, stage, name, attributes).
Example:
module "eg_prod_bastion_label" {
source = "cloudposse/label/null"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
namespace = "eg"
stage = "prod"
name = "bastion"
attributes = ["public"]
delimiter = "-"
tags = {
"BusinessUnit" = "XYZ",
"Snapshot" = "true"
}
}
A Terraform module which creates IAM resources on AWS. This module has two features, one allows you to create cross account access by defining IAM roles and the second one lets you set up individual IAM ressources as shown below :
module "iam_account" {
source = "terraform-aws-modules/iam/aws//modules/iam-account"
account_alias = "awesome-company"
minimum_password_length = 37
require_numbers = false
}
A Terraform module which creates EC2-VPC security groups on AWS.
This module aims to implement combinations of arguments supported by AWS and latest stable version of Terraform:
- IPv4/IPv6 CIDR blocks
- VPC endpoint prefix lists
- Access from source security groups
- Access from self
- Named rules
- Named groups of rules with ingress (inbound) and egress (outbound) ports open for common scenarios
- Conditionally create security group and/or all required security group rules.
You can use two ways to create security groups using this module:
- Specifying predefined rules (HTTP, SSH, etc)
module "web_server_sg" {
source = "terraform-aws-modules/security-group/aws//modules/http-80"
name = "web-server"
description = "Security group for web-server with HTTP ports open within VPC"
vpc_id = "vpc-12345678"
ingress_cidr_blocks = ["10.10.0.0/16"]
}
- Security group with custom rules:
module "vote_service_sg" {
source = "terraform-aws-modules/security-group/aws"
name = "user-service"
description = "Security group for user-service with custom ports open within VPC, and PostgreSQL publicly open"
vpc_id = "vpc-12345678"
ingress_cidr_blocks = ["10.10.0.0/16"]
ingress_rules = ["https-443-tcp"]
ingress_with_cidr_blocks = [
{
from_port = 8080
to_port = 8090
protocol = "tcp"
description = "User-service ports"
cidr_blocks = "10.10.0.0/16"
},
{
rule = "postgresql-tcp"
cidr_blocks = "0.0.0.0/0"
},
]
}
A Terraform module used to create an Elastic Kubernetes (EKS) cluster and associated resources.
Example:
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 18.0"
cluster_name = "my-cluster"
cluster_version = "1.22"
cluster_endpoint_private_access = true
cluster_endpoint_public_access = true
cluster_addons = {
coredns = {
resolve_conflicts = "OVERWRITE"
}
kube-proxy = {}
vpc-cni = {
resolve_conflicts = "OVERWRITE"
}
}
cluster_encryption_config = [{
provider_key_arn = "arn:aws:kms:eu-west-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
resources = ["secrets"]
}]
vpc_id = "vpc-1234556abcdef"
subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"]
# Self Managed Node Group(s)
self_managed_node_group_defaults = {
instance_type = "m6i.large"
update_launch_template_default_version = true
iam_role_additional_policies = [
"arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
]
}
self_managed_node_groups = {
one = {
name = "mixed-1"
max_size = 5
desired_size = 2
use_mixed_instances_policy = true
mixed_instances_policy = {
instances_distribution = {
on_demand_base_capacity = 0
on_demand_percentage_above_base_capacity = 10
spot_allocation_strategy = "capacity-optimized"
}
override = [
{
instance_type = "m5.large"
weighted_capacity = "1"
},
{
instance_type = "m6i.large"
weighted_capacity = "2"
},
]
}
}
}
# EKS Managed Node Group(s)
eks_managed_node_group_defaults = {
disk_size = 50
instance_types = ["m6i.large", "m5.large", "m5n.large", "m5zn.large"]
}
eks_managed_node_groups = {
blue = {}
green = {
min_size = 1
max_size = 10
desired_size = 1
instance_types = ["t3.large"]
capacity_type = "SPOT"
}
}
# Fargate Profile(s)
fargate_profiles = {
default = {
name = "default"
selectors = [
{
namespace = "default"
}
]
}
}
# aws-auth configmap
manage_aws_auth_configmap = true
aws_auth_roles = [
{
rolearn = "arn:aws:iam::66666666666:role/role1"
username = "role1"
groups = ["system:masters"]
},
]
aws_auth_users = [
{
userarn = "arn:aws:iam::66666666666:user/user1"
username = "user1"
groups = ["system:masters"]
},
{
userarn = "arn:aws:iam::66666666666:user/user2"
username = "user2"
groups = ["system:masters"]
},
]
aws_auth_accounts = [
"777777777777",
"888888888888",
]
tags = {
Environment = "dev"
Terraform = "true"
}
}
A Terraform module which creates S3 bucket resources on AWS.
You can use this module to create three types of buckets:
- Private bucket with versioning enabled:
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
bucket = "my-s3-bucket"
acl = "private"
versioning = {
enabled = true
}
}
- Bucket with ELB access log delivery policy attached:
module "s3_bucket_for_logs" {
source = "terraform-aws-modules/s3-bucket/aws"
bucket = "my-s3-bucket-for-logs"
acl = "log-delivery-write"
# Allow deletion of non-empty bucket
force_destroy = true
attach_elb_log_delivery_policy = true
}
- Bucket with ALB/NLB access log delivery policy attached:
module "s3_bucket_for_logs" {
source = "terraform-aws-modules/s3-bucket/aws"
bucket = "my-s3-bucket-for-logs"
acl = "log-delivery-write"
# Allow deletion of non-empty bucket
force_destroy = true
attach_elb_log_delivery_policy = true # Required for ALB logs
attach_lb_log_delivery_policy = true # Required for ALB/NLB logs
}
A Terraform module which takes care of a lot of AWS Lambda/serverless tasks (build dependencies, packages, updates, deployments) in countless combinations.
You can use this module in various ways, but here is the simplest way to use it, using this module to store packages locally:
module "lambda_function" {
source = "terraform-aws-modules/lambda/aws"
function_name = "my-lambda1"
description = "My awesome lambda function"
handler = "index.lambda_handler"
runtime = "python3.8"
source_path = "../src/lambda-function1"
tags = {
Name = "my-lambda1"
}
}
A Terraform module which creates RDS resources on AWS. You can use it to create specifically four RDS ressources: DB instance, DB subnet group, DB parameter group and DB option group.
Example:
module "db" {
source = "terraform-aws-modules/rds/aws"
identifier = "demodb"
engine = "mysql"
engine_version = "5.7.25"
instance_class = "db.t3a.large"
allocated_storage = 5
db_name = "demodb"
username = "user"
port = "3306"
iam_database_authentication_enabled = true
vpc_security_group_ids = ["sg-12345678"]
maintenance_window = "Mon:00:00-Mon:03:00"
backup_window = "03:00-06:00"
# Enhanced Monitoring - see example for details on how to create the role
# by yourself, in case you don't want to create it automatically
monitoring_interval = "30"
monitoring_role_name = "MyRDSMonitoringRole"
create_monitoring_role = true
tags = {
Owner = "user"
Environment = "dev"
}
# DB subnet group
create_db_subnet_group = true
subnet_ids = ["subnet-12345678", "subnet-87654321"]
# DB parameter group
family = "mysql5.7"
# DB option group
major_engine_version = "5.7"
# Database Deletion Protection
deletion_protection = true
parameters = [
{
name = "character_set_client"
value = "utf8mb4"
},
{
name = "character_set_server"
value = "utf8mb4"
}
]
options = [
{
option_name = "MARIADB_AUDIT_PLUGIN"
option_settings = [
{
name = "SERVER_AUDIT_EVENTS"
value = "CONNECT"
},
{
name = "SERVER_AUDIT_FILE_ROTATIONS"
value = "37"
},
]
},
]
}
A Terraform module which allows you to create opinionated Google Cloud Platform projects. You can use it to create projects and configure aspects like Shared VPC connectivity, IAM access, Service Accounts, and API enablement.
Example :
module "project-factory" {
source = "terraform-google-modules/project-factory/google"
version = "~> 10.1"
name = "pf-test-1"
random_project_id = true
org_id = "1234567890"
usage_bucket_name = "pf-test-1-usage-report-bucket"
usage_bucket_prefix = "pf/test/1/integration"
billing_account = "ABCDEF-ABCDEF-ABCDEF"
svpc_host_project_id = "shared_vpc_host_name"
shared_vpc_subnets = [
"projects/base-project-196723/regions/us-east1/subnetworks/default",
"projects/base-project-196723/regions/us-central1/subnetworks/default",
"projects/base-project-196723/regions/us-central1/subnetworks/subnet-1",
]
}
Terraform module to create an AWS Application/Network Load Balancer (ALB/NLB) and associated resources. As the name suggests, you can use this modules to create either an ALB or NLB. However, the ALB modules can be used in three different ways :
- HTTP and HTTPS listeners with default actions
- HTTP to HTTPS redirect and HTTPS cognito authentication
- Cognito Authentication only on certain routes, with redirects for other routes
A Terraform module which makes it easier to non-destructively manage multiple IAM roles for resources on the Google Cloud Platform. You can use this module with a collection of various submodules.
Example:
module "projects_iam_bindings" {
source = "terraform-google-modules/iam/google//modules/projects_iam"
version = "~> 6.4"
projects = ["project-123456", "project-9876543"]
bindings = {
"roles/storage.admin" = [
"group:test_sa_group@lnescidev.com",
"user:someone@google.com",
]
"roles/compute.networkAdmin" = [
"group:test_sa_group@lnescidev.com",
"user:someone@google.com",
]
"roles/compute.imageUser" = [
"user:someone@google.com",
]
}
}
This module for basically allows you to execute gcloud commands within Terraform.
Example:
module "gcloud" {
source = "terraform-google-modules/gcloud/google"
version = "~> 2.0"
platform = "linux"
additional_components = ["kubectl", "beta"]
create_cmd_entrypoint = "gcloud"
create_cmd_body = "version"
destroy_cmd_entrypoint = "gcloud"
destroy_cmd_body = "version"
}
A Terraform module which loads an opinionated "stack" configuration from local or remote YAML sources. It supports deep-merged variables, settings, ENV variables, backend config, and remote state outputs for Terraform and helmfile components.
Example:
module "vars" {
source = "cloudposse/stack-config/yaml//modules/vars"
# version = "x.x.x"
stack_config_local_path = "./stacks"
stack = "my-stack"
component_type = "terraform"
component = "my-vpc"
context = module.this.context
}
module "backend" {
source = "cloudposse/stack-config/yaml//modules/backend"
# version = "x.x.x"
stack_config_local_path = "./stacks"
stack = "my-stack"
component_type = "terraform"
component = "my-vpc"
context = module.this.context
}
module "settings" {
source = "cloudposse/stack-config/yaml//modules/settings"
# version = "x.x.x"
stack_config_local_path = "./stacks"
stack = "my-stack"
component_type = "terraform"
component = "my-vpc"
context = module.this.context
}
module "env" {
source = "cloudposse/stack-config/yaml//modules/env"
# version = "x.x.x"
stack_config_local_path = "./stacks"
stack = "my-stack"
component_type = "terraform"
component = "my-vpc"
context = module.this.context
}
A Terraform module which creates RDS Aurora resources on AWS.
Example
module "cluster" {
source = "terraform-aws-modules/rds-aurora/aws"
name = "test-aurora-db-postgres96"
engine = "aurora-postgresql"
engine_version = "11.12"
instance_class = "db.r6g.large"
instances = {
one = {}
2 = {
instance_class = "db.r6g.2xlarge"
}
}
vpc_id = "vpc-12345678"
subnets = ["subnet-12345678", "subnet-87654321"]
allowed_security_groups = ["sg-12345678"]
allowed_cidr_blocks = ["10.20.0.0/20"]
storage_encrypted = true
apply_immediately = true
monitoring_interval = 10
db_parameter_group_name = "default"
db_cluster_parameter_group_name = "default"
enabled_cloudwatch_logs_exports = ["postgresql"]
tags = {
Environment = "dev"
Terraform = "true"
}
}
A Terraform module which creates and validates ACM certificate. Depending on how you want to validate your ACM certificates, there is four ways you can use this module:
- Usage with Route53 DNS validation (recommended)
- Usage with external DNS validation (e.g. CloudFlare)
- Usage with CloudFront
- Usage with Route53 DNS validation and separate AWS providers
A Terraform module which creates EC2 instance(s) on AWS. Depending on how many EC2 instances you want to create, there is three ways to use this module:
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "~> 3.0"
name = "single-instance"
ami = "ami-ebd02392"
instance_type = "t2.micro"
key_name = "user1"
monitoring = true
vpc_security_group_ids = ["sg-12345678"]
subnet_id = "subnet-eddcdzz4"
tags = {
Terraform = "true"
Environment = "dev"
}
}
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "~> 3.0"
for_each = toset(["one", "two", "three"])
name = "instance-${each.key}"
ami = "ami-ebd02392"
instance_type = "t2.micro"
key_name = "user1"
monitoring = true
vpc_security_group_ids = ["sg-12345678"]
subnet_id = "subnet-eddcdzz4"
tags = {
Terraform = "true"
Environment = "dev"
}
}
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "~> 3.0"
name = "spot-instance"
create_spot_instance = true
spot_price = "0.60"
spot_type = "persistent"
ami = "ami-ebd02392"
instance_type = "t2.micro"
key_name = "user1"
monitoring = true
vpc_security_group_ids = ["sg-12345678"]
subnet_id = "subnet-eddcdzz4"
tags = {
Terraform = "true"
Environment = "dev"
}
}
A Terraform module to generate well-formed JSON documents that are passed to the aws_ecs_task_definition Terraform resource.
Example:
module "container_definition" {
source = "cloudposse/ecs-container-definition/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
container_name = "geodesic"
container_image = "cloudposse/geodesic"
}
A Terraform module that makes it easy to set up a new VPC Network in GCP. Using it, you can create a Google VPC, Subnets within that VPC and secondary range for the subnets.
Example:
module "vpc" {
source = "terraform-google-modules/network/google"
version = "~> 4.0"
project_id = "<PROJECT ID>"
network_name = "example-vpc"
routing_mode = "GLOBAL"
subnets = [
{
subnet_name = "subnet-01"
subnet_ip = "10.10.10.0/24"
subnet_region = "us-west1"
},
{
subnet_name = "subnet-02"
subnet_ip = "10.10.20.0/24"
subnet_region = "us-west1"
subnet_private_access = "true"
subnet_flow_logs = "true"
description = "This subnet has a description"
},
{
subnet_name = "subnet-03"
subnet_ip = "10.10.30.0/24"
subnet_region = "us-west1"
subnet_flow_logs = "true"
subnet_flow_logs_interval = "INTERVAL_10_MIN"
subnet_flow_logs_sampling = 0.7
subnet_flow_logs_metadata = "INCLUDE_ALL_METADATA"
}
]
secondary_ranges = {
subnet-01 = [
{
range_name = "subnet-01-secondary-01"
ip_cidr_range = "192.168.64.0/24"
},
]
subnet-02 = []
}
routes = [
{
name = "egress-internet"
description = "route through IGW to access internet"
destination_range = "0.0.0.0/0"
tags = "egress-inet"
next_hop_internet = "true"
},
{
name = "app-proxy"
description = "route through proxy to reach app"
destination_range = "10.50.10.0/24"
tags = "app-proxy"
next_hop_instance = "app-proxy-instance"
next_hop_instance_zone = "us-west1-a"
},
]
}
A Terraform module for configuring GKE clusters.
Example:
# google_client_config and kubernetes provider must be explicitly specified like the following.
data "google_client_config" "default" {}
provider "kubernetes" {
host = "https://${module.gke.endpoint}"
token = data.google_client_config.default.access_token
cluster_ca_certificate = base64decode(module.gke.ca_certificate)
}
module "gke" {
source = "terraform-google-modules/kubernetes-engine/google"
project_id = "<PROJECT ID>"
name = "gke-test-1"
region = "us-central1"
zones = ["us-central1-a", "us-central1-b", "us-central1-f"]
network = "vpc-01"
subnetwork = "us-central1-01"
ip_range_pods = "us-central1-01-gke-01-pods"
ip_range_services = "us-central1-01-gke-01-services"
http_load_balancing = false
network_policy = false
horizontal_pod_autoscaling = true
filestore_csi_driver = false
node_pools = [
{
name = "default-node-pool"
machine_type = "e2-medium"
node_locations = "us-central1-b,us-central1-c"
min_count = 1
max_count = 100
local_ssd_count = 0
spot = false
disk_size_gb = 100
disk_type = "pd-standard"
image_type = "COS_CONTAINERD"
enable_gcfs = false
enable_gvnic = false
auto_repair = true
auto_upgrade = true
service_account = "project-service-account@<PROJECT ID>.iam.gserviceaccount.com"
preemptible = false
initial_node_count = 80
},
]
node_pools_oauth_scopes = {
all = [
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring",
]
}
node_pools_labels = {
all = {}
default-node-pool = {
default-node-pool = true
}
}
node_pools_metadata = {
all = {}
default-node-pool = {
node-pool-metadata-custom-value = "my-node-pool"
}
}
node_pools_taints = {
all = []
default-node-pool = [
{
key = "default-node-pool"
value = true
effect = "PREFER_NO_SCHEDULE"
},
]
}
node_pools_tags = {
all = []
default-node-pool = [
"default-node-pool",
]
}
}
A Terraform module which creates Auto Scaling resources on AWS
Example:
module "asg" {
source = "terraform-aws-modules/autoscaling/aws"
# Autoscaling group
name = "example-asg"
min_size = 0
max_size = 1
desired_capacity = 1
wait_for_capacity_timeout = 0
health_check_type = "EC2"
vpc_zone_identifier = ["subnet-1235678", "subnet-87654321"]
initial_lifecycle_hooks = [
{
name = "ExampleStartupLifeCycleHook"
default_result = "CONTINUE"
heartbeat_timeout = 60
lifecycle_transition = "autoscaling:EC2_INSTANCE_LAUNCHING"
notification_metadata = jsonencode({ "hello" = "world" })
},
{
name = "ExampleTerminationLifeCycleHook"
default_result = "CONTINUE"
heartbeat_timeout = 180
lifecycle_transition = "autoscaling:EC2_INSTANCE_TERMINATING"
notification_metadata = jsonencode({ "goodbye" = "world" })
}
]
instance_refresh = {
strategy = "Rolling"
preferences = {
checkpoint_delay = 600
checkpoint_percentages = [35, 70, 100]
instance_warmup = 300
min_healthy_percentage = 50
}
triggers = ["tag"]
}
# Launch template
launch_template_name = "example-asg"
launch_template_description = "Launch template example"
update_default_version = true
image_id = "ami-ebd02392"
instance_type = "t3.micro"
ebs_optimized = true
enable_monitoring = true
# IAM role & instance profile
create_iam_instance_profile = true
iam_role_name = "example-asg"
iam_role_path = "/ec2/"
iam_role_description = "IAM role example"
iam_role_tags = {
CustomIamRole = "Yes"
}
iam_role_policies = {
AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
block_device_mappings = [
{
# Root volume
device_name = "/dev/xvda"
no_device = 0
ebs = {
delete_on_termination = true
encrypted = true
volume_size = 20
volume_type = "gp2"
}
}, {
device_name = "/dev/sda1"
no_device = 1
ebs = {
delete_on_termination = true
encrypted = true
volume_size = 30
volume_type = "gp2"
}
}
]
capacity_reservation_specification = {
capacity_reservation_preference = "open"
}
cpu_options = {
core_count = 1
threads_per_core = 1
}
credit_specification = {
cpu_credits = "standard"
}
instance_market_options = {
market_type = "spot"
spot_options = {
block_duration_minutes = 60
}
}
metadata_options = {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 32
}
network_interfaces = [
{
delete_on_termination = true
description = "eth0"
device_index = 0
security_groups = ["sg-12345678"]
},
{
delete_on_termination = true
description = "eth1"
device_index = 1
security_groups = ["sg-12345678"]
}
]
placement = {
availability_zone = "us-west-1b"
}
tag_specifications = [
{
resource_type = "instance"
tags = { WhatAmI = "Instance" }
},
{
resource_type = "volume"
tags = { WhatAmI = "Volume" }
},
{
resource_type = "spot-instances-request"
tags = { WhatAmI = "SpotInstanceRequest" }
}
]
tags = {
Environment = "dev"
Project = "megasecret"
}
}