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

时间:2019-04-23 10:57:20

标签: amazon-ec2 terraform devops 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"
  }
}

2 个答案:

答案 0 :(得分:2)

Terraform is doing exactly as you asked it to do. Each time it runs it looks for the most recent AMI with a name beginning with ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-* and then passes that AMI ID to the aws_instance resource. As it's not possibly to modify the image ID of an instance, Terraform correctly determines it must destroy the old instances and rebuild them from the new AMI.

If you want to specify a specific AMI then you should either make the data source only return a single AMI (eg by specifying the date stamp in the name filter) or you should hardcode the AMI ID you want to use.

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"]
  }
}

or:

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

If you were to remove the most_recent = true parameter then instead your data source would find multiple images that match those criteria and then fail as the aws_ami data source can only return a single AMI:

NOTE: If more or less than a single match is returned by the search, Terraform will fail. Ensure that your search is specific enough to return a single AMI ID only, or use most_recent to choose the most recent one. If you want to match multiple AMIs, use the aws_ami_ids data source instead.

Also note that I added the owners field to your data source. This is now required since version 2.0.0 because otherwise this was very insecure as your data source could return any public image that uses that naming scheme.

答案 1 :(得分:0)

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

lifecycle {
    ignore_changes = ["ami"]
  }

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