【问题标题】:Terraform multiple instance types from count?从计数中构建多个实例类型?
【发布时间】:2021-01-12 02:19:36
【问题描述】:

我想看看是否有什么可以让我部署 3 个不同实例类型的 EC2 实例的方法?显然下面不起作用,但我在网上看不到任何关于执行此操作的最有效方式的内容。

variable "instance_type" {
    type = list 
    default = ["t2.micro", "t2.small", "t2.medium"]
}

resource "aws_instance" "Server1" {
    instance_type = var.instance_type [0,1,2]
    count = 3

【问题讨论】:

  • 什么版本的 Terraform?
  • 这里有很多类似的问题有答案。今天早些时候的一个例子甚至是stackoverflow.com/questions/65664963/ec2-instance-creation。那对你有用吗?如果不是,那么请您编辑您的问题以显示您尝试过的其他事情,然后解释为什么它们不起作用或显示您遇到的任何错误?

标签: terraform


【解决方案1】:

对您已经尝试过的方法的最小更改的答案类似于以下内容,但它有一些注意事项,我将在后面描述。

variable "instance_types" {
  type = list(string)
}

resource "aws_instance" "example" {
  count = length(var.instance_types)

  instance_type = var.instance_types[count.index]
  # etc...
}

上面使用count.indexaws_instance.example 的编号实例与var.instance_types 中的元素索引相关联,得到我认为您正在寻找的结果。

此解决方案的一个重要警告是,就 Terraform 而言,它使 var.instance_type 中元素的索引成为您的实例的唯一标识符。如果你用上面的代码运行terraform plan,那么你会看到 Terraform 计划实例的地址如下:

  • aws_instance.example[0]instance_type = "t2.micro"
  • aws_instance.example[1]instance_type = "t2.small"
  • aws_instance.example[2]instance_type = "t2.medium"

在设计 Terraform 模块时,重要的是要考虑它将如何响应未来的变化,因为您使用 Terraform 描述的基础架构通常会“无限期地”保持运行,我们希望避免在任何可能的情况下替换它。

鉴于此,请考虑如果您在实例类型列表的开始处添加一个新元素会发生什么:

  instance_types = [
    "m3.medium",
    "t2.micro",
    "t2.small",
    "t2.medium",
  ]

如果您再次运行terraform plan,Terraform 将再次将列表元素索引与资源实例标识符相关联,并将制定如下计划:

  • aws_instance.example[0]~ instance_type = "t2.micro" -> "m3.medium"
  • aws_instance.example[1]~ instance_type = "t2.small" -> "t2.micro"
  • aws_instance.example[2]~ instance_type = "t2.medium" -> "t2.small"
  • aws_instance.example[3]+ instance_type = "t2.medium"

在 EC2 实例运行后无法更改其实例类型,因此 AWS 提供商将计划替换三个现有实例以应用此更改。这里的“替换”意味着销毁现有对象并创建一个新对象,因此会丢失这些实例上的任何状态并可能导致停机。


对此问题的一个典型答案是对实例使用有意义的标识符字符串,而不仅仅是列表中的位置。您可以通过将变量更改为映射,其键是有意义的标识符,然后使用 for_each 而不是 count

variable "instance_types" {
  type = map(string)
}

resource "aws_instance" "example" {
  for_each = var.instance_types

  instance_type = each.value
  # etc...
}

在这种情况下,您可以使用映射填充 instance_types 变量,其键是向人类维护人员描述每个实例的用途的名称:

  instance_types = {
    worker   = "t2.micro"
    web      = "t2.small"
    database = "t2.medium"
  }

当您使用 for_each 时,Terraform 使用地图中的键作为实例标识符,因此您的计划现在看起来像这样:

  • aws_instance.example["worker"]instance_type = "t2.micro"
  • aws_instance.example["web"]instance_type = "t2.small"
  • aws_instance.example["database"]instance_type = "t2.medium"

现在,如果您想稍后添加一个新实例,您可以使用新的唯一键向地图添加一个新元素,Terraform 会理解您打算添加一个新实例并保持所有其他实例不变。

【讨论】:

  • 感谢马丁的深入回答。这极大地提高了我对如何以几种不同方式实现这一目标的理解
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2019-05-19
  • 1970-01-01
  • 2014-09-25
  • 1970-01-01
  • 2017-11-24
相关资源
最近更新 更多