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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了新AMI发布时,Terraform重新创建EC2实例相关的知识,希望对你有一定的参考价值。

我写了一些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"
  }
}
答案

Terraform完全按照您的要求行事。每次运行时,它会查找名称以ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*开头的最新AMI,然后将该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"]
  }
}

要么:

variable "ami" {
  default = "ami-0727f3c2d4b0226d5"
}

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

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

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

另一答案

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

lifecycle {
    ignore_changes = ["ami"]
  }

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

以上是关于新AMI发布时,Terraform重新创建EC2实例的主要内容,如果未能解决你的问题,请参考以下文章

将安全组附加到我的 aws 实例的 Terraform 问题

使用 Terraform 时从实例获取 EC2 Windows 密码

Terraform - 在每个可用区创建 ec2 实例

如何在使用脚本创建新的 ec2 时避免 terraform 以前的 ec2 被破坏

Terraform 重新部署 EC2 实例

Amazon linux:创建 ami 映像时更改默认 ec2-user