moduleは、複数リソースをグループ化するための入れ物です。
すべてのTerraform設定は少なくとも1個のモジュールで構成されます。このモジュールがrootモジュールと呼ばれています。
※モジュールは一式の.tfファイルが置いているディレクトリとなります。
.tf拡張子のファイルが置かれているディレクトリが一つのモジュールとして認識できます。
Terraformのワークディレクトリがrootモジュールとなります(.tfが配置されている前提)。
rootモジュールは他のモジュールを呼び出すことが可能です。呼び出されているモジュールはchildモジュール(ディレクトリ)となります。
また、同じchildモジュールを何度も呼び出すことが可能です。
モジュールの構成
モジュール推奨構成
モジュールの推奨標準最小構成は以下となります。
.
├── README.md # 説明ドキュメント
├── main.tf # モジュールの呼び出し(rootモジュールのみ)、リソースの定義などメインな内容を書く
├── variables.tf # input変数の定義
├── outputs.tf # output valueの定義
モジュールを外部公開する場合、上記のファイル以外に、LISENCE
ファイルも用意する必要があります。
※.tfファイル1個のみでも動きますが、再利用等を考えて、上記の構成は推奨されています。
main.tf, variables.tf, outputs.tf. These are the recommended filenames for a minimal module, even if they're empty. main.tf should be the primary entrypoint. For a simple module, this may be where all the resources are created. For a complex module, resource creation may be split into multiple files but any nested module calls should be in the main file.
- main.tf、variables.tf、outputs.tfは推奨されるファイルです。空ファイルでも用意してください。
- 複雑な構成のあ場合、リソースの定義を複数のファイルに分けることも可能です。
- main.tfはモジュールの入口ファイル、リソースの定義が複数ファイルであっても、main.tfから呼び出してください。
複雑なモジュール構成
以下が複数モジュールが存在するような複雑な構成例です。
.
├── README.md
├── main.tf
├── variables.tf
├── outputs.tf
├── ...
├── modules/
│ ├── nestedA/
│ │ ├── README.md
│ │ ├── variables.tf
│ │ ├── main.tf
│ │ ├── outputs.tf
│ ├── nestedB/
│ ├── .../
├── examples/
│ ├── exampleA/
│ │ ├── main.tf
│ ├── exampleB/
│ ├── .../
childモジュールは./modules/
の配下に配置します。
また、./examples/
の配下は使用例を置くところです。
モジュールの呼び出し
モジュールの呼び出しは、module
ブロックで行います。
呼び出す時に、モジュールへinput変数(引数)を渡すことも可能です。
例:
# 呼び出されたモジュールはこの.tf内の名前はfoo
module "foo" {
# `source`引数でモジュールを呼び出す。
source = "./sample-module"
# input変数指定:childモジュールのinput変数を指定。
var = "hello world"
}
設定項目(arguments):
source
(必須オプション):childモジュールファイルのソース場所を指定- ソース場所は以下のものを指定可能
- ローカルディレクトリのパス(呼び出し元の相対パス)
- Terraform Registry
- GitHub
- Bitbucket
- Generic Git, Mercurial repositories
- HTTP URLs
- S3 buckets
- GCS buckets
- 文字列で指定する必要がある
- ソース場所は以下のものを指定可能
input変数
(必要な場合):childモジュールのinput変数を指定version
(オプション):childモジュールバージョンの指定providers
(オプション):childモジュールのprovidersを指定- childモジュールは複数のprovidersを使っている可能性があるので、データ形式はmapです。
- proviersブロックは、rootモジュールのみで定義することを推奨します。
count
、for_each
、lifecycle
などの処理部分
注意
moduleブロックを修正するたびに、terraform init
を実行する必要があります。
デフォルトでは、この操作では既にインストールしたproviderをアップグレードすることはありません。アップグレードしたい場合-upgrade
オプションを付けてください。
childモジュールのoutput valueのアクセス
モジュールの呼び出しは関数の呼び出しに似ていて、呼び出し元のモジュールからはchildモジュールのattributes(属性)をアクセスすることはできません。
childモジュールの属性をアクセスする場合、childモジュールのoutput valueを使用する必要があります。
※output valueはchildモジュールのreturn値みたいなイメージ
※root モジュールのoutput valueは出力処理となります
childモジュールのoutput valueの呼び出しはmodule.<モジュール名>.<output名>
でできます。
childモジュールの例
ファイル構成:
├─main.tf # rootモジュールの.tf
├─sample-module
│ └─main.tf # childモジュールの.tf
rootモジュール:
# rootモジュール
provider "google" {
project = "test-project"
region = "asia-northeast1"
zone = "asia-northeast1-a"
}
module "child_module" {
source = "./sample-module"
# input変数
image_name = "centos-cloud/centos-7"
instance_name = "test-instance-01"
}
output "child_output" {
value = module.child_module.test_output # childモジュールのoutput valueのアクセス
sensitive = false
description = "value from child module"
depends_on = []
}
childモジュール:
# childモジュール
# input変数
variable "image_name" {
type = string
default = "debian-cloud/debian-9"
description = "image name"
}
variable "instance_name" {
type = string
default = "terraform-instance"
description = "instance name"
}
# resource
resource "google_compute_instance" "vm_instance" {
name = var.instance_name
machine_type = "f1-micro"
boot_disk {
initialize_params {
image = var.image_name
}
}
network_interface {
network = "default"
access_config {
}
}
}
output "test_output" {
value = google_compute_instance.vm_instance.network_interface[0].network_ip
description = "this is a child module, so it return the value"
}
モジュールバージョン
外部モジュールを使用する際に、モジュールのバージョンを指定することを推奨します。
module "child_module" {
googleのモジュールを呼び出す
source = "terraform-google-modules/project-factory/google"
# モジュールのバージョン指定
version = "~> 8.1"
# ...
}
providerバージョンの制限
各モジュールのproviers制限はterraform
ブロックのrequired_providers
で指定します。
例:
terraform {
required_providers {
google = "~> 1.0" # googleのプラグインバージョン指定
}
}
providerの継承について
rootモジュールのデフォルトのproviderは自動的にchildモジュールに継承されます。
※providerブロックはrootモジュールにのみ記述することを推奨します。
ただ、aliasや複数のprovidersがある場合、明示的にchildモジュールに渡す必要があります。
※moduleブロックに、providersを指定する場合、デフォルトのproviderを上書きすることになります。
provider継承例
rootモジュールで、alias providerを定義します。
provider "google" {
project = "test-project"
region = "asia-northeast1"
zone = "asia-northeast1-a"
}
provider "google" {
alias = "us-google"
project = "test-project"
region = "us-central1"
zone = "us-central1-a"
}
module "child_module" {
source = "./sample-module"
providers = {
google = google.us-google # provider指定。複数providers存在する可能性があるので、object型になる
}
image_name = "centos-cloud/centos-7"
instance_name = "test-instance-01"
}
childモジュール
variable "image_name" {
type = string
default = "debian-cloud/debian-9"
description = "image name"
}
variable "instance_name" {
type = string
default = "terraform-instance"
description = "instance name"
}
resource "google_compute_instance" "vm_instance" {
name = var.instance_name
machine_type = "f1-micro"
boot_disk {
initialize_params {
image = var.image_name
}
}
network_interface {
network = "default"
access_config {
}
}
}
最後に
今回はmoduleについてご紹介しました。
プロ仕様に仕上がりするには絶対必要な知識となります。
ここまで読んでいただいて、お疲れ様でした。
コメント