[英]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" {...}
看起來是最好的選擇。 但顯然它沒有過濾選項來匹配網絡名稱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.