使用 Terraform,如何回收根 EC2 实例卷?

使用 Terraform,如何回收根 EC2 实例卷?

我想知道是否有人已经解决了使 EC2 根卷持久化的问题,以便可以污染实例资源并重新应用,并且实例将使用该卷而不是 ami 的卷?

我从文档中理解到 aws_ebs_volume 和 aws_ebs_volume_attachment 仅适用于非根卷。

答案1

Terraform 的aws_instance资源需要 AMI,并且根设备始终是从该 AMI 的底层 EBS 快照生成的新卷。据我所知,这是底层 EC2 API 的限制。

如您所见,可以将现有的 EBS 卷附加到正在运行的实例,aws_ebs_volume_attachment但无法将现有的 EBS 卷用作新实例的根文件系统。

关于根卷的官方文档指出我们最接近您想要的是:

  • 关闭旧实例,同时保留其根 EBS 卷。
  • 创建旧根 EBS 卷的快照。
  • 使用创建的快照创建一个新的 AMI。
  • 使用该新 AMI 启动新图像。

这种多步骤流程很难仅使用 Terraform 来协调,因为 Terraform 无法跟踪其在此类流程中的位置。但是,当您需要替换实例时,类似以下的配置将允许您通过一些手动工作流程来实现它:

variable "source_volume_id" {
}

resource "aws_ebs_snapshot" "new" {
  volume_id = "${var.source_volume_id}"
}

resource "aws_ami" "new" {
  name = "from-${aws_ebs_snapshot.new.id}"
  virtualization_type = "hvm"
  root_device_name = "/dev/xvda"

  ebs_block_device {
    device_name = "/dev/xvda"
    snapshot_id = "${aws_ebs_snapshot.new.id}"
    volume_size = "${aws_ebs_snapshot.new_volume_size}"
  }
}

resource "aws_instance" "new" {
  ami = "${aws_ami.new.id}"
  # ...etc...
}

此配置假设您已经手动终止了旧的 EC2 实例并记下了它的根卷 EBS 卷 ID。然后您通过变量传入该卷 ID source_volume_id,它将执行剩余步骤。

每次source_volume_id更改时,Terraform 都应重复此过程,创建新的快照、AMI 和实例。如果您source_volume_id使用最近使用的相同内容再次运行 Terraform,它应该会保持所有内容不变。

这种半手动过程的一个奇怪之处在于,它存在一个先有鸡还是先有蛋的问题,在第一次运行时,您可能还没有一个卷来作为 AMI 的基础。在这种情况下,您必须首先注释掉除aws_instance资源之外的所有内容,硬编码一个 AMI ID 来引导,然后让 Terraform 创建该初始实例。在后续运行中,您可以按照上面描述的过程进行操作。

如上所述,Terraform 目前并不适合解决此类问题。考虑到无论如何都有一些手动步骤,使用更命令式的方法(例如使用您最喜欢的编程语言使用 AWS SDK 之一)编写整个过程的脚本可能会更简单,尽管使用 Terraform 完成部分过程至少可以让您免于跟踪以前使用的快照和 AMI ID 以确保它们被清理的任务。

答案2

你是对的,terraformaws_instance需要 AMI,并且无法从现有 EBS 卷启动实例(可以在源代码资源)。

相关内容