広告

Terraform-module

GCP

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モジュールのみで定義することを推奨します。
  • countfor_eachlifecycleなどの処理部分

注意

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についてご紹介しました。
プロ仕様に仕上がりするには絶対必要な知識となります。

ここまで読んでいただいて、お疲れ様でした。

コメント

タイトルとURLをコピーしました