在Terraform中为资源指定多个标签的简洁语法

111次阅读
没有评论

问题描述

在使用Terraform时,希望能够为一个资源指定多个标签,他目前使用多个tag块来实现:

resource "aws_autoscaling_group" "instance" {
  # ...
  tag {
    key                 = "Name"
    value               = "${var.cluster_prefix}"
    propagate_at_launch = true
  }
  tag {
    key                 = "Owner"
    value               = "${var.tag_Owner}"
    propagate_at_launch = true
  }
  tag {
    key                 = "Project"
    value               = "${var.tag_Project}"
    propagate_at_launch = true
  }
}

尽管这样能够工作,但用户想知道是否有更简洁的语法。同时,他还提到这种方式有些容易出错,因为需要为每个标签都指定propagate_at_launch属性。

解决方案

请注意以下操作可能涉及版本差异或较新特性,请确保你的Terraform版本支持所述功能。

最佳解决方案

对于auto-scaling-group资源来说,目前这已经是最简洁的语法了。
对于大多数其他资源,你可以使用类似如下的tags语法:

tags = {
  Key1 = "value1"
  Key2 = "value2"
}

方案2

从Terraform v0.12开始,支持动态嵌套块(Dynamic Nested Blocks)。下面的示例源自Terraform的博客文章,介绍了这个新特性(见Dynamic Nested Blocks):

locals {
  standard_tags = {
    Name    = var.cluster_prefix
    Owner   = var.tag_Owner
    Project = var.tag_Project
  }
}

resource "aws_autoscaling_group" "example" {
  # ...
  dynamic "tag" {
    for_each = local.standard_tags
    content {
      key                 = tag.key
      value               = tag.value
      propagate_at_launch = true
    }
  }
}

方案3

另一个选择是使用terraform-null-label模块。该模块支持将一个名为tags的变量作为标准Terraform映射传递。模块会生成一个名为tags_as_list_of_maps的输出,其中包含你想要的标签格式。这个模块的另一个好处是可以生成遵循固定约定的一致性资源名称。
例如,你可以这样使用:

module "example" {
  source     = "git::https://github.com/cloudposse/terraform-null-label.git?ref=master"
  namespace  = "eg"
  stage      = "prod"
  name       = "bastion"
  tags       = {
                "BusinessUnit" = "XYZ"
                "Snapshot" = "true"
              }
}

resource "aws_autoscaling_group" "instance" {
  # ...
  name = "${module.example.id}"
  ...
  tags = "${module.example.tags_as_list_of_maps}"
  ...
}

注意:上述示例中,我添加了name字段以展示如何生成唯一的资源名称。

方案4

aws_autoscaling_group现在支持一个标签列表(文档链接)。但这与其他Terraform资源的语法略有不同:

tags = [
  {
    key                 = "explicit1"
    value               = "value1"
    propagate_at_launch = true
  },
  {
    key                 = "explicit2"
    value               = "value2"
    propagate_at_launch = true
  },
]

方案5

如果你希望将相同的常用标签附加到所有资源,并仍然可以为各个资源添加自定义标签,以下是最佳实践:
在Terraform提供者部分添加默认标签配置:

# 配置AWS提供者
provider "aws" {
  region  = var.aws_region
  profile = var.aws_profile
  default_tags {
    tags = {
      environment = var.tag_environment
      created_by  = var.tag_created_by
    }
  }
}

注意:在这个示例中,我添加了name字段以展示如何生成唯一的资源名称。

这样,你可以在资源定义中省略常见的标签,Terraform会自动应用它们。

注意:如果你使用的是旧版本的Terraform,某些解决方案可能不适用或需要相应的修改。请确保你的Terraform版本符合解决方案中所述。

正文完