導入
Terraform モジュールを使用すると、インフラストラクチャの個別のリソースを単一の統合リソースにグループ化できます。これらのリソースは、必要に応じてカスタマイズして再利用できるため、リソース定義を毎回繰り返す必要がなく、複雑な構造を持つ大規模プロジェクトに便利です。定義した入力変数を使用してモジュール インスタンスをカスタマイズし、出力を使用して情報を抽出することもできます。独自のカスタム モジュールを作成するだけでなく、Terraform レジストリで公開されているビルド済みモジュールを使用することもできます。開発者は、作成したモジュールと同様に入力を使用してこれらのモジュールを使用およびカスタマイズできますが、ソース コードはクラウド内外に保存されます。このチュートリアルでは、冗長性を確保するためにロード バランサーの背後で複数の Droplet を起動する Terraform モジュールを作成します。また、Hashicorp 構成言語 (HCL) の for_each および count ループ機能を使用して、複数のカスタマイズされたモジュール インスタンスを同時にデプロイします。.
前提条件
- 個人用DigitalOceanアクセスコード
- Terraform がシステムにインストールされ、DO プロバイダーを使用してプロジェクトがセットアップされます。
- データ型とHCLループの紹介
- Terraform の出力とその用途の紹介
モジュール構造と利点
このセクションでは、モジュールがもたらすメリット、プロジェクト内での一般的な配置場所、そしてモジュールの構造化方法について学習します。カスタム Terraform モジュールは、大規模なプロジェクトでよく使用され、一緒にデプロイされる、接続されたコンポーネントをカプセル化するために作成されます。これらは自己完結型で、必要なリソース、変数、プロバイダーのみがまとめられています。モジュールは通常、プロジェクト ルートの中央フォルダに保存され、各モジュールは独自のサブフォルダに格納されます。モジュール間の明確な分離を維持するには、モジュールを常に単一の目的を持つように設計し、サブモジュールが含まれないようにしてください。単一のリソースをモジュールとしてパッケージ化すると冗長になり、アーキテクチャ全体のシンプルさが徐々に損なわれる可能性があります。小規模な開発およびテスト プロジェクトでは、モジュールを結合しても大きな進展はないため、結合は不要です。また、モジュールには、定義を 1 か所で変更するだけで、それがインフラストラクチャの残りの部分に伝播されるという利点もあります。.
次に、Terraform プロジェクトでモジュールを定義、使用、カスタマイズします。.
モジュールを作成する
このセクションでは、複数のドロップレットとロードバランサをTerraformリソースとして定義し、モジュールにパッケージ化します。また、構成可能なモジュール入力を使用して、作成されたモジュールを構成します。.
モジュールを以下のディレクトリに配置します。 液滴ポンドは、modulesというディレクトリに保存されます。前提条件として作成したterraform-modulesディレクトリにいると仮定し、次のコマンドを実行して両方を同時にインストールします。
mkdir -p modules/droplet-lb-p 引数は、指定されたパス内のすべてのディレクトリを作成するように mkdir に指示します。.
それにアクセスしてください:
cd modules/droplet-lb前のセクションで述べたように、モジュールには使用するリソースと変数が含まれています。Terraform 0.13以降では、使用するプロバイダーの定義もモジュールに含める必要があります。モジュールでは、コードがモジュールであることを示すために特別な設定は必要ありません。これは、TerraformがHCLコードを含むディレクトリ(プロジェクトのルートディレクトリを含む)をすべてモジュールと見なすためです。.
モジュール内で定義された変数は入力として公開され、リソース定義でカスタマイズに使用できます。作成するモジュールには、作成するドロップレットの数とグループ名の2つの入力があります。 変数.tf 変数を保存する場所を作成して開きます。
nano variables.tf次の行を追加します。
variable "droplet_count" {}
variable "group_name" {}ファイルを保存して閉じます。.
Dropletは、以下のファイルで定義します。 液滴.tf 保存します。作成して編集用に開きます。
nano droplets.tf
次の行を追加します。
resource "digitalocean_droplet" "droplets" {
count = var.droplet_count
image = "ubuntu-22-04-x64"
name = "${var.group_name}-${count.index}"
region = "fra1"
size = "s-1vcpu-1gb"
lifecycle {
precondition {
condition = var.droplet_count >= 2
error_message = "At least two droplets must be created."
}
}
}パラメータ カウント作成するリソースのインスタンス数を指定するdroplet_count変数を渡します。この値は、モジュールがメインプロジェクトコードから呼び出された際に決定されます。デプロイされる各ドロップレットの名前はそれぞれ異なり、これは現在のドロップレットのインデックスを指定されたグループ名に追加することで実現されます。ゾーンへのドロップレットのデプロイ fra1 Ubuntu 22.04 が実行されます。.
セクション ライフサイクル 含まれている 前提条件 リソースが実際にデプロイされる前に実行されます。ここでは、少なくとも2つのドロップが作成されることを確認します。ドロップが1つしか作成されないと、ロードバランサーの目的が達成されません。検証の別の例は、k8s-bootstrapperリポジトリにあります。このリポジトリには、Terraformを使用してDigitalOcean Kubernetesクラスターをセットアップするためのテンプレートが含まれています。このリポジトリでは、クラスター内のノード数が範囲内であることを確認するために検証が使用されています。.
完了したら、ファイルを保存して閉じます。.
ドロップレットの定義が完了したら、ロードバランサーの作成に進みます。ソースを以下のファイルで定義します。 ポンド.tf 保存します。以下のコマンドを実行してファイルを作成し、編集用に開きます。
nano lb.tfソース定義を追加します。
resource "digitalocean_loadbalancer" "www-lb" {
name = "lb-${var.group_name}"
region = "fra1"
forwarding_rule {
entry_port = 80
entry_protocol = "http"
target_port = 80
target_protocol = "http"
}
healthcheck {
port = 22
protocol = "tcp"
}
droplet_ids = [
for droplet in digitalocean_droplet.droplets:
droplet.id
]
}ロードバランサは、識別しやすいようにグループ名を名前に含めて定義します。ゾーン内のドロップと一緒に定義します。 fra1 次の 2 つのセクションでは、ターゲットおよび監視ポートとプロトコルを指定します。.
ハイライト表示されているdroplet_idsブロックは、ロードバランサで管理する必要があるドロップレットのIDを取得します。ドロップレットは複数存在し、その数は事前に不明であるため、forループを使用してドロップレットのコレクション(digitalocean_droplet.droplets)をループ処理し、それぞれのIDを取得します。forループを括弧([])で囲むことで、結果のコレクションはリストになります。.
ファイルを保存して閉じます。.
モジュールのドロップレット、ロードバランサ、変数を定義したので、次にプロバイダ要件を定義し、モジュールが使用するプロバイダ(バージョンと場所を含む)を指定する必要があります。Terraform 0.13以降、モジュールは使用するHashicorp以外のプロバイダリソースを明示的に定義する必要があります。これは、モジュールが親プロジェクトからリソースを継承しないためです。.
プロバイダの要件は、次のファイルで定義します。 プロバイダー.tf 保存します。以下のコマンドを実行して編集できるようにします。
nano provider.tfDigitalocean プロバイダーを要求するには、次の行を追加します。
terraform {
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "~> 2.0"
}
}
}完了したら、ファイルを保存して閉じます。モジュール 液滴ポンド プロバイダーへ デジタルオーシャン ニーズ。.
モジュールは、リソースの状態に関する内部情報を抽出するために使用できる出力もサポートしています。ロードバランサーのIPアドレスを表示する出力を定義し、それを「」というファイルに配置します。 出力.tf 保存して編集用に作成します。
nano outputs.tf次の定義を追加します。
output "lb_ip" {
value = digitalocean_loadbalancer.www-lb.ip
}この出力はロードバランサーのIPアドレスを取得します。ファイルを保存して閉じてください。.
モジュール 液滴ポンド これで完全に機能し、デプロイする準備が整いました。プロジェクトのルートに保存するメインコードから呼び出します。まず、ファイルディレクトリをダブルクリックして、メインコードまで移動します。
cd ../..次に、 メイン.tf モジュールを使用する場所を作成し、編集用に開きます。
nano main.tf次の行を追加します。
module "groups" {
source = "./modules/droplet-lb"
droplet_count = 3
group_name = "group1"
}
output "loadbalancer-ip" {
value = module.groups.lb_ip
}この発表では、モジュール 液滴ポンド 指定されたディレクトリにあるソースディレクトリを呼び出します。入力は次のようになります。 滴数 そして グループ名 後でインスタンスを区別できるように、group1 に設定するよう構成します。.
ロードバランサIP出力はモジュール内で定義されているため、プロジェクトをデプロイしても自動的には表示されません。この問題を解決するには、その値(loadbalancer_ip)を取得して別の出力を作成します。.
完了したら、ファイルを保存して閉じます。.
次のコマンドを実行してモジュールを実行します。
terraform init出力は次のようになります。
OutputInitializing modules...
- groups in modules/droplet-lb
Initializing the backend...
Initializing provider plugins...
- Finding digitalocean/digitalocean versions matching "~> 2.0"...
- Installing digitalocean/digitalocean v2.34.1...
- Installed digitalocean/digitalocean v2.34.1 (signed by a HashiCorp partner, key ID F82037E524B9C0E8)
...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.プロジェクトをスケジュールして、実行時に Terraform が実行するアクションを確認できます。
terraform plan -var "do_token=${DO_PAT}"出力は次のようになります。
Output...
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.groups.digitalocean_droplet.droplets[0] will be created
+ resource "digitalocean_droplet" "droplets" {
...
+ name = "group1-0"
...
}
# module.groups.digitalocean_droplet.droplets[1] will be created
+ resource "digitalocean_droplet" "droplets" {
...
+ name = "group1-1"
...
}
# module.groups.digitalocean_droplet.droplets[2] will be created
+ resource "digitalocean_droplet" "droplets" {
...
+ name = "group1-2"
...
}
# module.groups.digitalocean_loadbalancer.www-lb will be created
+ resource "digitalocean_loadbalancer" "www-lb" {
...
+ name = "lb-group1"
...
}
Plan: 4 to add, 0 to change, 0 to destroy.
...この出力は、Terraform が group1-0、group1-1、group1-2 という名前の 3 つのドロップレットを作成し、3 つのドロップレットとの間のトラフィックを処理する group1-lb という名前のロード バランサも作成することを示しています。.
次のコマンドを実行すると、プロジェクトをクラウドにデプロイできます。
terraform apply -var "do_token=${DO_PAT}"プロンプトが表示されたら「yes」と入力します。出力にはすべてのアクションが表示され、ロードバランサーのIPアドレスも表示されます。
Outputmodule.groups.digitalocean_droplet.droplets[1]: Creating...
module.groups.digitalocean_droplet.droplets[0]: Creating...
module.groups.digitalocean_droplet.droplets[2]: Creating...
...
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Outputs:
loadbalancer-ip = ip_address設定可能な数のドロップレットと、それらの受信トラフィックと送信トラフィックを管理するように自動的に設定されるロード バランサを含むモジュールを作成しました。.
デプロイされたリソースの名前を変更する
前のセクションでは、定義したモジュールをデプロイし、Groupという名前を付けました。名前を変更する場合、モジュール呼び出しの名前を変更するだけでは期待どおりの結果は得られません。呼び出しの名前を変更すると、Terraformによってリソースが破棄されて再作成されるため、ダウンタイムが長引く可能性があります。.
例えば、 メイン.tf 次のコマンドを実行して編集用に開きます。
nano main.tf指定に従って、グループ モジュールの名前を group_renamed に変更します。
module "groups_renamed" {
source = "./modules/droplet-lb"
droplet_count = 3
group_name = "group1"
}
output "loadbalancer-ip" {
value = module.groups_renamed.lb_ip
}ファイルを保存して閉じます。プロジェクトを再度初期化します。
terraform initこれでプロジェクトを計画できます。
terraform plan -var "do_token=${DO_PAT}"出力は長くなりますが、次のようになります。
Output...
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
- destroy
Terraform will perform the following actions:
# module.groups.digitalocean_droplet.droplets[0] will be destroyed
...
# module.groups_renamed.digitalocean_droplet.droplets[0] will be created
...Terraformでは、既存のインスタンスを破棄して新しいインスタンスを作成する必要があります。これは破壊的で不必要な処理であり、意図しないクラッシュを引き起こす可能性があります。.
代わりに、 migrated ブロックを使用して、Terraform に古いリソースを新しい名前で移行するように指示することができます。main.tf を開いて編集し、ファイルの末尾に次の行を追加します。
moved {
from = module.groups
to = module.groups_renamed
}完了したら、ファイルを保存して閉じます。.
これでプロジェクトを計画できます。
terraform plan -var "do_token=${DO_PAT}"main.tf 内の移動されたブロックを使用してプログラムすると、Terraform はリソースを再作成するのではなく移動しようとします。
OutputTerraform will perform the following actions:
# module.groups.digitalocean_droplet.droplets[0] has moved to module.groups_renamed.digitalocean_droplet.droplets[0]
...
# module.groups.digitalocean_droplet.droplets[1] has moved to module.groups_renamed.digitalocean_droplet.droplets[1]
...モバイル リソースは Terraform モードでは場所が変更されますが、実際のクラウド リソースは変更、破棄、または再作成されません。.
次のステップで構成を大幅に変更するため、次のコマンドを実行してデプロイされたリソースを更新します。
terraform destroy -var "do_token=${DO_PAT}"尋ねられたとき、 はい と入力します。出力は次のようになります。
Output...
Destroy complete! Resources: 4 destroyed.このセクションでは、Terraformプロジェクト内のリソースを破棄せずに名前を変更しました。次に、for_eachとcountを使用して、同じコードからモジュールの複数のインスタンスをデプロイします。.
複数のモジュールインスタンスのデプロイ
このセクションでは、count と for_each を使用して、droplet-lb モジュールをカスタマイズして複数回デプロイします。.
カウントを使用する
モジュールの複数のインスタンスを同時にデプロイする方法の一つは、各モジュールで自動的に利用可能な count パラメータに数を渡すことです。main.tf を開いて編集します。
nano main.tf既存の出力定義と移動したブロックを削除して、次のように変更します。
module "groups" {
source = "./modules/droplet-lb"
count = 3
droplet_count = 3
group_name = "group1-${count.index}"
}カウントを3に設定すると、Terraformはモジュールを3回デプロイし、それぞれ異なるグループ名でデプロイします。完了したら、ファイルを保存して閉じます。.
次のコマンドを実行してデプロイメントをスケジュールします。
terraform plan -var "do_token=${DO_PAT}"出力は長くなり、次のようになります。
Output...
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.groups[0].digitalocean_droplet.droplets[0] will be created
...
# module.groups[0].digitalocean_droplet.droplets[1] will be created
...
# module.groups[0].digitalocean_droplet.droplets[2] will be created
...
# module.groups[0].digitalocean_loadbalancer.www-lb will be created
...
# module.groups[1].digitalocean_droplet.droplets[0] will be created
...
# module.groups[1].digitalocean_droplet.droplets[1] will be created
...
# module.groups[1].digitalocean_droplet.droplets[2] will be created
...
# module.groups[1].digitalocean_loadbalancer.www-lb will be created
...
# module.groups[2].digitalocean_droplet.droplets[0] will be created
...
# module.groups[2].digitalocean_droplet.droplets[1] will be created
...
# module.groups[2].digitalocean_droplet.droplets[2] will be created
...
# module.groups[2].digitalocean_loadbalancer.www-lb will be created
...
Plan: 12 to add, 0 to change, 0 to destroy.
...Terraform は出力で、3 つのモジュール インスタンスのそれぞれに 3 つの Droplet と、それらに関連付けられたロード バランサがあることを説明します。.
for_eachの使用
より複雑なインスタンスのカスタマイズが必要な場合、またはインスタンスの数がコードの記述時には不明なサードパーティのデータ (多くの場合マップとして提供される) に依存する場合は、モジュールに対して for_each を使用できます。.
次に、グループ名とドロップレットの数を関連付けたマップを定義し、それに基づいてdroplet-lbインスタンスを実装します。以下のコマンドを実行して、main.tfを開いて編集します。
nano main.tfファイルを次のように変更します。
variable "group_counts" {
type = map
default = {
"group1" = 1
"group2" = 3
}
}
module "groups" {
source = "./modules/droplet-lb"
for_each = var.group_counts
droplet_count = each.value
group_name = each.key
}まず、特定のグループに含まれるドロップレットの数を格納する group_counts というマップを定義します。次に、droplet-lb モジュールを呼び出しますが、for_each ループは先ほど定義したマップ var.group_counts に対して実行されるように指定します。droplet_count は、現在のペアの値である each.value を受け取ります。これは現在のグループのドロップレットの数です。group_name はグループ名を受け取ります。.
完了したら、ファイルを保存して閉じます。.
次のコマンドを実行して構成を適用してみてください。
terraform plan -var "do_token=${DO_PAT}"出力には、ドロップレットとロードバランサを使用してこれら 2 つのグループを作成するための Terraform のアクションの詳細が表示されます。
Output...
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.groups["group1"].digitalocean_droplet.droplets[0] will be created
...
# module.groups["group1"].digitalocean_loadbalancer.www-lb will be created
...
# module.groups["group2"].digitalocean_droplet.droplets[0] will be created
...
# module.groups["group2"].digitalocean_droplet.droplets[1] will be created
...
# module.groups["group2"].digitalocean_droplet.droplets[2] will be created
...
# module.groups["group2"].digitalocean_loadbalancer.www-lb will be created
...この時点で、count と for_each を使用して、同じコードからモジュールの複数のカスタマイズされたインスタンスをデプロイしました。.
結果
このチュートリアルでは、Terraformモジュールを作成および実装しました。モジュールを使用して、論理的に関連するリソースをグループ化し、それらをカスタマイズして、中央のコード定義の複数の異なるインスタンスをデプロイしました。また、出力を使用して、モジュール内のリソースのプロパティを表示しました。.









