私が取り組んでいるVPCには、Web、アプリ、DBの3つの論理層があります。各層の各アベイラビリティーゾーンには1つのサブネットがあります。使用しているリージョンの合計6つのサブネット。
モジュールとcount
パラメーターを使用してEC2インスタンスを作成しようとしていますが、Teraformにアプリ層の2つのサブネットを使用するように指示する方法がわかりません。私が持っている追加の制約は、静的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
を作成してリストとしてアクセスします。ただし、変数の定義で補間を使用することはできません。私は本当にアイデアを使い果たしました。特定のサブネットワークにインスタンスをデプロイして、ある程度の抽象化を維持する必要がある人はいないようです。サブネットワークが指定されていない場合、または人々がすべてにデフォルト値を使用している場合の例のみが表示されます。これは本当に珍しいものですか?
皆様、ありがとうございました。
最後に、data "aws_subnet_ids" {...}
を使用してその方法を理解し、count
を使用するとterraformがリソースからリストを作成することをさらに理解しました。
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)}"
...
}
Moduloを使用して複数のゾーンにインスタンスを均等に分散することが可能です。
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) ]}"
...
}
この分散メカニズムにより、ゾーン間でノードを均等に分散できます。
例えば。ゾーン= [A、B]-インスタンス1はA、インスタンス2はB、インスタンス3は再びAになります。
ゾーンCをゾーンに追加すると、インスタンス3がCにシフトします。
aws_subnet_ids
データソース を使用し、階層を表すタグ(私の場合はpublic/private)でフィルタリングすることにより、Terraformがアベイラビリティーゾーンのサブネットをループするようにします。
これは、次のようになります。
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順に返しますが、AZがアカウントごとにシャッフルされるため、独自の内部IDによって順序付けられていると思います(おそらく、人間が使用できるすべての場所にすべてのものを配置するのが予測できないため、AZ Aが氾濫するのを防ぐためです) 。
奇妙な理由でインスタンスが最初にAZ Aに配置されることに特に関心がある場合は、恐ろしい結び目で結ぶ必要がありますが、この最小限の例では、少なくともTerraformに依存することにより、サブネットがあるAZを介してインスタンスがラウンドロビン化されるはずです。配列の長さを超えると、配列をループバックします。
サブネットよりもインスタンスが多い場合、リソースのカウントインデックスはエラーをスローします。 Terraformの要素補間を使用する
element(list、index)-指定されたインデックスにあるリストから単一の要素を返します。インデックスが要素の数より大きい場合、この関数は標準のmodアルゴリズムを使用してラップします。この関数はフラットリストでのみ機能します。
subnet_id = "${element(data.aws_subnet_ids.app_tier_ids.ids, count.index)}"