创建一个;“随机”;具有Terraform的实例-自动创建有效配置

创建一个;“随机”;具有Terraform的实例-自动创建有效配置,terraform,Terraform,我不熟悉地形,喜欢创建“随机”实例。 一些设置,如操作系统、安装脚本。。。将保持不变。大部分地区/区域都会发生变化 我该怎么做? Terraform似乎已经知道哪些组合是有效的。例如,对于AWS EC2或lightsail,如果您选择了错误的组合,它会抱怨。我想这会减少工作量。我想知道这是否对每个提供者都有效 在Terraform每次运行时仅更改区域或分区的情况下,如何自动创建有效配置 编辑:配置看起来像: terraform { required_providers { a

我不熟悉地形,喜欢创建“随机”实例。 一些设置,如操作系统、安装脚本。。。将保持不变。大部分地区/区域都会发生变化

我该怎么做? 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"
}
以AWS为例,它有两个必需的参数:
ami
instance\u type

因此,要创建实例,您需要同时提供这两个实例:

resource "aws_instance" "my" {
  ami           = "ami-02354e95b39ca8dec"
  instance_type = "t2.micro"
}
其他所有内容都将被推断或设置为其默认值。就可用性区域和子网而言,如果未明确指定,则将“随机”选择它们(AWS决定如何放置它们,因此,如果事实上它们可以全部放在一个AZ中)

因此,要在不同的子网和AZ中创建3个实例,只需执行以下操作:

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"
}
以AWS为例,它有两个必需的参数:
ami
instance\u type

因此,要创建实例,您需要同时提供这两个实例:

resource "aws_instance" "my" {
  ami           = "ami-02354e95b39ca8dec"
  instance_type = "t2.micro"
}
其他所有内容都将被推断或设置为其默认值。就可用性区域和子网而言,如果未明确指定,则将“随机”选择它们(AWS决定如何放置它们,因此,如果事实上它们可以全部放在一个AZ中)

因此,要在不同的子网和AZ中创建3个实例,只需执行以下操作:

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

不幸的是,像Terraform这样的声明性系统对随机性不是很友好,因为它期望系统收敛到期望的状态,但随机配置意味着期望的状态在每个动作上都会发生变化,因此它永远不会收敛。在可能的情况下,我建议使用云提供商内置的“随机化”或“分布”机制,例如AWS在多个子网上自动缩放

然而,实用的Terraform确实有一个,它将随机数的生成表示为一种有趣的Terraform资源,这样就可以在一次运行到下一次运行时保留随机结果,就像Terraform在一次运行到下一次运行时记住EC2实例的ID一样

对于这种“选择这些选项中的任意一个(或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.selected\u region
local.selected\u availability\u zones

但是,随机选择区域有一个特别重要的问题:AWS提供程序被设计为需要一个区域,因为每个AWS区域都是一组完全不同的端点,因此如果直到应用步骤才知道该区域,则提供程序将无法成功地配置自己,如果您在提供程序配置中写入
region=local.selected\u region
,则会出现这种情况

要解决此问题,需要使用Exception use only
-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

不幸的是,像Terraform这样的声明性系统对随机性不是很友好,因为它期望系统收敛到期望的状态,但随机配置意味着期望的状态在每个动作上都会发生变化,因此它永远不会收敛。在可能的情况下,我建议使用云提供商内置的“随机化”或“分布”机制,例如AWS在多个子网上自动缩放

然而,实用的Terraform确实有一个,它将随机数的生成表示为一种有趣的Terraform资源,这样就可以在一次运行到下一次运行时保留随机结果,就像Terraform在一次运行到下一次运行时记住EC2实例的ID一样

对于这种“选择这些选项中的任意一个(或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.selected\u region
local.selected\u availability\u zones

但是,随机选择区域有一个特别重要的问题:AWS提供程序被设计为需要一个区域,因为每个AWS区域都是一组完全不同的端点,因此如果直到应用步骤才知道该区域,则提供程序将无法成功地配置自己,如果您在提供程序配置中写入
region=local.selected\u region
,则会出现这种情况

要解决此问题,需要使用Exception use only
-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

这对我不起作用。我得到“参数”region是必需的,但没有找到定义。“你可能在别处定义了一个区域吗?”?某些模块或默认配置文件?像GCE、Digitalocean这样的其他供应商呢?有没有办法列出可用区域