⭐️terraform init時の挙動

module のダウンロードの流れ

Registry は倉庫ではなく住所案内所。 モジュールの実体は持っておらず、「そのバージョンの実体はここにあるよ」と X-Terraform-Get ヘッダで住所を返すだけ。実体は GitHub などにある。

  1. .tf から module ブロックを集め、source の種類を判別する
  2. registry なら 3 往復して実体の住所を聞き出す(下の具体例)
  3. git / http / S3 は 2 をスキップして直接取得する
  4. .terraform/modules/<key>/ に展開し、modules.json に台帳を書く
  5. 取得した module の中にさらに module があれば 1 に戻って再帰する
  6. 全 module が出揃ってから provider の実行バイナリ(terraform-provider-aws など、AWS の API を実際に叩く本体)を落としに行く。module の中にも required_providers が書けるので、先に集めきらないとどの provider がどのバージョンで要るのか決まらない

具体例: terraform-aws-modules/vpc/aws

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 6.0"
}

この 2 行で実際に起きること(source はホスト省略なので registry.terraform.io):

  1. どこに聞けばいい? → GET https://registry.terraform.io/.well-known/terraform.json

    {"modules.v1":"/v1/modules/","providers.v1":"/v1/providers/"}
    
  2. どのバージョンがある? → GET https://registry.terraform.io/v1/modules/terraform-aws-modules/vpc/aws/versions

    243 個返ってくる。~> 6.0 に合う最新として 6.7.2 を選ぶ

  3. 実体はどこ? → GET https://registry.terraform.io/v1/modules/terraform-aws-modules/vpc/aws/6.7.2/download

    HTTP/2 204
    x-terraform-get: git::https://github.com/terraform-aws-modules/terraform-aws-vpc?ref=cf0e3ca...
    

    本文は空(204)。住所だけ返る。バージョンタグではなくコミット SHA に解決済みなのがポイント

  4. その GitHub リポジトリを取得し、.terraform/modules/vpc/ に置く

provider を「解決する」とは

Terraform 本体は AWS を知らない。 リソースの作り方を知っているのは provider という別の実行バイナリ。「解決」とは、全 module の要求を突き合わせて provider ごとに 1 バージョンを決め、そのバイナリを落とすこと。