iT邦幫忙

2025 iThome 鐵人賽

DAY 5
1

昨天我們成功在本地建立了第一個 Terraform 專案,不知道大家有沒有注意到專案資料夾中會多出一個檔案 terraform.tfstate。今天就是要深入探討這隻檔案的重要性!

🐈🐈🐈

Part 1: 檢視昨天的成果

我們先來回顧一下昨天練習的操作結果並仔細做個觀察!

1.1 檢查專案資料夹

首先讓我們先回到昨天的 hello-terraform 專案:

cd hello-terraform
ls -la

你應該會看到:

.
├── .gitignore
├── .terraform/                 # Provider 快取資料夾
├── .terraform.lock.hcl         # Provider 版本鎖定檔案
├── hello-terraform.txt         # 我們建立的檔案
├── main.tf                     # Terraform 配置
└── terraform.tfstate           # ← 今天的主角!

1.2 State 檔案

# 可以檢視 state 檔案大小和建立時間
ls -lh terraform.tfstate

# 快速檢視內容
head terraform.tfstate

https://ithelp.ithome.com.tw/upload/images/20250905/201662873cQp2YyWmE.pnghttps://ithelp.ithome.com.tw/upload/images/20250905/20166287HkmGUutDKG.png

這是一個 JSON 檔案,而且包含了許多資訊~


Part 2: State 檔案的本質與作用

接著我們來說說這隻檔案到底有什麼特別的?

2.1 什麼是 Terraform State?

想像一下這個情境:

👨‍💼 老闆:「我們現在有幾台伺服器?」
👩‍💻 你:「讓我用 terraform state list 查一下...」

因為 State 是 Terraform 的「記憶系統」,它會記錄著:

  • 資源清單:我管理了哪些資源?
  • 資源狀態:這些資源目前的配置是什麼?
  • 資源屬性:每個資源的詳細參數值
  • 依賴關係:資源之間的關聯性
  • 元數據:版本、序號、更新時間等

所以在上面的場景中,我們可以查詢 State 來確認目前有哪些資源~

2.2 為什麼需要 State?

Terraform 不同於其他工具的關鍵特色:

# 你寫的配置 (main.tf)
resource "local_file" "hello_world" {
  filename = "hello-terraform.txt"
  content  = "Hello Terraform!"
}

Terraform 會透過 State 檔案知道目前有哪些資源,我們可以想想並比較一下:

沒有 State 會發生什麼?

# 假設沒有 state 檔案
terraform plan
# 結果:Terraform 認為需要建立新檔案(即使檔案已存在)

有了 State 的話:

terraform plan
# 結果:No changes. Infrastructure is up-to-date

有 State 檔案記錄著 Tarreform 才能知道目標資源與實際資源的差異,就不會出現重複創建的問題。


Part 3: State 檔案結構完整解析

接著我們來解剖這隻檔案的內容!

3.1 檢視 State 檔案內容

我們可以用以下三種方式來檢視 State 檔案的內容:

# 方式一:直接查看(內容較多)
cat terraform.tfstate

# 方式二:使用 jq 格式化顯示(如果有安裝)
cat terraform.tfstate | jq '.'

# 方式三:使用 Terraform 原生指令(推薦)
terraform show

3.2 State 檔案頂層結構

輸入指令後會看到類似這樣的內容:

{
  "version": 4,
  "terraform_version": "1.6.0",
  "serial": 1,
  "lineage": "12345678-1234-5678-9abc-123456789abc",
  "outputs": {...},
  "resources": [...],
  "check_results": null
}

這邊幫大家整理出來各欄位的詳細說明:

欄位 說明
version State 檔案格式版本
terraform_version 建立此 state 的 Terraform 版本
serial 狀態序號(每次變更遞增)
lineage State 檔案的唯一識別碼
outputs 輸出值的實際結果
resources 所有受管理資源的詳細資訊

3.3 深入分析 Resources 區塊

前面文章中也提到 Resources 是核心元件我們來看看它在 State 中的樣貌:

{
  "resources": [
    {
      "mode": "managed",
      "type": "local_file",
      "name": "hello_world",
      "provider": "provider[\"registry.terraform.io/hashicorp/local\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "content": "🚀 Hello Terraform!\n\n這是我的第一個...",
            "content_base64sha256": "...",
            "content_base64sha512": "...",
            "content_md5": "...",
            "content_sha1": "...",
            "content_sha256": "...",
            "content_sha512": "...",
            "directory_permission": "0777",
            "file_permission": "0777",
            "filename": "hello-terraform.txt",
            "id": "..."
          },
          "sensitive_attributes": [],
          "private": "..."
        }
      ]
    }
  ]
}

Resource 結構解析:

  • mode: 資源模式
    • managed: 由 Terraform 管理的資源
    • data: Data Source(唯讀資源)
  • type: 資源類型(如 local_fileaws_instance
  • name: 資源名稱(你在 .tf 檔案中定義的)
  • provider: 使用的 Provider
  • instances: 資源實例(支援多實例)
    • attributes: 所有資源屬性的實際值
    • sensitive_attributes: 敏感屬性清單
    • private: Provider 內部使用的私有資料

3.4 Outputs 區塊分析

這裡就比較單純,是用於儲存所有 output 的實際計算結果,會像這樣:

{
  "outputs": {
    "content_length": {
      "value": 120,
      "type": "number"
    },
    "hello_file_path": {
      "value": "/path/to/hello-terraform/hello-terraform.txt",
      "type": "string"
    }
  }
}

Part 4: State 的運作機制

4.1 Terraform 的三方比較

Terraform 在每次 planapply 時都會進行三方比較,這也是我們在前面文章中提到的狀態管理機制!

1. 配置檔案 (main.tf)      ← 你想要的狀態
      ↓
2. State 檔案             ← Terraform 記錄的狀態
      ↓
3. 實際資源                ← 真實世界的狀態

4.2 實際演示三方比較

我們可以在本地做個測試來觀察 State 的變化會更清楚~

測試一:配置與 State 一致

我們先配置與狀態一致的 main.tf

terraform plan
# 結果:No changes. Infrastructure is up-to-date.

測試二:修改配置檔案

再來修改 main.tf 中的 content:

resource "local_file" "hello_world" {
  filename = "hello-terraform.txt"
  content  = "Hello Terraform! 我修改了內容!"  # ← 修改這裡
}
terraform plan

觀察輸出結果

# local_file.hello_world will be updated in-place
  ~ resource "local_file" "hello_world" {
      ~ content = "🚀 Hello Terraform!..." -> "Hello Terraform! 我修改了內容!"
        # (其他屬性保持不變)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

測試三:手動刪除實際檔案

# 刪除實際檔案(但保留 state)
rm hello-terraform.txt

terraform plan

觀察輸出結果

# local_file.hello_world will be created
  + resource "local_file" "hello_world" {
      + content = "Hello Terraform! 我修改了內容!"
      + filename = "hello-terraform.txt"
      # ...
    }

會發現即使我們只是刪除了檔案,Terraform 仍然知道這個資源應該存在!

4.3 State 更新的時機

這邊幫大家整理 State 檔案會在哪些情況更新:

  1. terraform apply - 套用變更後
  2. terraform refresh - 手動同步實際資源狀態
  3. terraform import - 匯入現有資源時
  4. terraform state 指令 - 手動操作 state 時

Part 5: State 管理指令

5.1 基本查詢指令

# 列出所有受管理的資源
terraform state list

# 顯示特定資源的詳細資訊
terraform state show local_file.hello_world

# 查看整個 state 的內容
terraform show

# 以 JSON 格式輸出 state
terraform show -json

5.2 State 同步指令

# 重新整理 state(與實際資源同步)
terraform refresh

# 這等同於
terraform apply -refresh-only

5.3 State 備份與恢復

# Terraform 會自動建立備份
ls -la *.tfstate*
# 你會看到:
# terraform.tfstate
# terraform.tfstate.backup

# 手動建立備份
cp terraform.tfstate "terraform.tfstate.backup.$(date +%Y%m%d_%H%M%S)

Part 6: State 檔案的風險與安全考量

6.1 敏感資訊洩露風險

State 檔案可能會包含敏感資訊,例如:

{
  "attributes": {
    "password": "super_secret_password",
    "api_key": "ak_1234567890abcdef",
    "private_key": "-----BEGIN PRIVATE KEY-----...",
    "database_url": "postgres://user:pass@host:5432/db"
  }
}

6.2 實際安全示例

我們建立一個包含敏感資料的範例試試看:

# 在 main.tf 中新增
variable "secret_message" {
  description = "機密訊息"
  type        = string
  default     = "這是機密資料:password123"
  sensitive   = true  # 標記為敏感
}

resource "local_file" "secret_file" {
  filename = "secret.txt"
  content  = var.secret_message
}

terraform apply

檢查 state 檔案:

https://ithelp.ithome.com.tw/upload/images/20250905/20166287JK96emp9X7.png

大家會發現即使標記為 sensitive,資料仍會以明文儲存在 state 檔案中!

6.3 安全最佳實踐

這邊提供大家安全實踐的方法~

.gitignore 配置

# Terraform 狀態檔案(敏感資料)
*.tfstate
*.tfstate.*

# Terraform 工作目錄
.terraform/
.terraform.lock.hcl

# 執行計畫檔案
*.tfplan

# 變數檔案(可能包含敏感資料)
*.tfvars
terraform.tfvars

# 除了範例檔案
!*.tfvars.example

# 備份檔案
*.backup

# IDE 檔案
.vscode/
.idea/
*.swp
*.swo
*~

# macOS 檔案
.DS_Store

檔案權限設定

# 限制 state 檔案的讀取權限
chmod 600 terraform.tfstate
chmod 600 terraform.tfstate.backup

除了上面兩個方式外也可以定期清理敏感檔案~

🐈🐈🐈

今天探討了 State 檔案的重要,不過我們現在都還是個人操作,但當需要團隊協作的時候,這些狀態檔案又該怎麼運作呢?

我們可以先想像一下:

👨‍💻 工程師 A 正在修改網路設定
👩‍💻 工程師 B 同時在調整伺服器配置

然後兩人同時執行 terraform apply …結果呢?狀態檔案會衝突,基礎設施也可能損毀!

那該怎麼避免這可怕問題發生呢?這就是我們明天要探討的 —— Terraform Backend:團隊協作的關鍵


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

尚未有邦友留言

立即登入留言