Terraform Naming Conventions
Introduction
When working with Terraform to manage infrastructure as code, establishing consistent naming conventions is crucial. Good naming conventions help teams understand resources at a glance, prevent naming conflicts, and make your code more maintainable. This guide will explore best practices for naming your Terraform resources, modules, and files.
Why Naming Conventions Matter
Proper naming conventions in Terraform provide several benefits:
- Readability: Well-named resources make code easier to understand
- Scalability: Consistent naming helps manage resources as your infrastructure grows
- Collaboration: Team members can quickly understand resource purposes
- Troubleshooting: Easier to identify resources when debugging
- Automation: Consistent naming patterns enable better scripting and automation
Basic Naming Convention Principles
1. Consistency
Use a consistent pattern across all resources. Consistency makes your code more predictable and easier to understand.
# Good - Consistent naming pattern
resource "aws_instance" "web_server" {
# ...
}
resource "aws_security_group" "web_server_sg" {
# ...
}
# Bad - Inconsistent naming
resource "aws_instance" "webServer" {
# ...
}
resource "aws_security_group" "sg-for-web" {
# ...
}
2. Descriptiveness
Names should clearly indicate the purpose and type of the resource.
# Good - Descriptive name
resource "aws_s3_bucket" "user_uploads_bucket" {
# ...
}
# Bad - Vague name
resource "aws_s3_bucket" "bucket1" {
# ...
}
3. Use of Delimiters
Choose a consistent delimiter (underscore, hyphen) and stick with it.
# Using underscores
resource "aws_instance" "prod_web_server" {
# ...
}
# Using hyphens
resource "aws_instance" "prod-web-server" {
# ...
}
# Choose one style and be consistent
Naming Conventions for Different Terraform Elements
File and Directory Structure
project-root/
├── main.tf # Main configuration file
├── variables.tf # Input variables
├── outputs.tf # Output values
├── terraform.tfvars # Variable values
├── providers.tf # Provider configurations
└── modules/ # Reusable modules
└── vpc/ # VPC module
├── main.tf
├── variables.tf
└── outputs.tf
Resource Naming
A good resource naming convention follows this pattern:
[prefix]-[environment]-[region]-[purpose]-[resource_type]
Example:
resource "aws_s3_bucket" "acme_prod_us_east_1_logs_bucket" {
bucket = "acme-prod-us-east-1-logs"
# ...
}
Variable Naming
Variables should be named descriptively and use snake_case:
# Good
variable "vpc_cidr_block" {
description = "CIDR block for the VPC"
type = string
default = "10.0.0.0/16"
}
# Bad
variable "cidr" {
description = "CIDR"
type = string
default = "10.0.0.0/16"
}
Module Naming
Module names should be descriptive and indicate their purpose:
module "web_server_cluster" {
source = "./modules/web-server"
# ...
}
Practical Examples
Example 1: AWS Infrastructure
# Define a VPC
resource "aws_vpc" "main_vpc" {
cidr_block = var.vpc_cidr_block
tags = {
Name = "${var.project_name}-${var.environment}-vpc"
Environment = var.environment
}
}
# Define a subnet
resource "aws_subnet" "public_subnet_a" {
vpc_id = aws_vpc.main_vpc.id
cidr_block = var.public_subnet_a_cidr
availability_zone = "${var.region}a"
map_public_ip_on_launch = true
tags = {
Name = "${var.project_name}-${var.environment}-public-subnet-a"
Environment = var.environment
}
}
# Define a security group
resource "aws_security_group" "web_server_sg" {
name = "${var.project_name}-${var.environment}-web-server-sg"
description = "Security group for web servers"
vpc_id = aws_vpc.main_vpc.id
# ...
tags = {
Name = "${var.project_name}-${var.environment}-web-server-sg"
Environment = var.environment
}
}
Example 2: Azure Resource Naming
# Resource group
resource "azurerm_resource_group" "app_rg" {
name = "${var.company_name}-${var.environment}-${var.region}-app-rg"
location = var.region
tags = {
Environment = var.environment
Project = var.project_name
}
}
# Virtual network
resource "azurerm_virtual_network" "app_vnet" {
name = "${var.company_name}-${var.environment}-${var.region}-app-vnet"
location = azurerm_resource_group.app_rg.location
resource_group_name = azurerm_resource_group.app_rg.name
address_space = [var.vnet_address_space]
tags = {
Environment = var.environment
Project = var.project_name
}
}
Advanced Naming Conventions
Using Terraform Locals for Consistent Naming
Use locals
to define naming conventions in one place:
locals {
# Define naming conventions
name_prefix = "${var.project_name}-${var.environment}"
resource_tags = {
Environment = var.environment
Project = var.project_name
ManagedBy = "Terraform"
}
}
# Use the naming convention
resource "aws_s3_bucket" "logs_bucket" {
bucket = "${local.name_prefix}-logs"
tags = merge(
local.resource_tags,
{
Name = "${local.name_prefix}-logs"
}
)
}
resource "aws_instance" "web_server" {
ami = var.ami_id
instance_type = var.instance_type
tags = merge(
local.resource_tags,
{
Name = "${local.name_prefix}-web-server"
}
)
}
Tag Standardization
Define a standard set of tags for all resources:
locals {
common_tags = {
Environment = var.environment
Project = var.project_name
Owner = var.team_name
ManagedBy = "Terraform"
}
}
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = merge(
local.common_tags,
{
Name = "${var.project_name}-${var.environment}-vpc"
}
)
}
Best Practices Visual Representation
Here's a diagram illustrating the relationship between different naming elements:
Common Pitfalls to Avoid
- Inconsistent casing: Mixing camelCase, snake_case, and kebab-case
- Overly abbreviated names: Using abbreviations that aren't widely understood
- Too generic names: Using names that don't convey the purpose
- Too long names: Creating names that are difficult to read or hit length limits
- Hardcoded environment names: Not using variables for environment names
Practical Exercise
Exercise: Refactor Poor Naming Conventions
Look at the following Terraform code with poor naming conventions:
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "Subnet1" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.0.1.0/24"
}
resource "aws_instance" "webserver" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = aws_subnet.Subnet1.id
}
Now, refactor it with better naming conventions:
resource "aws_vpc" "main_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "acme-prod-main-vpc"
}
}
resource "aws_subnet" "public_subnet_a" {
vpc_id = aws_vpc.main_vpc.id
cidr_block = "10.0.1.0/24"
tags = {
Name = "acme-prod-public-subnet-a"
}
}
resource "aws_instance" "web_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet_a.id
tags = {
Name = "acme-prod-web-server"
}
}
Summary
Implementing consistent naming conventions in your Terraform code is essential for maintaining readable, scalable, and manageable infrastructure. Key takeaways include:
- Use consistent patterns and delimiters
- Make names descriptive and purposeful
- Consider using prefixes for environments and resource types
- Utilize
locals
for centralized naming conventions - Standardize tags across resources
- Avoid common pitfalls like inconsistent casing and overly abbreviated names
By following these guidelines, you'll create Terraform code that is easier to understand, maintain, and troubleshoot, especially as your infrastructure grows in complexity.
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)