【GCP & Terraform】【入門編②】Terraformの依存関係とVPCの構成

# 前回
【GCP & Terraform】【入門編①】terraform使用でのGCP仮想マシン作成
https://qiita.com/SHA_AKA/items/86bf08e9cf35c3b7fd6f

# 今回の目標
1. 構成ファイルmain.tfについて
2. リソースの依存関係について：明示的なと暗黙の依存関係
3. 暗黙の依存関係：VPCの作成とVMの作成
4. 明示的な依存関係：バケットとVMの作成

## 1. 構成ファイルmain.tfについて
前回と同じく、GCPでCloud Shellを起動して、構成ファイルとしてのmain.tfを作成します。
```
touch main.tf
```
main.tf ファイルに次の内容を追加します。
```
terraform {
  required_providers {
    google = {
      source = "hashicorp/google"
    }
  }
}
```
`` terraform {} ``ブロックではTerraform Registry からダウンロードするプロバイダを Terraform に知らせるために必要です。
上記の構成では、google プロバイダのソースが registry.terraform.io/hashicorp/google の短縮形である hashicorp/google として定義されています。
```
provider "google" {
#  version = "3.5.0"
  project = "<PROJECT_ID>"
  region  = "asia-northeast3"
  zone    = "asia-northeast3-c"
}
```
`` <PROJECT_ID> `` はプロジェクト ID におきかえました。
`` region/zone ``も設定できます。
`` version `` 引数は省略可能
（最近asia-northeast1のリソースがよく足りなく、避難のためasia-northeast3に行きました。）
指定したプロバイダ（この場合は google）の構成に使用し、プロバイダは、リソースの作成と管理を担います。
Terraform 構成で複数のプロバイダのリソースを管理する場合は、複数のproviderブロックを指定できます。


## 2. リソースの依存関係について：明示的なと暗黙の依存関係
terraformリソース間の依存関係の有無を自動的に推測できます。暗黙の依存関係は、Terraform に依存関係を認識させる主要な手段であり、可能な限り、これを使用します。
リソース間には、Terraform から「見えない」依存関係が存在する場合があります。明示的な依存関係を作成するには、リソースに depends_on 引数を追加し、依存先となるリソースのリストを指定します。


## 3. 暗黙の依存関係：VPCの作成
main.tf でVPCリソースを追加します。
```
resource "google_compute_network" "vpc_network" {
  name = "terraform-network"
}
```
main.tf に Compute インスタンス リソースを追加します。
```
resource "google_compute_instance" "vm_instance" {
  name         = "terraform-instance"
  machine_type = "f1-micro"
  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-9"
    }
  }
  network_interface {
    network = google_compute_network.vpc_network.self_link
    access_config {
      nat_ip = google_compute_address.vm_static_ip.address
    }
  }
}
```
main.tf で VM インスタンスに静的 IP を割り当てて構成に追加します。
```
resource "google_compute_address" "vm_static_ip" {
  name = "terraform-static-ip"
}
```
Terraform は、この構成を読み取り、次の処理を行います。
1.vm_instance を作成する前に VPC,vm_static_ip を作成するようにする
2.vm_static_ip のプロパティを状態に保存する
3.nat_ip を vm_static_ip.address プロパティの値に設定する

コマンド`` terraform apply ``を実行すると、下記の出力例になっております。
```
...
google_compute_address.vm_static_ip: Creating...
google_compute_network.vpc_network: Creating...
google_compute_address.vm_static_ip: Creation complete after 5s [id=projects/<projectid>/regions/asia-northeast3/addresses/terraform-static-ip]
google_compute_network.vpc_network: Still creating... [10s elapsed]
google_compute_network.vpc_network: Still creating... [20s elapsed]
google_compute_network.vpc_network: Still creating... [30s elapsed]
google_compute_network.vpc_network: Creation complete after 37s [id=projects/<projectid>/global/networks/terraform-network]
google_compute_instance.vm_instance: Creating...
google_compute_instance.vm_instance: Still creating... [10s elapsed]
google_compute_instance.vm_instance: Creation complete after 14s [id=projects/<projectid>/zones/asia-northeast3-c/instances/terraform-instance]
```

## 4. 明示的な依存関係：バケットとVMの作成
例をあげると、インスタンスで実行するアプリケーションで特定の Cloud Storage バケットを使用するとしましょう。
この依存関係がアプリケーション コード内で構成されている場合、Terraform からは見えません。この場合は、depends_on を使用してこの依存関係を明示的に宣言する必要があります。
構成ファイルでは下記のように追加します。
```
# アプリケーションで使用するストレージ バケット用の新しいリソース
resource "google_storage_bucket" "example_bucket" {
  name     = "<UNIQUE-BUCKET-NAME>"
  location = "US"
  website {
    main_page_suffix = "index.html"
    not_found_page   = "404.html"
  }
}
# このバケットを使用する新しいインスタンスを作成する
resource "google_compute_instance" "webapp_instance" {
  # この VM インスタンスの作成は、ストレージ バケットの作成後にのみ行うよう
  # Terraform に指示する
  depends_on = [google_storage_bucket.example_bucket]
  name         = "terraform-instance-2"
  machine_type = "f1-micro"
  boot_disk {
    initialize_params {
      image =  "debian-cloud/debian-9"
    }
  }
  network_interface {
    network = google_compute_network.vpc_network.self_link
    access_config {
    }
  }
}
```
その中、`` depends_on = [google_storage_bucket.example_bucket] ``では明示的な依存関係を示すことです。
コマンド`` terraform apply ``を実行すると、下記の出力例になっております。
```
...
google_storage_bucket.example_bucket: Creating...
google_storage_bucket.example_bucket: Creation complete after 1s [id=shadev202205261433]
google_compute_instance.webapp_instance: Creating...
google_compute_instance.webapp_instance: Still creating... [10s elapsed]
google_compute_instance.webapp_instance: Creation complete after 12s [id=projects/<projectid>/zones/asia-northeast3-c/instances/terraform-instance-2]
```

## リソースの削除および次回
コマンド`` terraform destroy ``を実行すると、今回構成したリソースをすべて削除されます。
次回ではGCP上のTerraformモジュールについて話をしたいと思います。