Terraform OpenTofu 開源替代方案

OpenTofu as Terraform Open Source Alternative

前言

在 Infrastructure as Code(IaC)領域中,Terraform 長期以來一直是業界標準工具。然而,2023 年 HashiCorp 宣布將 Terraform 的授權從開源的 Mozilla Public License 2.0(MPL 2.0)變更為 Business Source License 1.1(BSL 1.1),這項決定在開源社群引發了巨大的迴響。作為回應,OpenTofu 應運而生,成為 Terraform 的真正開源替代方案。

本文將深入探討 OpenTofu 的背景、與 Terraform 的差異、安裝遷移方式,以及企業採用時的各種考量。


1. OpenTofu 背景與緣起

HashiCorp 授權變更事件

2023 年 8 月,HashiCorp 宣布將旗下產品(包括 Terraform、Vault、Consul 等)的授權從 MPL 2.0 變更為 BSL 1.1。這項變更意味著:

  • 商業使用限制:競爭對手無法直接使用這些工具提供類似的託管服務
  • 開源精神受損:BSL 不符合 Open Source Initiative(OSI)的開源定義
  • 社群貢獻疑慮:許多貢獻者擔心其貢獻被商業化利用

OpenTofu 的誕生

為了維護 Terraform 的開源精神,Linux Foundation 在 2023 年 9 月宣布成立 OpenTofu 專案:

  • Fork 自 Terraform:基於 Terraform v1.5.x 的最後一個 MPL 2.0 版本
  • 真正的開源:採用 MPL 2.0 授權,永久保持開源
  • 社群驅動:由 Linux Foundation 管理,確保中立治理
  • 企業支持:獲得 Spacelift、env0、Scalr 等多家公司支持
1
2
3
4
5
6
Timeline:
2023-08    HashiCorp 宣布授權變更
2023-09    OpenTofu 專案成立
2023-12    OpenTofu 1.6.0 正式發布
2024-03    OpenTofu 1.7.0 發布,新增獨特功能
2025-xx    持續發展,功能逐漸分化

2. 與 Terraform 差異

授權差異

項目TerraformOpenTofu
授權BSL 1.1MPL 2.0
開源認證是(OSI 認證)
商業使用有限制無限制
社群治理HashiCorp 主導Linux Foundation 治理

功能差異

從 OpenTofu 1.7 開始,兩者的功能開始出現分化:

OpenTofu 獨有功能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 1. State Encryption - 狀態檔案加密
terraform {
  encryption {
    key_provider "pbkdf2" "my_passphrase" {
      passphrase = var.state_passphrase
    }

    method "aes_gcm" "my_method" {
      keys = key_provider.pbkdf2.my_passphrase
    }

    state {
      method = method.aes_gcm.my_method
    }
  }
}

# 2. Early Variable/Local Evaluation
# 可在 module source 和 backend configuration 中使用變數
locals {
  environment = "production"
}

module "vpc" {
  source = "git::https://github.com/org/modules.git//vpc?ref=${local.environment}"
}

# 3. Provider-defined Functions
# Provider 可以定義自己的函數
output "parsed_arn" {
  value = provider::aws::arn_parse("arn:aws:s3:::my-bucket")
}

Terraform 獨有功能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 1. Stacks (Terraform Cloud 功能)
# 用於管理多個相關的 Terraform 配置

# 2. Ephemeral Values (1.10+)
# 臨時值,不會儲存在 state 中
variable "temporary_token" {
  type      = string
  ephemeral = true
}

# 3. terraform test 功能增強
# 原生測試框架

CLI 差異

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Terraform
terraform init
terraform plan
terraform apply

# OpenTofu - 完全相容的 CLI
tofu init
tofu plan
tofu apply

# OpenTofu 特有命令
tofu state encryption    # 管理狀態加密

3. 安裝與遷移

安裝 OpenTofu

macOS

1
2
3
4
5
6
# 使用 Homebrew
brew update
brew install opentofu

# 驗證安裝
tofu version

Linux (Debian/Ubuntu)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 安裝 GPG key 和 repository
curl -fsSL https://get.opentofu.org/install-opentofu.sh | sudo bash -s -- --install-method deb

# 或手動安裝
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg

curl -fsSL https://packages.opentofu.org/opentofu/tofu/gpgkey | \
  sudo gpg --dearmor -o /usr/share/keyrings/opentofu-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/opentofu-archive-keyring.gpg] \
  https://packages.opentofu.org/opentofu/tofu/any/ any main" | \
  sudo tee /etc/apt/sources.list.d/opentofu.list > /dev/null

sudo apt-get update
sudo apt-get install tofu

Linux (RHEL/CentOS/Fedora)

1
2
3
4
5
# 使用安裝腳本
curl -fsSL https://get.opentofu.org/install-opentofu.sh | sudo bash -s -- --install-method rpm

# 驗證
tofu version

Windows

1
2
3
4
5
6
# 使用 Chocolatey
choco install opentofu

# 或使用 Scoop
scoop bucket add opentofu https://github.com/opentofu/scoop-bucket
scoop install opentofu

Docker

1
2
3
4
5
6
# 使用官方 Docker image
docker pull ghcr.io/opentofu/opentofu:latest

# 執行
docker run --rm -v $(pwd):/workspace -w /workspace \
  ghcr.io/opentofu/opentofu:latest init

從 Terraform 遷移

基本遷移步驟

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 1. 備份現有狀態
cp terraform.tfstate terraform.tfstate.backup
cp -r .terraform .terraform.backup

# 2. 清理 Terraform 快取
rm -rf .terraform
rm -f .terraform.lock.hcl

# 3. 初始化 OpenTofu
tofu init

# 4. 驗證狀態
tofu plan
# 應該顯示 "No changes" 如果遷移成功

處理 Provider Lock 檔案

1
2
3
4
5
6
7
8
# 重新產生 lock 檔案
tofu providers lock \
  -platform=linux_amd64 \
  -platform=darwin_amd64 \
  -platform=darwin_arm64

# 檢查 lock 檔案
cat .terraform.lock.hcl

CI/CD Pipeline 遷移

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# GitHub Actions 範例
name: OpenTofu CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  tofu:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup OpenTofu
        uses: opentofu/setup-opentofu@v1
        with:
          tofu_version: 1.8.0

      - name: OpenTofu Init
        run: tofu init

      - name: OpenTofu Format Check
        run: tofu fmt -check -recursive

      - name: OpenTofu Validate
        run: tofu validate

      - name: OpenTofu Plan
        run: tofu plan -out=tfplan

      - name: OpenTofu Apply
        if: github.ref == 'refs/heads/main'
        run: tofu apply -auto-approve tfplan

4. 相容性與功能

Terraform 相容性對照表

Terraform 版本OpenTofu 版本相容性說明
1.5.x1.6.x完全相容
1.6.x1.6.x大部分相容
1.7.x1.7.x核心相容,部分功能分化
1.8.x+1.8.x+功能開始顯著分化

State 檔案相容性

1
2
3
4
5
6
# 檢查 state 版本
cat terraform.tfstate | jq '.version, .terraform_version'

# OpenTofu 支援的 state 版本
# version: 4 (完全支援)
# terraform_version: 1.5.x 或更早 (完全支援)

Provider 相容性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 大多數 Provider 完全相容
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.0"
    }
  }
}

模組相容性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Terraform Registry 模組繼續可用
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"

  name = "my-vpc"
  cidr = "10.0.0.0/16"
}

# OpenTofu Registry 模組
module "eks" {
  source  = "registry.opentofu.org/terraform-aws-modules/eks/aws"
  version = "20.0.0"

  cluster_name = "my-cluster"
}

5. 社群與發展路線

社群治理結構

OpenTofu 採用開放的社群治理模式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Linux Foundation
┌─────────────────┐
│ Technical       │
│ Steering        │
│ Committee (TSC) │
└────────┬────────┘
    ┌────┴────┐
    ▼         ▼
┌───────┐ ┌───────┐
│ Core  │ │ Eco-  │
│ Team  │ │ system│
└───────┘ └───────┘

貢獻方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Fork 並 clone repository
git clone https://github.com/opentofu/opentofu.git
cd opentofu

# 建立開發環境
go mod download

# 執行測試
go test ./...

# 建置
go build -o tofu ./cmd/tofu

發展路線圖

已完成功能(2024-2025)

  • State Encryption(狀態加密)
  • Early Variable Evaluation(早期變數評估)
  • Provider-defined Functions(Provider 自定義函數)
  • Registry Mirror 支援
  • 改進的錯誤訊息

計畫中功能(2025-2026)

  • Enhanced Module Testing
  • Improved Import Workflow
  • Better IDE Integration
  • Performance Optimizations
  • Extended Provider Protocol

參與社群

1
2
3
4
5
6
7
8
# 官方資源
# GitHub: https://github.com/opentofu/opentofu
# Slack: https://opentofu.org/slack
# Forum: https://github.com/opentofu/opentofu/discussions

# 追蹤更新
# RSS: https://opentofu.org/blog/rss.xml
# Newsletter: https://opentofu.org/newsletter

6. Provider 生態系統

OpenTofu Registry

OpenTofu 建立了自己的 Registry 系統,同時保持與 Terraform Registry 的相容性:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
terraform {
  required_providers {
    # 預設使用 OpenTofu Registry (優先)
    # 回退到 Terraform Registry
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

Registry 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# ~/.tofurc 或專案內 .tofurc
provider_installation {
  network_mirror {
    url = "https://registry.opentofu.org/v1/mirror/"
  }

  direct {
    exclude = ["registry.terraform.io/*/*"]
  }
}

常用 Provider 一覽

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 雲端平台
terraform {
  required_providers {
    # AWS
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.30"
    }

    # Google Cloud
    google = {
      source  = "hashicorp/google"
      version = "~> 5.10"
    }

    # Azure
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.85"
    }

    # Alibaba Cloud
    alicloud = {
      source  = "aliyun/alicloud"
      version = "~> 1.215"
    }
  }
}

# 容器與 Kubernetes
terraform {
  required_providers {
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.25"
    }

    helm = {
      source  = "hashicorp/helm"
      version = "~> 2.12"
    }

    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0"
    }
  }
}

# 監控與維運
terraform {
  required_providers {
    datadog = {
      source  = "DataDog/datadog"
      version = "~> 3.35"
    }

    grafana = {
      source  = "grafana/grafana"
      version = "~> 2.10"
    }

    pagerduty = {
      source  = "PagerDuty/pagerduty"
      version = "~> 3.6"
    }
  }
}

自建 Provider Registry

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 使用 OpenTofu Registry Protocol
# 目錄結構
registry/
├── v1/
│   └── providers/
│       └── myorg/
│           └── myprovider/
│               ├── versions
│               └── 1.0.0/
│                   └── download/
│                       └── linux_amd64
1
2
3
4
5
6
7
8
9
# 配置使用自建 Registry
terraform {
  required_providers {
    myprovider = {
      source  = "registry.mycompany.com/myorg/myprovider"
      version = "~> 1.0"
    }
  }
}

7. 企業使用考量

法務與合規評估

授權比較

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
MPL 2.0 (OpenTofu):
✓ 可自由使用、修改、分發
✓ 可用於商業目的
✓ 可整合到專有軟體中
✓ 無需公開衍生作品(除非修改 MPL 授權的檔案)

BSL 1.1 (Terraform):
✓ 可用於內部使用
✗ 競爭用途受限
✗ 提供類似託管服務受限
○ 4 年後轉為開源授權

技術評估矩陣

評估項目TerraformOpenTofu備註
穩定性兩者都成熟穩定
企業支援HashiCorp社群 + 第三方HashiCorp 提供付費支援
雲端整合Terraform Cloud第三方方案Spacelift, env0, Scalr
長期維護商業公司Linux Foundation兩者都可靠
功能更新快速穩健各有特色功能

遷移風險評估

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/bin/bash
# migration-assessment.sh - 遷移評估腳本

echo "=== OpenTofu 遷移評估報告 ==="

# 檢查 Terraform 版本
echo -e "\n[1] Terraform 版本檢查"
terraform version

# 檢查 state 版本
echo -e "\n[2] State 版本檢查"
if [ -f "terraform.tfstate" ]; then
  jq '.version, .terraform_version' terraform.tfstate
else
  echo "使用遠端 state"
fi

# 檢查 provider 版本
echo -e "\n[3] Provider 版本檢查"
cat .terraform.lock.hcl 2>/dev/null | grep -A2 'provider'

# 檢查模組來源
echo -e "\n[4] 模組來源檢查"
grep -r "source\s*=" *.tf 2>/dev/null | head -20

# 檢查是否使用 Terraform Cloud 功能
echo -e "\n[5] Terraform Cloud 功能檢查"
grep -r "cloud\s*{" *.tf 2>/dev/null

echo -e "\n=== 評估完成 ==="

企業級架構範例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 企業級 OpenTofu 配置範例

terraform {
  required_version = ">= 1.7.0"

  # 使用加密的 S3 後端
  backend "s3" {
    bucket         = "company-tofu-state"
    key            = "production/infrastructure.tfstate"
    region         = "ap-northeast-1"
    encrypt        = true
    dynamodb_table = "tofu-state-lock"
    kms_key_id     = "arn:aws:kms:ap-northeast-1:123456789:key/xxx"
  }

  # 狀態加密 (OpenTofu 獨有)
  encryption {
    key_provider "aws_kms" "main" {
      kms_key_id = "arn:aws:kms:ap-northeast-1:123456789:key/xxx"
      region     = "ap-northeast-1"
    }

    method "aes_gcm" "default" {
      keys = key_provider.aws_kms.main
    }

    state {
      method   = method.aes_gcm.default
      enforced = true
    }

    plan {
      method   = method.aes_gcm.default
      enforced = true
    }
  }

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.30"
    }
  }
}

# 標準化標籤
locals {
  common_tags = {
    Environment = var.environment
    Project     = var.project_name
    ManagedBy   = "OpenTofu"
    CostCenter  = var.cost_center
    Owner       = var.team_email
  }
}

成本考量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Terraform 生態系統成本:
├── Terraform Cloud (Team & Governance)
│   └── $20/user/month 起
├── Terraform Enterprise
│   └── 需要聯繫銷售
└── HashiCorp 支援合約
    └── 依規模定價

OpenTofu 生態系統成本:
├── OpenTofu Core
│   └── 免費 (MPL 2.0)
├── 第三方託管方案
│   ├── Spacelift: $20/user/month 起
│   ├── env0: 依使用量計價
│   └── Scalr: $25/user/month 起
└── 自建方案
    └── 運維成本

8. 遷移最佳實務

遷移前準備

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 1. 完整備份
#!/bin/bash

BACKUP_DIR="terraform-backup-$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"

# 備份所有 .tf 檔案
cp -r *.tf "$BACKUP_DIR/"

# 備份 state
if [ -f "terraform.tfstate" ]; then
  cp terraform.tfstate "$BACKUP_DIR/"
fi

# 備份 lock 檔案
cp .terraform.lock.hcl "$BACKUP_DIR/" 2>/dev/null

# 備份 .terraform 目錄
cp -r .terraform "$BACKUP_DIR/" 2>/dev/null

echo "備份完成: $BACKUP_DIR"

分階段遷移策略

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Phase 1: 評估與準備 (1-2 週)
├── 盤點所有 Terraform 專案
├── 評估各專案複雜度
├── 建立測試環境
└── 培訓團隊成員

Phase 2: 試點專案 (2-4 週)
├── 選擇低風險專案
├── 執行遷移
├── 驗證功能
└── 記錄問題與解決方案

Phase 3: 漸進式遷移 (依規模)
├── 依優先序遷移專案
├── 更新 CI/CD pipeline
├── 同步文件
└── 持續監控

Phase 4: 完成與優化 (2 週)
├── 確認所有專案遷移完成
├── 移除 Terraform 相依
├── 探索 OpenTofu 新功能
└── 建立長期維護流程

遷移驗證清單

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/bin/bash
# migration-validation.sh

echo "=== OpenTofu 遷移驗證清單 ==="

# 1. 初始化檢查
echo -e "\n[1] 初始化驗證"
tofu init -upgrade
if [ $? -eq 0 ]; then
  echo "✓ 初始化成功"
else
  echo "✗ 初始化失敗"
  exit 1
fi

# 2. 格式檢查
echo -e "\n[2] 格式驗證"
tofu fmt -check -recursive
if [ $? -eq 0 ]; then
  echo "✓ 格式正確"
else
  echo "⚠ 格式需要調整"
fi

# 3. 驗證配置
echo -e "\n[3] 配置驗證"
tofu validate
if [ $? -eq 0 ]; then
  echo "✓ 配置有效"
else
  echo "✗ 配置無效"
  exit 1
fi

# 4. Plan 檢查
echo -e "\n[4] Plan 驗證 (應無變更)"
tofu plan -detailed-exitcode
PLAN_EXIT=$?
if [ $PLAN_EXIT -eq 0 ]; then
  echo "✓ 無變更 - 遷移成功"
elif [ $PLAN_EXIT -eq 2 ]; then
  echo "⚠ 偵測到變更 - 請檢查"
else
  echo "✗ Plan 失敗"
  exit 1
fi

# 5. State 檢查
echo -e "\n[5] State 驗證"
tofu state list | head -10
echo "..."
RESOURCE_COUNT=$(tofu state list | wc -l)
echo "總資源數: $RESOURCE_COUNT"

echo -e "\n=== 驗證完成 ==="

常見問題處理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 問題 1: Provider 版本衝突
# 解決方案: 重新產生 lock 檔案
# tofu providers lock -platform=linux_amd64

# 問題 2: State 版本不相容
# 解決方案: 確認使用相容的 OpenTofu 版本
terraform {
  required_version = ">= 1.6.0, < 2.0.0"
}

# 問題 3: 模組來源問題
# 解決方案: 使用明確的 registry 來源
module "example" {
  source  = "registry.terraform.io/terraform-aws-modules/vpc/aws"
  version = "5.0.0"
  # 或使用 OpenTofu registry
  # source = "registry.opentofu.org/terraform-aws-modules/vpc/aws"
}

# 問題 4: Backend 遷移
# 解決方案: 使用 state migration
# tofu init -migrate-state

Alias 設定建議

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# ~/.bashrc 或 ~/.zshrc

# 方案 1: 完全取代
alias terraform="tofu"
alias tf="tofu"

# 方案 2: 共存
alias tofu="tofu"
alias tf="tofu"
# 保留 terraform 指向原始命令

# 方案 3: 環境切換
function use-tofu() {
  alias terraform="tofu"
  echo "Now using OpenTofu"
}

function use-terraform() {
  unalias terraform 2>/dev/null
  echo "Now using Terraform"
}

總結

OpenTofu 作為 Terraform 的開源替代方案,提供了:

  1. 真正的開源授權:MPL 2.0 確保永久開源
  2. 完整的相容性:與 Terraform 生態系統高度相容
  3. 創新功能:State Encryption、Early Variable Evaluation 等獨特功能
  4. 穩健的治理:Linux Foundation 確保中立與透明
  5. 活躍的社群:持續成長的貢獻者與使用者社群

對於重視開源精神、需要避免授權風險,或希望使用 OpenTofu 獨有功能的團隊,遷移到 OpenTofu 是值得考慮的選擇。透過本文介紹的遷移策略與最佳實務,相信能夠順利完成轉換,享受開源 IaC 工具帶來的自由與彈性。

參考資源

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy