Organizing Terraform Variables: Best Practices for Collections, Primitives, and Structural Types

Organizing Terraform Variables: Best Practices for Collections, Primitives, and Structural Types

One of the key features of Terraform is its ability to use variables, which enable you to create parameters of your configurations and increase scalability and version control. As your Terraform configurations grow, it becomes crucial to organize your variables efficiently. In this article, we'll explore best practices for separating variables based on their types, as well as the use of backend and variable backend files.

1. Separating Variables by Type


Terraform supports various types of variables, including collections (lists and maps), primitives (strings, numbers, and booleans), and structural types (objects and tuples). It's recommended to separate these variable types into different files for better organization and scalability over time.

1.1. Collections (Lists and Maps)


Collections are used to represent groups of values. Lists are ordered collections, and then maps are going to be unordered key-value pairs.

Example: variables_collections.tf

# List of EC2 instance types
variable "instance_types" {
  type        = list(string)
  description = "List of EC2 instance types"
  default     = ["t2.micro", "t3.micro", "t3.small"]
}

# Map of environment-specific settings
variable "env_settings" {
  type        = map(string)
  description = "Map of environment-specific settings"
  default = {
    dev  = "non-prod"
    prod = "production"
  }
}

1.2. Primitives (Strings, Numbers, and Booleans)


Primitives are basic data types used to represent single values or specific

Example: variables_primitives.tf

# EC2 instance name prefix
variable "instance_name_prefix" {
  type        = string
  description = "Prefix for EC2 instance names"
  default     = "my-instance"
}

# Number of EC2 instances
variable "instance_count" {
  type        = number
  description = "Number of EC2 instances to create"
  default     = 2
}

# Enable/disable public IP assignment
variable "assign_public_ip" {
  type        = bool
  description = "Assign public IP to EC2 instances"
  default     = true
}

1.3. Structural Types (Objects and Tuples)


Structural types are used to represent complex data structures. Objects are collections of key-value pairs with different types, while tuples are ordered collections of different types.

Example: variables_structural.tf

# EC2 instance configuration
variable "instance_config" {
  type = object({
    ami           = string
    instance_type = string
    root_volume_size = number
    tags = map(string)
  })
  description = "EC2 instance configuration"
  default = {
    ami           = "ami-0c94855ba95c71c99"
    instance_type = "t3.micro"
    root_volume_size = 20
    tags = {
      Environment = "dev"
      Project     = "my-project"
    }
  }
}

2. Backend and Variable Backend Files


Terraform supports remote state management using backends, which allow you to store your state files in a remote location, such as an Amazon S3 bucket, Azure Storage, or HashiCorp Consul. Additionally, you can use variable backend files to store sensitive information, such as access keys or passwords, separately from your main configuration files.

2.1. Backend Configuration


Example: backend.tf

terraform {
  backend "s3" {
    bucket         = "my-terraform-state-bucket"
    key            = "path/to/my/state/file.tfstate"
    region         = "us-west-2"
    dynamodb_table = "my-terraform-locks"
  }
}

2.2. Variable Backend File


Example: backend_vars.tfvars

access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

In this example, the backend_vars.tfvars file stores sensitive information, such as access keys, separately from the main configuration files. You can then reference these variables in your backend configuration using the ${var.variable_name} syntax.


By separating your Terraform variables based on their types and using backend and variable backend files, you can improve the organization, maintainability, and security of your Terraform configurations. This approach promotes code reusability, makes it easier to manage and update variables, and helps keep sensitive information separate from your main configuration files. Remember to follow best practices and adapt these techniques to suit your specific project requirements.

Read more