Экземпляры EC2, воссозданные Terraform при выпуске нового AMI

#amazon-ec2 #terraform #devops #amazon-ami

#amazon-ec2 #terraform #devops #amazon-ami

Вопрос:

Я написал некоторый код Terraform для создания некоторых серверов. Для AMI я использовал модуль данных Terraform, чтобы получить последний идентификатор изображения Ubuntu 16.04 и назначить его экземплярам EC2.

Недавно я хотел добавить еще один экземпляр EC2 в эту среду, однако при запуске terraform plan я вижу, что Terraform пытается удалить существующий экземпляр EC2 и воссоздать их. Причина в том, что был выпущен новый образ Ubuntu, и он пытается удалить старый экземпляр и создать новые с новым идентификатором AMI.

Есть ли шанс, что я смогу решить эту проблему, поскольку я не хочу случайно удалять наши производственные серверы?

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

Комментарии:

1. Какое отношение к этому имеет Ansible? Вы имеете в виду, что написали некоторый код Terraform для создания некоторых серверов?

2. извините, я имел в виду, что код terraform не доступен. Моя ошибка.

Ответ №1:

Хотя приведенный выше ответ помогает, я решил проблему, добавив следующее в ресурс aws_instance.

 lifecycle {
    ignore_changes = ["ami"]
  }
  

Пожалуйста, обратите внимание, что если вы используете модуль AWS, как я, вам нужно будет ввести этот код в main.tf файл в .terraform/modules/.

Комментарии:

1. Ответ @ydaetskcor был полезным и актуальным, но это тот, который я искал. Просто отмечая, что использование кавычек, как указано выше, [”ami”] , теперь устарело, просто поместите [ami]

Ответ №2:

Terraform выполняет именно то, что вы просили. При каждом запуске он ищет самый последний AMI с именем, начинающимся с ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-* , а затем передает этот идентификатор AMI aws_instance ресурсу. Поскольку невозможно изменить идентификатор изображения экземпляра, Terraform правильно определяет, что он должен уничтожить старые экземпляры и перестроить их из нового AMI.

Если вы хотите указать конкретный AMI, вам следует либо заставить источник данных возвращать только один AMI (например, указав метку даты в name фильтре), либо вам следует жестко закодировать идентификатор AMI, который вы хотите использовать.

 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, или используйте most_recent для выбора самого последнего. Если вы хотите сопоставить несколько AMI, используйте вместо этого aws_ami_ids источник данных.

Также обратите внимание, что я добавил owners поле в ваш источник данных. Это теперь требуется начиная с версии 2.0.0 , поскольку в противном случае это было бы очень небезопасно, поскольку ваш источник данных мог возвращать любое общедоступное изображение, использующее эту схему именования.