新 AMI 发布时由 Terraform 重新创建的 EC2 实例

Asi*_*sim 3 amazon-ec2 terraform devops amazon-ami

我编写了一些 Terraform 代码来创建一些服务器。对于 AMI,我使用 Terraform 数据模块获取最新的 Ubuntu 16.04 映像 ID 并将其分配给 EC2 实例。

最近我想向这个环境添加另一个 EC2 实例,但是当我运行时,terraform plan我可以看到 Terraform 正在尝试删除现有的 EC2 实例并重新创建它们。原因是新的 Ubuntu 映像已发布,它正在尝试删除旧实例并使用新的 AMI ID 创建新实例。

由于我不想意外删除我们的生产服务器,我是否有机会解决这个问题?

data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

module "jenkins" {
  source = "terraform-aws-modules/ec2-instance/aws"

  name           = "Jenkins"
  instance_count = 1

  ami                         = "${data.aws_ami.ubuntu.id}"
  instance_type               = "t2.small"
  associate_public_ip_address = true
  disable_api_termination     = true
  key_name                    = "${aws_key_pair.ssh_key.key_name}"
  monitoring                  = false
  vpc_security_group_ids      = "${module.jenkins_http_sg.this_security_group_id}", "${module.jenkins_https_sg.this_security_group_id}", "${module.ssh_sg.this_security_group_id}"]
  subnet_id                   = "${module.vpc.public_subnets[0]}"
  iam_instance_profile        = "${aws_iam_instance_profile.update-dns-profile.name}"

  tags = {
    Terraform       = "true"
  }
}
Run Code Online (Sandbox Code Playgroud)

Asi*_*sim 6

虽然上面的答案有帮助,但我通过将以下内容添加到 aws_instance 资源解决了这个问题。

lifecycle {
    ignore_changes = ["ami"]
  }
Run Code Online (Sandbox Code Playgroud)

请注意,如果您像我一样使用 AWS 模块,则必须将此代码输入到 .terraform/modules/ 中的 main.tf 文件中。

  • @ydaetskcor 的答案很有帮助且相关,但这正是我正在寻找的答案。请注意,使用上面的引号“[”ami”]`现在已被弃用,只需输入“[ami]” (3认同)

yda*_*coR 5

Terraform 正在按照您的要求进行操作。每次运行时,它都会查找名称以 开头的最新 AMI ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*,然后将该 AMI ID 传递给aws_instance资源。由于不可能修改实例的映像 ID,Terraform 正确地确定它必须销毁旧实例并从新 AMI 重建它们。

如果您想要指定特定的 AMI,那么您应该让数据源仅返回单个 AMI(例如,通过在过滤器中指定日期戳name),或者您应该对您想要使用的 AMI ID 进行硬编码。

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-20190403"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}
Run Code Online (Sandbox Code Playgroud)

或者:

variable "ami" {
  default = "ami-0727f3c2d4b0226d5"
}
Run Code Online (Sandbox Code Playgroud)

如果您要删除该most_recent = true参数,那么您的数据源将找到符合这些条件的多个图像,然后失败,因为aws_ami数据源只能返回单个 AMI:

注意:如果搜索返回多于或少于单个匹配项,Terraform 将失败。确保您的搜索足够具体以仅返回单个 AMI ID,或用于most_recent选择最新的一个。如果您想要匹配多个 AMI,请改用aws_ami_ids数据源。

另请注意,我已将该owners字段添加到您的数据源中。从版本开始 ,这是必需的,因为否则这是非常不安全的,因为您的数据源可能会返回使用该命名方案的任何公共图像。2.0.0