簡體   English   中英

AWS 上具有 terraform 的多個可用區

[英]Multiple availability zones with terraform on AWS

我正在處理的 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 = ...
}

到目前為止我嘗試過/想到的事情:

  • 使用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以將其作為列表訪問。 但是在變量定義中使用插值是不可能的;
  • 不使用模塊並對每個環境的每個實例進行硬編碼。 嗯……真的嗎?

我真的沒有主意了。 似乎沒有人必須在特定的子網中部署實例並保持良好的抽象程度。 我只看到未指定子網或人們只對所有內容使用默認值的示例。 這真的很不尋常嗎?

在此先感謝大家。

可以使用模數將實例均勻分布在多個區域中。

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

這種分布機制允許跨區域均勻分布節點。
例如 zone = [A,B] - instance-1 將在 A 中,instance-2 將在 B 中,instance-3 將再次在 A 中。
通過將區域 C 添加到區域會將實例 3 轉移到 C。

如果實例多於子網,資源中的計數索引將引發錯誤。 使用 Terraform 的元素插值

element(list, index) - 從給定索引處的列表中返回單個元素。 如果索引大於元素的數量,則此函數將使用標准 mod 算法進行換行。 此功能僅適用於平面列表。

subnet_id = "${element(data.aws_subnet_ids.app_tier_ids.ids, count.index)}"

最后我想出了如何做到這一點,使用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)

  ...
}

我讓 Terraform 通過使用aws_subnet_ids數據源並通過表示層的標記(在我的情況下為公共/私有)過濾來遍歷可用區中的子網。

然后看起來像這樣:

variable "vpc" {}
variable "ami" {}
variable "subnet_tier" {}
variable "instance_count" {}

data "aws_vpc" "selected" {
  tags {
    Name = "${var.vpc}"
  }
}

data "aws_subnet_ids" "selected" {
  vpc_id = "${data.aws_vpc.selected.id}"

  tags {
    Tier = "${var.subnet_tier}"
  }
}

resource "aws_instance" "instance" {
  count         = "${var.instance_count}"
  ami           = "${var.ami}"
  subnet_id     = "${data.aws_subnet_ids.selected.ids[count.index]}"
  instance_type = "${var.instance_type}"
}

這將返回一致的排序順序,但不一定以您賬戶中的 AZ A 開頭。 我懷疑 AWS API 按 AZ 順序返回子網,但按它們自己的內部 id 排序,因為 AZ 按帳戶打亂(大概是為了阻止 AZ A 被淹沒,因為可以預見,人類不擅長將所有東西放在他們可以使用的首位) .

如果出於某種奇怪的原因您特別關心首先將實例放置在 AZ A 中,您將不得不把自己綁在一些可怕的結上,但是這個最小的示例應該至少通過依賴 Terraform 的子網在您擁有子網的 AZ 中輪詢實例超過數組長度時循環返回數組。

對於在 aws_instance 方法中建議 count.index 的每個人來說,這不是最好的,因為如果您的實例多於子網,則會失敗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM