The easiest way to define AWS Tag in your Terraform Code.

Bits Lovers
Written by Bits Lovers on
The easiest way to define AWS Tag in your Terraform Code.

AWS tags let you attach custom key-value pairs to just about any resource in your account. If you’ve ever tried managing tags manually across dozens of resources, you know it gets old fast.

I ran into this myself a few years back. I ended up building a Terraform module to handle tag assignment for my team, but it grew into something complicated pretty quickly. Supporting all the edge cases made it a nightmare to maintain.

Then I stumbled on a cleaner approach.

Provider-Level Default Tags

Starting with the AWS Provider v3.38.0 and Terraform 0.12, you can define tags once in the provider block and have them apply to every resource automatically. Here’s how it looks:

provider "aws" {
  default_tags {
    tags = {
      Environment = "Prod"
      Owner       = "Bits Lovers"
      Goal        = "Biggest Blog about DevOps"
    }
  }
}


resource "aws_s3_bucket" "my-bucket" {
  bucket = "my-for-tags-example"
  acl    = "private"

  versioning {
    enabled = true
  }
}

resource "aws_ecs_cluster" "bits-cluster" {
  name = "Bits-Lovers"

  setting {
    name  = "containerInsights"
    value = "enabled"
  }
}

The S3 bucket and ECS cluster both get the Environment, Owner, and Goal tags applied without you having to specify them on each resource. The provider handles it for you.

One thing to note: if you define a tag with the same key at the resource level, the resource-level value takes precedence over the provider default.

Auto Scaling Groups Are the Exception

Auto Scaling Groups don’t work with the default_tags block. AWS handles ASG tags differently at the instance level, so you need a separate approach.

The modern way to handle this is with the aws_default_tags data source. Here’s the pattern:

provider "aws" {
  default_tags {
    tags = {
      Environment = "Prod"
      Owner       = "Bits Lovers"
      Goal        = "Biggest Blog about DevOps"
    }
  }
}

data "aws_default_tags" "example" {}

resource "aws_autoscaling_group" "bits-asg" {
  availability_zones = ["us-east-1a"]
  desired_capacity   = 1
  max_size           = 1
  min_size           = 1

  launch_template {
    id      = aws_launch_template.foobar.id
    version = "$Latest"
  }

  dynamic "tag" {
    for_each = data.aws_default_tags.example.tags
    content {
      key                 = tag.key
      value               = tag.value
      propagate_at_launch = true
    }
  }
}

This pulls in the provider-level defaults and applies them to the ASG with propagate_at_launch = true, so new instances launched by the ASG get the tags too.

Wrapping Up

This isn’t groundbreaking stuff, but it saves real time. Define your tags once at the provider level and you won’t have to remember to add them to every resource. Just remember that ASGs need their own treatment.

Bits Lovers

Bits Lovers

Professional writer and blogger. Focus on Cloud Computing.

Comments

comments powered by Disqus