何时使用 ebs_block_device?

dur*_*dur 4 terraform terraform-provider-aws

我想使用 Terraform 创建 EC2 实例。该实例应该有一些 EBS。

在文档中我读到 Terraform 提供了两种创建 EBS 的方法:

  • ebs_block_device
  • aws_ebs_volumeaws_volume_attachment

我想知道,我应该什么时候使用ebs_block_device

文档

不幸的是,文档不太清楚(至少对我来说):

  • 什么时候使用ebs_block_device
  • 确切的实际行为如何?

请参阅资源:aws_instance

ebs_block_device- (可选)一个或多个配置块以及附加到实例的附加 EBS 块设备。块设备配置仅适用于资源创建。有关属性和漂移检测的详细信息,请参阅下面的块设备。当将 this 作为属性引用访问时,它是一组对象。

ebs_block_device目前, Terraform 无法自动检测现有资源配置的更改。要管理 EBS 块对实例的更改和附件,请改用aws_ebs_volumeaws_volume_attachment资源。如果您ebs_block_device在 上使用aws_instance,Terraform 将承担对实例的全套非根 EBS 块设备的管理,将其他块设备视为漂移。因此,不能与给定实例的外部和资源ebs_block_device混合。aws_ebs_volumeaws_volume_attachment

研究

我读:

我知道问题与 Terraform 和 Terraform AWS 提供商的不同版本有关,并且一些问题已经修复,但实际的预期行为是什么?

在几乎所有问题中,解决方法/建议是使用aws_ebs_volumewithaws_volume_attachment而不是ebs_block_device

问题

我应该什么时候使用ebs_block_device?此功能的用例是什么?

小智 6

我强烈建议仅使用资源aws_ebs_volume。创建实例时,会自动创建根块。对于额外的 EBS 存储,您将希望 Terraform 独立管理它们。为什么?

基本上,您有 2 个选择来创建具有 1 个额外磁盘的实例:

resource "aws_instance" "instance" {
  ami                  = "ami-xxxx"
  instance_type        = "t4g.micro"
  #... other arguments ...

  ebs_block_device {
    volume_size = 10
    volume_type = "gp3"
    #... other arguments ...
  }
}
Run Code Online (Sandbox Code Playgroud)

或者

resource "aws_instance" "instance" {
  ami                  = "ami-xxxx"
  instance_type        = "t4g.micro"
  #... other arguments ...
}

resource "aws_ebs_volume" "volume" {
  size = 10
  type = "gp3"
}

resource "aws_volume_attachment" "attachment" {
  volume_id   = aws_ebs_volume.volume.id
  instance_id = aws_instance.instance.id
  device_name = "/dev/sdb"
}
Run Code Online (Sandbox Code Playgroud)

第一种方法更紧凑,创建的 Terraform 资源更少并且更terraform import容易。但是如果您需要重新创建实例会发生什么?Terraform 将删除该实例,并使用新卷从头开始重新部署它。如果您使用 false 参数delete_on_termination,卷仍然存在,但它们不会附加到您的实例。

相反,当使用专用资源时,实例重新创建将重新创建附件(因为实例 ID 发生更改),然后将现有卷重新附加到实例,这在 90% 的情况下是我们所需要的。

此外,如果在某些时候您需要在 Terraform 状态下操作卷(terraform state命令),那么在单个资源上执行此操作会容易得多aws_ebs_volume

最后,在您的 Terraform 之旅中的某个时刻,您将希望通过添加循环、变量等来工业化您的代码。一个常见的用例是设置卷的数量变量:您提供卷列表,Terraform 根据此列表创建 1、2 或 10 个卷。为此,您还有 2 个选择:

variable "my_volume" { map(any) }
my_volume = {
  "/dev/sdb": {
    "size": 10
    "type": "gp3"
  }
}

resource "aws_instance" "instance" {
  ami                  = "ami-xxxx"
  instance_type        = "t4g.micro"
  #... other arguments ...

  dynamic "ebs_block_device" {
    for_each = var.my_volumes
    content {
      volume_size = ebs_block_device.value["size"]
      volume_type = ebs_block_device.value["type"]
      #... other arguments ...
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

或者

resource "aws_instance" "instance" {
  ami                  = "ami-xxxx"
  instance_type        = "t4g.micro"
  #... other arguments ...
}

resource "aws_ebs_volume" "volume" {
  for_each = var.
  size = 10
  type = "gp3"
}

resource "aws_volume_attachment" "attachment" {
  volume_id   = aws_ebs_volume.volume.id
  instance_id = aws_instance.instance.id
  device_name = "/dev/sdb"
}
Run Code Online (Sandbox Code Playgroud)