DEV Community

Spacelift team for Spacelift

Posted on • Originally published at spacelift.io

How to Use Tags in Terraform?

In this article, we will take a look at how to use tags with Terraform. We will explain what they are and why you might use them with some use case examples before moving on to some practical examples of how to tag resources on AWS. 

What are tags in Terraform?

Tags in Terraform are key-value pairs associated with cloud resources. They allow you to categorize and organize these resources for better management, cost allocation, environment identification (e.g., production, staging, development), and automation. The keys can be anything you choose as long as they don't conflict with any reserved keys from your cloud provider.

For cloud providers like AWS, Azure, and Google Cloud, Terraform leverages these tags to associate metadata with resources such as instances, networks, or databases. The key represents the category (e.g., "Environment"), while the value specifies the detail (e.g., "Production").

What is the difference between tags and tags_all in Terraform?

Tags are implemented differently depending on the cloud provider you're using. However, Terraform itself offers ways to set and manage tags consistently across providers using the tags attribute of a resource.

The tags_all is a read-only attribute that enables you to reference tags from other parts of your code. For example, if you had an Azure vnet called example that you wanted to reference the tags on, you could use azurerm_virtual_network.example.tags_all.

Use cases for tags in Terraform

Tags are often used to apply metadata to resources, making it easier to identify, manage, and track costs. They can help categorize resources by ownership, environment, project, or other criteria.

Organization: Terraform tags help organize and group-specific resources, making it easier to locate them within a large set.

Example tags:

  • env = "production"
  • owner = "team-abc"
  • purpose = "web-server"

Cost management: You can use Terraform tags to identify resources associated with a particular project or cost center.

  • cost_center = "sales"

You also might want to consider tagging resources that have assigned reserved instances.

Automation: Tags can be used to automate deployments or configurations based on specific tags. For example, you might only deploy resources with the tag deploy = "true" during a production rollout. 

You could also use them to enable targeting with configuration management tools such as Chef and Ansible or to denote which DevOps deployment strategy has been used.

  • auto_shutdown = "true"
  • deploy = "true"
  • ansible_managed = "true"
  • deployment = "bluegreen"

Access control: Tags can be used in defining access control policies, ensuring that only authorized users or groups can manage specific resources. 

For example, you could tag resources in the development environment with the key "Environment" and the value "Development." Then, in the AWS IAM console, create a policy that allows the "DevOps" group to access resources with the "Environment" tag set to "Development." 

Note that tag-based access control might not be the most granular approach. It's often best used in conjunction with other IAM roles and permissions.

Disaster recovery and backup: Tags help manage disaster recovery and backup processes.

  • backup = "monthly"

Compliance: You can mark resources that need to comply with specific regulations.

  • gdpr = "true"
  • iso27001 = "true"

How to add tags to Terraform resources?

You can use the tags attribute to specify your map of key-value pairs to use as tags.

  • tags -- (Optional) A mapping of tags to assign to the resource.

Each key in the map represents the tag name, and the corresponding value is the tag content.

Here are the basic steps for adding tags to resources in Terraform:

  1. Check if the resource supports tags - Not all Terraform resources support tags.
  2. Add a tags block
  3. Define the key-value pairs - You can specify multiple tags by defining key-value pairs inside the tags block.

Example: Using tags in Terraform

This code snippet adds a tag to a resource, where the key is Environment and the value is Development.

tags = {
  Environment = "Development"
}
Enter fullscreen mode Exit fullscreen mode

💡 You might also like:

How to add multiple tags to Terraform resources?

To add multiple tags to Terraform resources, you can include multiple key-value pairs inside the tags block. Each tag consists of a unique key and its corresponding value.

For example:

tags = {
  Environment = "Development"
  Owner       = "Luke Skywalker"
  Department  = "Jedi Order"
}
Enter fullscreen mode Exit fullscreen mode

What are Terraform default tags?

Default tags in Terraform refer to tags that are applied to all or most of the resources in your configuration. These can be defined at a higher level (e.g., through variables or modules) to avoid repetition and ensure consistency across resources. You can define default tags either by setting them globally through variables or directly within each resource.

For example, to define tags in the variable defaults:

variable "common_tags" {
  type = map(string)
  default = {
    Environment = "Development"
  }
}

tags = var.common_tags
Enter fullscreen mode Exit fullscreen mode

How to override the default tags?

If you want to override the default tags with custom tags for specific resources, you can do this by explicitly defining the tags argument in the resource definition.

  • Override at the resource level: If default tags are applied via the provider or module, you can add or change specific tags directly within the resource block.
  • Merge default and custom tags: Use Terraform functions like merge() to combine the default tags with custom tags while giving priority to the custom ones.

How to ignore changes to Terraform tags?

If external systems interact with resource tags (e.g., Configuration Management Databases or your cloud adds auto-generated tags for certain resources, such as Azure Databricks), you can configure Terraform to ignore changes to specific tags. This prevents Terraform from showing unexpected changes in your Terraform plan.

To ignore changes to Terraform tags, you can use the lifecycle block in your resource definition, which is the most common approach and works for all Terraform resources. Simply set the value of ignore_changes to "tags" to ignore all tag changes. 

Using ignore_changes can be helpful, but it's essential to understand why tags are being modified externally. Ensure these external modifications are consistent with your infrastructure management practices.

resource "aws_instance" "my_instance" {
  # ... other configuration options

  lifecycle {
    ignore_changes = [tags]
  }
}
Enter fullscreen mode Exit fullscreen mode

Some Terraform providers, like the AWS provider, offer a provider-level configuration option called ignore_tags. This option applies to all resources managed by that provider in your Terraform configuration.

provider "aws" {
  # ... other configuration options

  ignore_tags = [
    "CostCenter",  # Ignore changes to tags with this key
  ]
}
Enter fullscreen mode Exit fullscreen mode

How to merge Terraform tags?

One useful application of the merge function in Terraform is adding additional tags to resources to combine with your default set of tags. The merge() function combines multiple maps (key-value pairs), and tags are typically defined as a map.

In this example, a tag is set as the default in the variable, and the merge function is used to add a name tag using the tags attribute in the resource.

variable "common_tags" {
  type = map(string)
  default = {
    Environment = "Development"
  }
}

resource "aws_instance" "my_instance" {
  # ... other configuration options

  tags = merge(var.common_tags, {
    Name = "My Web Server"
  })
}
Enter fullscreen mode Exit fullscreen mode

Tagging shared resources on AWS

As of version 3.38.0 of the Terraform AWS provider, the Terraform Configuration Language also enables provider-level tagging. Instead of defining tags on each resource, you can set them at the provider level, and they will propagate down to all supported resources automatically (except for scale sets), keeping your code clean and reducing duplication. 

If you want to apply individual tags in addition to the default set, you can still use the AWS tags attribute on the resource in question and these will get added to the set. In the example below, the aws_vpc resource will be assigned all four tags.

provider "aws" {
  # ... other configuration ...
  default_tags {
    tags = {
      Environment = "Development"
      Owner       = "Luke Skywalker"
      Department  = "Jedi Order"
    }
  }
}

resource "aws_vpc" "example" {
# ... other configuration ...
  tags = {
    VNET_Name = "Dagobah system VNET"
  }
}
Enter fullscreen mode Exit fullscreen mode

Best practices for Terraform tags

Defining a tagging strategy at the start of your project deployment is definitely a good idea to avoid any rework.

  • Consistency - Ensure that the same key names are consistently used across different resources for better organization. It's important to find the right balance when determining the level of detail for your tags. While too many tags can be overwhelming, too few can make it difficult to effectively organize and retrieve information.
  • Documentation - Document your tagging strategy and maintain a tagging convention.
  • Automation - Use Terraform modules or scripts to automate tagging and ensure that all resources are tagged correctly.
  • Leverage Terraform default tags - Terraform allows you to define default tags in the AWS provider section. These default tags are automatically applied to all AWS resources created by Terraform. By defining default tags in one code location, you follow the best practice of DRY (Don't Repeat Yourself).

Deploying Terraform resources with Spacelift

Terraform is really powerful, but to achieve an end-to-end secure Gitops approach, you need to use a product that can run your Terraform workflows. Spacelift takes managing Terraform to the next level by giving you access to a powerful CI/CD workflow and unlocking features such as:

  • Policies (based on Open Policy Agent) - You can control how many approvals you need for runs, what kind of resources you can create, and what kind of parameters these resources can have, and you can also control the behavior when a pull request is open or merged.
  • Multi-IaC workflows - Combine Terraform with Kubernetes, Ansible, and other infrastructure-as-code (IaC) tools such as OpenTofu, Pulumi, and CloudFormation,  create dependencies among them, and share outputs
  • Build self-service infrastructure - You can use Blueprints to build self-service infrastructure; simply complete a form to provision infrastructure based on Terraform and other supported tools.
  • Integrations with any third-party tools - You can integrate with your favorite third-party tools and even build policies for them. For example, see how to Integrate security tools in your workflows using Custom Inputs.

Spacelift enables you to create private workers inside your infrastructure, which helps you execute Spacelift-related workflows on your end. For more information on configuring private workers, refer to the documentation.

You can check it for free by creating a trial account or booking a demo with one of our engineers.

Key points

Terraform tags represent key-value pairs assigned to resources to improve resource categorization, cost management, and automation. They are widely used in cloud environments for optimizing infrastructure operations. A well-thought-out tagging strategy forms the backbone of successful cloud governance and resource optimization.

Written by Jack Roper

Top comments (0)