当新的AMI发布时,Terraform会重新创建EC2实例。

6
我已编写了一些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"
  }
}

Ansible与此有什么关系?你的意思是你编写了一些Terraform代码来创建一些服务器吗? - ydaetskcoR
抱歉,我是指 Terraform 代码而不是 Ansible。我的错误。 - Asim
2个回答

13
虽然上面的答案有帮助,但我通过添加以下内容到 aws_instance资源中解决了这个问题。
lifecycle {
    ignore_changes = ["ami"]
  }
请注意,如果您像我一样使用AWS模块,您需要将此代码输入到.terraform/modules/主.tf文件中。

3
@ydaetskcor的回答是有帮助且相关的,但这个回答才是我想要的。只是提醒一下,像上面使用引号["ami"]的方式现在已经不再推荐了,可以直接使用[ami] - Marc

5
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数据源只能返回单个AMI:

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

还要注意,我在您的数据源中添加了owners字段。这是现在必需的,因为版本2.0.0,否则这将非常不安全,因为您的数据源可能返回使用该命名方案的任何公共图像。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接