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

Amazon ec2 新AMI发布时Terraform重新创建的EC2实例,amazon-ec2,terraform,devops,amazon-ami,Amazon Ec2,Terraform,Devops,Amazon Ami,我已经编写了一些Terraform代码来创建一些服务器。对于AMI,我使用Terraform数据模块获取最新的Ubuntu 16.04图像ID,并将其分配给EC2实例 最近我想向这个环境添加另一个EC2实例,但是当我运行terraform plan时,我可以看到terraform正在尝试删除现有的EC2实例并重新创建它们。原因是一个新的Ubuntu映像已经发布,它正在尝试删除旧的实例,并使用新的AMI ID创建新的实例 我是否有可能解决这个问题,因为我不想意外删除我们的生产服务器 data "a

我已经编写了一些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\u实例
资源。由于不可能修改实例的映像ID,Terraform正确地确定它必须销毁旧实例并从新AMI重建它们

如果您想要指定一个特定的AMI,那么您应该使数据源只返回一个AMI(例如通过在
名称
过滤器中指定日期戳),或者您应该硬编码您想要使用的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"]
  }
}
或:

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

注意:如果搜索返回的匹配多于或少于一个,Terraform将失败。确保您的搜索足够具体,只返回单个AMI ID,或者使用
most\u recent
选择最新的AMI ID。如果要匹配多个ami,请改用
aws\u ami\u ID
数据源


还要注意,我将
所有者
字段添加到了数据源中。这是因为,否则这是非常不安全的,因为您的数据源可能返回使用该命名方案的任何公共映像。

虽然上面的答案有帮助,但我通过将以下内容添加到aws_实例资源中解决了问题

lifecycle {
    ignore_changes = ["ami"]
  }

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

中的main.tf文件中,Ansible与此有什么关系?你是说你写了一些地形代码来创建一些服务器吗?对不起,我是说地形代码不可解析。我的错误。@ydaetskcor的回答是有用的和相关的,但这就是我一直在寻找的答案。请注意,如上所述使用引号,
[“ami”]
现在已不推荐使用,只需将
[ami]
lifecycle {
    ignore_changes = ["ami"]
  }