Создание «случайного» экземпляра с помощью Terraform — автоматическое создание допустимых конфигураций

#terraform

#terraform

Вопрос:

Я новичок в Terraform и люблю создавать «случайные» экземпляры. Некоторые настройки, такие как ОС, сценарий установки … останется прежним. В основном изменится регион / zone.

Как я могу это сделать? Похоже, Terraform уже знает, какие комбинации допустимы. Например, с AWS EC2 или lightsail он будет жаловаться, если вы выберете неправильную комбинацию. Я думаю, это уменьшит объем работы. Мне интересно, хотя, действительно ли это для каждого поставщика.

Как вы могли бы автоматически создавать допустимую конфигурацию, меняя только регион или зону при каждом запуске Terraform?

Редактировать: Конфигурация выглядит следующим образом:

     terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

provider "aws" {
#  profile    = "default"
#  region     = "us-west-2"
   accesskey = ...
   secretkey = ...
}

resource "aws_instance" "example" {
  ami           = "ami-830c94e3"
  instance_type = "t2.micro"
}
  

Ответ №1:

Используя AWS в качестве примера, aws_instance имеет два обязательных параметра: ami и instance_type .

Таким образом, чтобы создать экземпляр, вам необходимо предоставить их оба:

 resource "aws_instance" "my" {
  ami           = "ami-02354e95b39ca8dec"
  instance_type = "t2.micro"
}
  

Все остальное будет выведено или установлено в значения по умолчанию. Что касается зон доступности и подсетей, то, если они явно не указаны, они будут выбраны «случайным образом» (AWS решает, как их разместить, так что на самом деле они могут быть все в одном AZ).

Таким образом, чтобы создать 3 экземпляра в разных подсетях и AZS, вы можете сделать просто:

 provider "aws" {
  region     = "us-east-1"
}


data "aws_ami" "al2_ami" {

    most_recent = true

    owners = ["amazon"]

   filter {
     name   = "name"
     values = ["amzn2-ami-hvm*"]
   }
}

resource "aws_instance" "my" {
  count         = 3
  ami           = data.aws_ami.al2_ami.id
  instance_type = "t2.micro"
}
  

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

1. У меня это не работает. Я получаю «Требуется аргумент «region», но определение не найдено «. Возможно, у вас есть регион, определенный в другом месте? Какой-то модуль или профиль по умолчанию? Как насчет других поставщиков, таких как GCE, Digitalocean… ? Есть ли какой-нибудь способ составить список доступных регионов с помощью Terraform?

2. @shittyscripts В aws_instance нет регионов. Регион выбирается на уровне поставщика TF, а не на уровне экземпляра. Я не могу комментировать другие облака.

3. Я добавил свою нерабочую конфигурацию. Можете взглянуть? Это более или менее первая конфигурация, которую я когда-либо настраивал, так что, возможно, в папке Terraform чего-то не хватает?

4. @shittyscripts Да, я обновил ответ. Единственным региональным атрибутом был AMI. Вы можете динамически извлекать действительный идентификатор AMI для данного региона, используя data "aws_ami" , и пример теперь не зависит от региона.

5. извините, что снова беспокою вас. Но я получаю ту же ошибку. Он запрашивает у меня регион. Когда я ввожу это, создается 3 экземпляра в этом регионе. Не могли бы вы добавить немного больше таких вещей, как «поставщик» и т.д., К вашему образцу затрат за вычетом ключей api? Итак, я могу просто попытаться скопировать вставить, а затем «применить terraform». Я

Ответ №2:

Декларативная система, подобная Terraform, к сожалению, не очень дружелюбна к случайности, поскольку она ожидает, что система сойдется к желаемому состоянию, но случайная конфигурация означала бы, что желаемое состояние будет меняться при каждом действии и, следовательно, оно никогда не сойдется. Там, где это возможно, я бы рекомендовал использовать механизмы «рандомизации» или «распространения», встроенные в вашего поставщика облачных услуг, такие как автоматическое масштабирование AWS по нескольким подсетям.

Однако, если быть прагматичным, у Terraform действительно есть random поставщик, который представляет генерацию случайных чисел как забавный вид ресурса Terraform, так что случайные результаты могут сохраняться от одного запуска к следующему, точно так же, как Terraform запоминает идентификатор экземпляра EC2 от одного запуска к следующему.

random_shuffle Ресурс может быть полезен в ситуации типа «выберите любой один (или N) из этих параметров».

На примере случайного выбора регионов AWS и зон доступности первым шагом будет перечисление всех опций, из которых может быть выбран ваш случайный выбор:

 locals {
  possible_regions = toset([
    "us-east-1",
    "us-east-2",
    "us-west-1",
    "us-west-2",
  ])
  possible_availability_zones = tomap({
    us-east-1 = toset(["a", "b", "e"])
    us-east-2 = toset(["a", "c")
    us-west-1 = toset(["a", "b"])
    us-west-2 = toset(["b", "c"])
  })
}
  

Затем вы можете передать эти входные данные в random_shuffle ресурсы, чтобы выбрать, например, один регион, а затем две зоны доступности из этого региона:

 resource "random_shuffle" "region" {
  input        = local.possible_regions
  result_count = 1
}

resource "random_shuffle" "availability_zones" {
  input        = local.possible_availability_zones[local.chosen_region]
  result_count = 2
}

locals {
  local.chosen_region = random_shuffle.region.result[0]
  local.chosen_availability_zones = random_shuffle.availability_zones.result
}
  

Затем вы можете использовать local.chosen_region и local.chosen_availability_zones в другом месте вашей конфигурации.

Однако при случайном выборе регионов, в частности, есть одна важная проблема: провайдеру AWS требуется регион, поскольку каждый регион AWS представляет собой совершенно отдельный набор конечных точек, и поэтому провайдер не сможет успешно настроить себя, если регион неизвестен до этапа применения, как это было бы, если бы вы написали region = local.chosen_region в конфигурации провайдера.

Чтобы обойти это, потребуется использовать -target опцию только для исключительного использования в terraform apply , чтобы направить Terraform сначала сосредоточиться только на генерации случайной области и игнорировать все остальное, пока это не будет выполнено успешно:

 # First apply with just the random region targeted
terraform apply -target=random_shuffle.region

# After that succeeds, run apply again normally to
# create everything else.
terraform apply