3. Terraform安装与多云网络Provider配置

在真正开始用 Terraform 描述企业网络之前,必须先解决两件事:一是让 Terraform 本体在受控环境中可用,二是让 Terraform 能够以正确的身份、正确的版本、正确的区域去调用 AWS、Azure、GCP、阿里云的 API。前者决定“命令能不能跑”,后者决定“资源能不能被创建到正确的云和账号里”。本节围绕安装、Provider 声明、认证方式与版本约束四条主线展开,并给出可直接参考的配置骨架。

一、安装 Terraform:选对版本与安装方式

Terraform 是单个二进制文件,安装本身并不复杂,但企业环境里真正需要关注的是版本一致性与可重复性。Terraform 的版本号遵循语义化版本,例如 1.7.5,其中主版本变化可能带来配置语法或状态格式的不兼容。团队协作时,如果 A 同学用 1.6、B 同学用 1.8,同一份配置可能在不同机器上产生不同的 plan 结果,因此建议在项目根目录用 required_version 锁定范围。

常见安装方式有三种:包管理器(如 apt、brew、choco)、官方二进制包、以及版本管理工具 tfenv。在 CI/CD 流水线中,推荐使用官方二进制或 tfenv,避免包管理器仓库版本滞后。以 Linux 为例,下载并校验后放入 PATH:

# 示例:下载 Terraform 1.7.5 并校验
curl -O https://releases.hashicorp.com/terraform/1.7.5/terraform_1.7.5_linux_amd64.zip
curl -O https://releases.hashicorp.com/terraform/1.7.5/terraform_1.7.5_SHA256SUMS
sha256sum -c terraform_1.7.5_SHA256SUMS --ignore-missing
unzip terraform_1.7.5_linux_amd64.zip -d /usr/local/bin/
terraform version

执行 terraform version 后应看到类似 Terraform v1.7.5 的输出。若同时安装了多个版本,可用 tfenv install 1.7.5 && tfenv use 1.7.5 切换。安装完成后,建议立即在项目里写入版本约束,而不是等到报错再补。

二、Provider 是什么:Terraform 与云 API 的适配层

Provider 是 Terraform 与具体云平台之间的插件。Terraform 核心只负责解析配置、构建依赖图、管理状态;真正调用 AWS EC2 API、Azure 虚拟网络 API、GCP VPC API、阿里云 VPC API 的动作,都由对应 Provider 完成。每个 Provider 有自己的资源类型、数据源、认证参数和版本节奏,因此“多云网络”本质上就是在一份配置里同时声明多个 Provider,并让每个资源明确归属到某个 Provider。

Provider 通过 required_providers 声明来源与版本,通过 provider 块配置认证与默认区域。下面这张图展示了 Terraform 核心、四个云 Provider 与各自认证入口之间的关系,以及版本约束所处的位置。

Terraform 核心与多云 Provider 认证关系 required_version 约束核心 · required_providers 约束插件 · provider 块绑定认证与区域 Terraform Core 解析配置 · 依赖图 · 状态管理 required_version = ">= 1.6.0" required_providers { source = "hashicorp/aws" version = "~> 5.40" } —— 锁定插件来源与版本范围 AWS Provider hashicorp/aws region = "cn-north-1" Azure Provider hashicorp/azurerm location = "chinaeast2" GCP Provider hashicorp/google region = "asia-east1" 阿里云 Provider aliyun/alicloud region = "cn-hangzhou" 认证入口 环境变量 / 共享凭证 AWS_PROFILE · AssumeRole 认证入口 Service Principal ARM_* 环境变量 / CLI 认证入口 Service Account JSON GOOGLE_APPLICATION_CREDENTIALS 认证入口 AccessKey / STS ALICLOUD_ACCESS_KEY 每个 Provider 独立认证、独立区域;资源通过 provider 参数显式归属,避免默认 Provider 误用

三、声明 Provider 与版本约束

在 Terraform 0.13 之后,Provider 必须显式声明来源。推荐把 required_version 与 required_providers 放在同一个 terraform 块中,形成项目级的“版本契约”。下面是一份多云网络项目的示例骨架:

terraform {
  required_version = ">= 1.6.0, < 2.0.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.40"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.95"
    }
    google = {
      source  = "hashicorp/google"
      version = "~> 5.20"
    }
    alicloud = {
      source  = "aliyun/alicloud"
      version = "~> 1.220"
    }
  }
}

这里的 ~> 5.40 表示允许 5.40 到 5.x 之间的补丁与次版本升级,但不跨到 6.0。这样既能获得安全修复,又不会因为主版本升级导致资源参数被重命名。执行 terraform init 时,Terraform 会读取该约束,从 Registry 下载匹配的 Provider 并写入 .terraform.lock.hcl。锁文件记录了精确版本与校验和,应提交到版本库,保证团队与流水线使用完全一致的插件。

如果企业内网无法访问公网 Registry,可以配置 provider_installation 指向内部镜像或文件系统镜像目录,再配合锁文件使用,避免每次 init 都依赖外网。

四、四种云的认证方式与配置示例

认证的核心原则是:不要把长期密钥硬编码在 .tf 文件里。优先使用环境变量、实例角色、工作负载身份或密钥管理服务。下面给出四种云在本地开发与 CI 中常见的配置方式。

AWS:推荐使用命名 profile 或 AssumeRole。Provider 块中可指定 profile 与 assume_role,凭证由 ~/.aws/credentials 或环境变量提供。

provider "aws" {
  region  = "cn-north-1"
  profile = "network-prod"

  assume_role {
    role_arn     = "arn:aws-cn:iam::123456789012:role/TerraformNetworkRole"
    session_name = "terraform-network"
  }
}

Azure:使用 Service Principal,通过 ARM_CLIENT_ID、ARM_CLIENT_SECRET、ARM_TENANT_ID、ARM_SUBSCRIPTION_ID 四个环境变量注入,Provider 块只需声明 features 与订阅。

provider "azurerm" {
  subscription_id = var.subscription_id
  features {
    virtual_network {
      delete_virtual_network_before_destroy = true
    }
  }
}

GCP:使用 Service Account JSON 文件,通过 GOOGLE_APPLICATION_CREDENTIALS 指向文件路径,Provider 中声明 project 与 region。

provider "google" {
  project = "net-prod-2024"
  region  = "asia-east1"
}

阿里云:使用 RAM 用户的 AccessKey,通过 ALICLOUD_ACCESS_KEY 与 ALICLOUD_SECRET_KEY 注入,Provider 中声明 region。生产环境建议改用 STS 临时凭证。

provider "alicloud" {
  region = "cn-hangzhou"
}

五、多 Provider 下的资源归属与别名

当同一份配置里出现多个云时,最容易出错的是“资源到底创建到哪个账号/区域”。Terraform 的规则是:资源默认使用同名 Provider 的默认配置;如果同一云需要多个区域或多个账号,就用 alias 定义别名,并在资源中通过 provider = aws.xxx 显式指定。例如同时管理 AWS 北京与宁夏两个区域:

provider "aws" {
  alias  = "beijing"
  region = "cn-north-1"
}

provider "aws" {
  alias  = "ningxia"
  region = "cn-northwest-1"
}

resource "aws_vpc" "bj_vpc" {
  provider   = aws.beijing
  cidr_block = "10.10.0.0/16"
  tags = { Name = "bj-network-vpc" }
}

执行 terraform plan 时,输出中会显示资源地址与 Provider 别名,例如 aws_vpc.bj_vpc 对应 provider["registry.terraform.io/hashicorp/aws"].beijing。这是判断“资源是否落到预期账号与区域”的第一道检查点。若发现 plan 中出现了未预期的 Provider,通常说明资源缺少 provider 参数,落到了默认配置上。

六、初始化与验证的完整闭环

配置写完后,按以下顺序验证:先 terraform init 下载 Provider 并生成锁文件;再 terraform providers 查看当前配置解析出的 Provider 树;然后 terraform validate 检查语法与必填参数;最后 terraform plan 观察资源归属与将要创建的网络对象。若认证失败,错误信息通常会明确指出是凭证缺失、权限不足还是区域不匹配,可据此回到对应的环境变量或 Provider 块排查。

不要把 .terraform.lock.hcl 加入 .gitignore。缺少锁文件时,不同机器可能拉到不同补丁版本,导致 plan 差异甚至状态迁移问题。锁文件与 required_providers 配合,才是完整的版本约束方案。