mcpField
O
opentofu-guide

opentofu-guide

github.com/josiahsiegel云与 DevOps59207 次安装19 周前更新
代码仓库

关于 opentofu-guide

面向 Terraform 用户和基础设施团队的 OpenTofu 知识与迁移指南,介绍兼容性、差异和迁移步骤。内容还涵盖状态加密、循环导入及变量求值等 OpenTofu 功能。

主要功能

  1. 01Terraform 与 OpenTofu 差异
  2. 02迁移兼容性评估步骤
  3. 03状态加密配置说明
  4. 04循环导入块示例
  5. 05变量与模块源求值

适用场景

  1. 01评估从 Terraform 切换的可行性
  2. 02迁移项目配置与状态
  3. 03为状态文件启用加密
  4. 04在配置中批量导入资源

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill opentofu-guide

安装后在 Claude Code 中输入/opentofu-guide确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
opentofu-1.10-features.md
opentofu-1.11-features.md
state-encryption.md

详细介绍

🚨 关键指南

Windows 文件路径要求

强制要求:在 Windows 上始终使用反斜杠表示文件路径

在 Windows 上使用 Edit 或 Write 工具时,必须在文件路径中使用反斜杠(\),而不是正斜杠(/)。

示例:

  • ❌ 错误:D:/repos/project/file.tsx
  • ✅ 正确:D:\repos\project\file.tsx

此要求适用于:

  • Edit 工具的 file_path 参数
  • Write 工具的 file_path 参数
  • Windows 系统上的所有文件操作
文档编写指南

除非用户明确要求,否则切勿创建新的文档文件。

  • 优先事项:更新现有的 README.md 文件,而不是创建新的文档
  • 保持仓库整洁:保持仓库根目录整洁——除非用户另有要求,否则只保留 README.md
  • 风格:文档应简洁、直接、专业,避免使用 AI 生成式语气
  • 用户偏好:只有用户明确要求提供文档时,才创建额外的 .md 文件

OpenTofu 专业知识与迁移指南

概述

OpenTofu 是 Terraform 的开源分支,诞生于 2023 年,此前 HashiCorp 将 Terraform 的许可证从 MPL 2.0 更改为 BSL(Business Source License)。OpenTofu 由 Linux Foundation 管理,与 Terraform 1.5.x 完全兼容,同时加入了由社区推动的功能。

主要区别(2025 年)

许可证

Terraform(HashiCorp):

  • 自 2023 年 8 月起采用 BSL(Business Source License)
  • 限制将其用于与之竞争的产品的商业用途
  • IBM 于 2024 年收购了 HashiCorp

OpenTofu:

  • MPL 2.0(Mozilla Public License)
  • 真正开源
  • 由 Linux Foundation 治理
  • 由社区推动开发
功能创新(2025 年)

OpenTofu 1.7 功能:

  • 状态加密:客户端加密(社区提出此需求已有 5 年以上)
  • 可循环导入块:在导入块中使用 for_each
  • 动态 Provider 函数:支持由 Provider 定义的函数
  • 提前评估变量:在 terraform 块中使用变量

OpenTofu 1.8 功能(最新):

  • OpenTofu 专属覆盖项:平衡兼容性与创新
  • 扩展提前评估变量的能力:在模块源中使用变量/locals
  • 增强的 Provider 支持:改进 Provider SDK

Terraform 的优势:

  • HCP Terraform:提供 Stacks、HYOK 和 Private VCS Access 的云平台
  • 企业支持:HashiCorp/IBM 提供直接支持
  • 更大的生态系统:更成熟的市场
  • Sentinel 策略:策略即代码框架(350 多项 NIST 策略)
兼容性

100% 兼容:

  • HCL 语法(相同的语言)
  • Provider 生态系统(可访问相同的注册表)
  • 状态文件格式(Terraform 1.5.x)
  • 模块结构
  • CLI 命令

迁移路径:

  • 可直接替换 Terraform 1.5.x
  • 无需更改代码
  • 状态文件可移植(需考虑加密问题)

何时选择 OpenTofu 或 Terraform

选择 OpenTofu 的情况:
  1. 有开源要求:

    • 组织政策要求使用开源工具
    • 希望避免供应商绑定
    • 担心未来许可证发生变化
  2. 需要状态加密:

    • 合规要求使用客户端加密
    • 希望在不使用 HCP Terraform 的情况下实现加密
    • 有多云加密需求
  3. 优化成本:

    • 希望免费使用状态加密
    • 不需要 HCP Terraform 的功能
    • 工具预算受限
  4. 由社区推动:

    • 希望影响发展路线图
    • 更倾向于由 Linux Foundation 治理
    • 重视社区贡献
在以下情况下选择 Terraform:
  1. 需要企业级功能:

    • 需要 HCP Terraform Stacks
    • 需要 HYOK(自持密钥)
    • 需要私有 VCS 访问
    • 需要 Sentinel 策略强制执行
  2. 企业级支持:

    • 需要 HashiCorp/IBM 的直接支持
    • 需要 SLA 保障
    • 需要合规认证
  3. 高级功能:

    • 临时值(1.10+)
    • Terraform Query(1.14+)
    • Actions 块(1.14+)
    • 优先获得最新的提供商功能
  4. 成熟的生态系统:

    • 已有 HCP Terraform 投资
    • 需要紧密集成
    • 需要成熟的工具

从 Terraform 迁移到 OpenTofu

步骤 1:评估兼容性
# Check Terraform version
terraform version
# Must be 1.5.x or compatible

# Check provider versions
terraform providers
# All providers compatible (same registry)
步骤 2:安装 OpenTofu

Windows:

# Chocolatey
choco install opentofu

# Scoop
scoop install opentofu

# Manual
# Download from https://github.com/opentofu/opentofu/releases

macOS:

# Homebrew
brew install opentofu

# Manual
curl -L https://github.com/opentofu/opentofu/releases/download/v1.8.0/tofu_1.8.0_darwin_amd64.tar.gz | tar xz
sudo mv tofu /usr/local/bin/

Linux:

# Snap
snap install opentofu --classic

# Debian/Ubuntu
curl -fsSL https://get.opentofu.org/install-opentofu.sh | sh

# Manual
wget https://github.com/opentofu/opentofu/releases/download/v1.8.0/tofu_1.8.0_linux_amd64.tar.gz
tar -xzf tofu_1.8.0_linux_amd64.tar.gz
sudo mv tofu /usr/local/bin/
步骤 3:测试兼容性
# Navigate to Terraform directory
cd /path/to/terraform/project

# Initialize with OpenTofu (non-destructive)
tofu init

# Validate configuration
tofu validate

# Generate plan (compare with Terraform plan)
tofu plan
步骤 4:迁移状态(可选)

如果未使用状态加密:

# State is compatible - no migration needed
# Just switch from 'terraform' to 'tofu' commands

# Verify state
tofu show

如果启用状态加密:

# Configure encryption in .tofu file
cat > .tofu <<EOF
encryption {
  state {
    method = "aes_gcm"
    keys {
      name = "my_key"
      passphrase = env.TOFU_ENCRYPTION_KEY
    }
  }

  plan {
    method = "aes_gcm"
    keys {
      name = "my_key"
      passphrase = env.TOFU_ENCRYPTION_KEY
    }
  }
}
EOF

# Set encryption key
export TOFU_ENCRYPTION_KEY="your-secure-passphrase"

# Migrate state (automatically encrypts)
tofu init -migrate-state
步骤 5:更新 CI/CD

GitHub Actions:

# Before (Terraform)
- uses: hashicorp/setup-terraform@v3
  with:
    terraform_version: 1.5.0

# After (OpenTofu)
- uses: opentofu/setup-opentofu@v1
  with:
    tofu_version: 1.8.0

# Or manual install
- name: Install OpenTofu
  run: |
    curl -fsSL https://get.opentofu.org/install-opentofu.sh | sh
    tofu version

Azure DevOps:

# Before
- task: TerraformInstaller@0
  inputs:
    terraformVersion: '1.5.0'

# After
- task: Bash@3
  displayName: 'Install OpenTofu'
  inputs:
    targetType: 'inline'
    script: |
      curl -fsSL https://get.opentofu.org/install-opentofu.sh | sh
      tofu version

GitLab CI:

# Before
image: hashicorp/terraform:1.5.0

# After
image: ghcr.io/opentofu/opentofu:1.8.0

状态加密(OpenTofu 独有)

配置

基本加密:

# .tofu or terraform.tf
encryption {
  state {
    method = "aes_gcm"
    keys {
      name = "primary_key"
      passphrase = env.TOFU_STATE_ENCRYPTION_KEY
    }
  }
}

密钥轮换:

encryption {
  state {
    method = "aes_gcm"
    keys {
      # New key
      name = "key_v2"
      passphrase = env.TOFU_KEY_V2

      # Old key (for decryption)
      fallback {
        name = "key_v1"
        passphrase = env.TOFU_KEY_V1
      }
    }
  }
}

云 KMS 集成:

# AWS KMS
encryption {
  state {
    method = "aws_kms"
    keys {
      name = "aws_key"
      kms_key_id = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
    }
  }
}

# Azure Key Vault
encryption {
  state {
    method = "azurerm_key_vault"
    keys {
      name = "azure_key"
      key_vault_key_id = "https://myvault.vault.azure.net/keys/mykey/version"
    }
  }
}

# GCP KMS
encryption {
  state {
    method = "gcp_kms"
    keys {
      name = "gcp_key"
      kms_crypto_key = "projects/PROJECT_ID/locations/LOCATION/keyRings/RING/cryptoKeys/KEY"
    }
  }
}
最佳实践
  1. 安全存储密钥:

    # Never commit keys
    echo "TOFU_ENCRYPTION_KEY=xxx" >> .env
    echo ".env" >> .gitignore
    
    # Use CI/CD secrets
    # GitHub: Repository Settings → Secrets
    # Azure DevOps: Pipeline → Variables → Secret
    
  2. 定期轮换密钥:

    # Generate new key
    NEW_KEY=$(openssl rand -base64 32)
    
    # Add to fallback, update configs
    # Migrate state
    tofu init -migrate-state
    
  3. 备份未加密的状态:

    # Before enabling encryption
    terraform state pull > backup-unencrypted.tfstate
    
    # Enable encryption
    tofu init -migrate-state
    
    # Verify
    tofu state pull  # Should be encrypted in backend
    

可循环的导入块(OpenTofu 1.7+)

Terraform 1.5+(单个导入):

import {
  to = azurerm_resource_group.example
  id = "/subscriptions/.../resourceGroups/my-rg"
}

OpenTofu 1.7+(循环导入):

# Import multiple resource groups
locals {
  resource_groups = {
    "rg1" = "/subscriptions/.../resourceGroups/rg1"
    "rg2" = "/subscriptions/.../resourceGroups/rg2"
    "rg3" = "/subscriptions/.../resourceGroups/rg3"
  }
}

import {
  for_each = local.resource_groups
  to       = azurerm_resource_group.imported[each.key]
  id       = each.value
}

resource "azurerm_resource_group" "imported" {
  for_each = local.resource_groups
  name     = each.key
  location = "eastus"
}

提前评估变量(OpenTofu 1.7+)

Terraform 1.5.x:

# Variables NOT allowed in terraform block
terraform {
  required_version = ">= 1.5.0"  # Static only

  backend "azurerm" {
    resource_group_name  = "terraform-state"  # Static only
    storage_account_name = "tfstate"
  }
}

OpenTofu 1.7+:

# Variables allowed in terraform block
variable "environment" {
  type = string
}

terraform {
  required_version = ">= 1.7.0"

  backend "azurerm" {
    resource_group_name  = "terraform-state-${var.environment}"
    storage_account_name = "tfstate${var.environment}"
    key                  = "${var.environment}.tfstate"
  }
}

OpenTofu 1.8+(模块源):

variable "module_version" {
  type    = string
  default = "v1.0.0"
}

module "networking" {
  source  = "git::https://github.com/org/module.git?ref=${var.module_version}"
  # Dynamic module version!
}

实用迁移示例

示例 1:小型项目迁移
# 1. Backup existing state
terraform state pull > backup.tfstate

# 2. Install OpenTofu
brew install opentofu

# 3. Test compatibility
tofu init
tofu plan

# 4. Switch to OpenTofu
alias terraform=tofu  # Optional: maintain muscle memory

# 5. Verify everything works
tofu apply
示例 2:使用加密的企业级迁移
# 1. Generate encryption key
ENCRYPTION_KEY=$(openssl rand -base64 32)
echo "TOFU_ENCRYPTION_KEY=$ENCRYPTION_KEY" >> .env.production

# 2. Create encryption config
cat > .tofu <<EOF
encryption {
  state {
    method = "aes_gcm"
    keys {
      name = "prod_key"
      passphrase = env.TOFU_ENCRYPTION_KEY
    }
  }

  plan {
    method = "aes_gcm"
    keys {
      name = "prod_key"
      passphrase = env.TOFU_ENCRYPTION_KEY
    }
  }
}
EOF

# 3. Migrate with encryption
source .env.production
tofu init -migrate-state

# 4. Verify encryption
tofu state pull  # State is now encrypted in backend
示例 3:CI/CD 迁移
# .github/workflows/terraform.yml
name: Infrastructure

on: [push, pull_request]

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

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

      - name: Init
        run: tofu init
        env:
          TOFU_ENCRYPTION_KEY: ${{ secrets.TOFU_ENCRYPTION_KEY }}

      - name: Plan
        run: tofu plan
        env:
          ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
          ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
          ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
          ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
          TOFU_ENCRYPTION_KEY: ${{ secrets.TOFU_ENCRYPTION_KEY }}

      - name: Apply
        if: github.ref == 'refs/heads/main'
        run: tofu apply -auto-approve
        env:
          ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
          ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
          ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
          ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
          TOFU_ENCRYPTION_KEY: ${{ secrets.TOFU_ENCRYPTION_KEY }}

命令兼容性

所有 Terraform 命令在 OpenTofu 中的用法完全相同(只需将 terraform 替换为 tofu):

# Terraform          # OpenTofu
terraform init      → tofu init
terraform plan      → tofu plan
terraform apply     → tofu apply
terraform destroy   → tofu destroy
terraform state     → tofu state
terraform import    → tofu import
terraform validate  → tofu validate
terraform fmt       → tofu fmt
terraform output    → tofu output

社区与支持

OpenTofu 社区:

Terraform 社区:

  • 论坛:HashiCorp 讨论区
  • GitHub:hashicorp/terraform
  • 注册表:registry.terraform.io
  • 支持:HashiCorp 支持门户

决策矩阵

因素TerraformOpenTofu
许可证BSL(专有)MPL 2.0(开源)
状态加密通过 HCP Terraform 提供(付费)内置(免费)
企业级功能HCP Terraform(Stacks、HYOK)社区替代方案
治理HashiCorp/IBMLinux Foundation
支持提供商业支持社区驱动
创新面向 HCP面向社区
成本CLI 免费,云服务付费完全免费
兼容性向前兼容兼容 Terraform 1.5.x

建议

在以下情况下从 OpenTofu 开始:

  • 构建新的基础设施
  • 不需要 HCP Terraform 功能
  • 希望无需云服务费用即可加密状态
  • 倾向于使用开源工具
  • 注重预算

在以下情况下继续使用 Terraform:

  • 正在使用 HCP Terraform Stacks
  • 需要 Sentinel 策略
  • 需要企业级支持
  • 希望优先获得最新功能(1.10+)
  • 已有 HCP 投资

切换轻松:

  • 两者长期来看都可行
  • 大多数项目的迁移耗时不到 1 小时
  • 状态文件可移植
  • 可以无承诺地评估两者

此技能为 terraform-expert Agent 提供全面的 OpenTofu 知识。

评论

支持 Markdown