AWS上具有terraform的多个可用区域

Col*_*RiX 10 amazon-ec2 amazon-web-services availability-zone terraform

我正在开发的VPC有3个逻辑层:Web,App和DB.对于每个层,每个可用区中都有一个子网.我正在使用的地区共有6个子网.

我正在尝试使用模块和count参数创建EC2实例,但我不知道如何告诉terraform使用App层的两个子网.我有一个额外的约束是使用静态IP地址(或具有确定性私有名称的方式)

我正在玩这个资源

resource "aws_instance" "app_server" {
  ...
  count = "${var.app_servers_count}"

  # Not all at the same time, though!
  availability_zone = ...
  subnet_id = ...
  private_ip = ...
}
Run Code Online (Sandbox Code Playgroud)

到目前为止我尝试/想过的事情:

  • 使用data "aws_subnet" "all_app_subnets" {...}按名称过滤,获取匹配的所有子网并将其用作列表.但aws_subnet不能退回清单;
  • 使用data "aws_availability_zones" {...}查找所有的区域.但我仍然有分配正确子网的问题;
  • 使用data "aws_subnet_ids" {...}看起来是最好的选择.但显然它没有匹配网络名称的过滤选项
  • 将子网ID作为字符串列表传递给模块.但我不想硬编码ID,它不是自动化;
  • 将子网硬编码为data "aws_subnet" "app_subnet_1" {...},data "aws_subnet" "app_subnet_2" {...}但是我必须为每个我不喜欢的子网使用单独的变量集;
  • 获取每个子网的信息,如上所述,然后创建一个map以列表形式访问它.但是在变量定义中使用插值是不可能的;
  • 不使用模块并为每个环境硬编码每个实例.嗯......真的吗?

我真的没想到了.似乎没有人必须在特定的子网中部署实例并保持良好的程度.我只看到未指定子网的示例或人们只使用默认值的示例.这真的很不寻常吗?

在此先感谢大家.

Tom*_*ime 10

可以使用模数在多个区域中均匀分布实例。

variable "zone" {
  description = "for single zone deployment"
  default = "europe-west4-b"
}

variable "zones" {
  description = "for multi zone deployment"
  default = ["europe-west4-b", "europe-west4-c"]
}

resource "google_compute_instance" "default" {
  count = "${var.role.count}"
  ...
  zone = "${var.zone != "" ? var.zone: var.zones[ count.index % length(var.zones) ]}"
  ...
}
Run Code Online (Sandbox Code Playgroud)

这种分布机制允许跨区域均匀分布节点。
例如 zone = [A,B] - instance-1 将在 A 中,instance-2 将在 B 中,instance-3 将再次在 A 中。
通过将区域 C 添加到区域会将实例 3 转移到 C。


小智 8

如果您的实例多于子网,资源中的计数索引将引发错误。使用 Terraform 中的元素插值

element(list, index) - 返回列表中给定索引处的单个元素。如果索引大于元素数量,该函数将使用标准 mod 算法换行。此函数仅适用于平面列表。

subnet_id = "${element(data.aws_subnet_ids.app_tier_ids.ids, count.index)}"
Run Code Online (Sandbox Code Playgroud)


Col*_*RiX 5

最后,我弄清楚了如何使用data "aws_subnet_ids" {...},更重要的是理解terraform在使用时会浪费资源,这是如何做到的count

variable "target_vpc" {}
variable "app_server_count" {}
variable "app_server_ip_start" {}

# Discover VPC
data "aws_vpc" "target_vpc" {
  filter = {
    name = "tag:Name"
    values = ["${var.target_vpc}"]
  }
}

# Discover subnet IDs. This requires the subnetworks to be tagged with Tier = "AppTier"
data "aws_subnet_ids" "app_tier_ids" {
  vpc_id = "${data.aws_vpc.target_vpc.id}"
  tags {
    Tier = "AppTier"
  }
}

# Discover subnets and create a list, one for each found ID
data "aws_subnet" "app_tier" {
  count = "${length(data.aws_subnet_ids.app_tier_ids.ids)}"
  id = "${data.aws_subnet_ids.app_tier_ids.ids[count.index]}"
}

resource "aws_instance" "app_server" {
  ...

  # Create N instances
  count = "${var.app_server_count}"

  # Use the "count.index" subnet
  subnet_id = "${data.aws_subnet_ids.app_tier_ids.ids[count.index]}"

  # Create an IP address using the CIDR of the subnet
  private_ip = "${cidrhost(element(data.aws_subnet.app_tier.*.cidr_block, count.index), var.app_server_ip_start + count.index)}"

  ...
}
Run Code Online (Sandbox Code Playgroud)