iT邦幫忙

2025 iThome 鐵人賽

DAY 8
0

昨天我們完成了 Remote State 與 Backend 的實戰,讓 Terraform 狀態檔集中存放在 GCS Bucket,團隊成員可以共享狀態檔,避免衝突。今天要更進一步用 Terraform CLI 實際建立一台 GCP VM!

🐈🐈🐈

環境配置

在開始寫 Terraform 配置之前,要先完成以下設定:

  1. 專案設定

    • 確認自己有一個 GCP Project ID,例如 my-demo-project

    • 也可以使用 gcloud 指令檢查專案的 ID

      gcloud config list project
      
  2. 啟用 Compute Engine API

    VM 是依靠 Compute Engine 提供服務,如果 API 沒有啟用,Terraform 就會報錯。

    • 使用 gcloud 指令啟用(當然也可以手動開啟)

      gcloud services enable compute.googleapis.com
      
  3. 建立 Service Account 並下載金鑰

    • 權限建議至少要有:roles/compute.admin
    • 並將下載的 JSON Key 檔放在專案目錄,例如 service-account.json
  4. Terraform 環境確認

    • 確認安裝 Terraform:

      terraform -v
      

專案結構

確認以下這兩隻檔案是一定要存在的:

project/
├── main.tf
├── service-account.json

撰寫 Terraform 配置

再來就到今天的核心步驟,我們要撰寫包含昨天的 Backend 設定與今天的 VM 建立配置內容:

terraform {
  backend "gcs" {
    bucket = "terraform-state-try" # 昨天建立的 GCS bucket
   prefix = "day07"
  }

  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  credentials = file("service-account.json")
  project     = "my-demo-project" # 自己的專案名稱
  region      = "asia-east1"
  zone        = "asia-east1-b"
}

resource "google_compute_instance" "vm_example" {
  name         = "terraform-study-vm"
  machine_type = "e2-micro" # 有免費額度最適合練習

  boot_disk {
    initialize_params {
      image = "ubuntu-os-cloud/ubuntu-2204-lts"
    }
  }

  network_interface {
    network = "default"
    access_config {} # 要記得沒有這行就沒有外部 IP
  }

  tags = ["dev", "ssh"]
}

💡 重點說明

  1. backend "gcs" → 指定 Terraform State 儲存在昨天建立的 GCS bucket。

  2. required_providers → 鎖定 Provider 版本,避免日後版本不相容。

  3. boot_disk → 這是 VM 啟動時會掛載的系統磁碟。

  4. initialize_params:定義開機磁碟初始化的屬性:

    • image:指定作業系統的映像檔。
    • 查詢方法:
    gcloud compute images list
    

    或到 GCP 官方映像清單查找。

  5. network_interface → 定義 VM 網路介面。

    • network = "default" 表示使用 GCP 預設 VPC network(名稱就叫 default,一開始所有專案都會有)。
    • 如果要用自己建立的 VPC,則寫成:network = google_compute_network.my_vpc.name
  6. access_config {} → 在 Terraform 的 VM 配置中,access_config { } 這一段常常會被忽略,但它其實決定了 VM 能不能直接連上網路。

    • 有寫(即使是空的 { })→ 會幫 VM 配一個 外部 IP,你就能直接從自己的電腦 SSH 進去,或讓外部服務連線進來。
    • 沒寫 → VM 只會拿到 內部 IP,只能在 VPC 網路內被存取,外部完全連不到。這種情況下,如果還想要連進去,就必須透過 Bastion host(跳板機) 或是 Cloud IAP(Identity-Aware Proxy) 來進行。

    所以如果你只是想練習或需要快速上線測試,記得一定要加上 access_config { };但如果你的需求是建立一台 private VM,那就可以省略。

  7. tag → 這些標籤有點像「貼紙」,你幫 VM 貼上什麼貼紙,它就會有對應的功能或身份。

    • dev:貼上這張貼紙,就代表這台機器是 開發環境。之後如果要快速區分哪些是測試用、哪些是正式用,就會很好找。
    • ssh:這張貼紙最常見,因為 GCP 的 防火牆規則 可以指定「只開放給有 ssh 貼紙的 VM」。這樣一來,不是每台 VM 都能被隨便 SSH 進來,而是只有符合標籤的 VM 才能!

    標籤的好處是:

    • 控管防火牆:決定哪些機器能對外開放哪些連線。
    • 方便管理:就像在記事本貼標籤一樣,讓你快速分類「這台是 dev」、「這台跑 web」、「這台是資料庫」。
    • 更好擴充:未來要寫自動化腳本、或用監控工具時,標籤就能幫忙過濾。

CLI 操作流程

1. 初始化

terraform init
  • Terraform 會下載 Google Provider
  • 同時檢查 backend 設定,連線到 GCS bucket

2. 檢查計畫

terraform plan
  • 螢幕會顯示 Terraform 打算新增 google_compute_instance.vm_example以及打算刪除哪些資源,這個步驟能避免誤操作。

3. 建立 VM

terraform apply
  • Terraform 會詢問 Do you want to perform these actions?
  • 輸入 yes → 幾分鐘後 VM 建立完成
  • 螢幕輸出會顯示 Apply complete!

4. 驗證一下

前往 [GCP Console → Compute Engine → VM Instances],看到剛剛建立的 VM,那就代表你建立成功了喔!

https://ithelp.ithome.com.tw/upload/images/20250908/20166287pQrIr72Hx4.png

5. 清理資源

為了避免產生額外費用,練習完建議刪掉 VM:

terraform destroy

常見問題

  1. 權限不足

    • 錯誤訊息通常會提到 permission denied
    • 此時就要去確認 Service Account 是否有配置對應的權限。
  2. API 沒有啟用

    • 錯誤訊息會提到 compute.googleapis.com has not been used

    • 這就表示沒有啟用到需要的 API

      gcloud services enable compute.googleapis.com
      
  3. VM 沒有 Public IP

    • 表示你忘了在 network_interface 裡加 access_config {}

總結一下

今天我們完整練習了:

  1. 確認 專案、API、Service Account 前置作業
  2. 撰寫 main.tf,包含 Backend 與 VM 配置
  3. 執行 terraform init → plan → apply 建立 VM
  4. 最後清理資源避免額外費用

這樣,我們就真正完成了 用 Terraform CLI 在 GCP 建立第一台 VM 的實戰了!👍🏻

🐈🐈🐈

明天我們要更進一步探討 Terraform Provider 的深入使用 —— 包含多 Provider 管理、版本鎖定、認證方式,讓你的 Terraform 更加專業化~


上一篇
Day 07 - Remote State 實戰
系列文
30 天 Terraform 學習筆記:從零開始的 IaC 實戰8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言