3. 跨云 Provider 配置:AWS、Azure、GCP Provider 的认证方式与最佳实践、多 Provider 混用模式

在跨云资源池编排中,Terraform 需要同时与 AWS、Azure、GCP 三大云厂商的 API 进行交互。每个云平台都有其独特的认证机制和权限模型。本章将深入剖析三大云 Provider 的认证方式、安全最佳实践,以及如何在同一个 Terraform 配置中安全、高效地混用多个 Provider。

3.1 三大云 Provider 认证方式对比

下表总结了 AWS、Azure、GCP 最常用的认证方式及其适用场景,帮助你在不同环境下快速选择正确的认证策略。

云平台 认证方式 环境变量 优先级 适用场景
AWS 静态凭证 (Access Key + Secret Key) AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 低 本地开发测试,不推荐生产
AWS 共享凭证文件 (~/.aws/credentials) AWS_PROFILE, AWS_SHARED_CREDENTIALS_FILE 中 本地开发、CI/CD 临时凭证
AWS IAM 实例角色 (EC2 / EKS) 自动注入 高 生产环境首选,自动轮换
Azure 服务主体 (Client ID + Secret) ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_TENANT_ID, ARM_SUBSCRIPTION_ID 中 CI/CD、自动化脚本
Azure 托管标识 (Managed Identity) 自动注入 高 生产环境首选,无需管理凭证
Azure Azure CLI 登录 az login 低 本地开发调试
GCP 服务账号密钥 (JSON Key File) GOOGLE_APPLICATION_CREDENTIALS 中 CI/CD、本地开发
GCP 默认服务账号 (Compute Engine / GKE) 自动注入 高 生产环境首选,自动轮换
GCP gcloud 应用默认凭证 (ADC) gcloud auth application-default login 低 本地开发调试
最佳实践提示: 在 CI/CD 流水线中,优先使用云平台的原生无密钥认证机制(如 AWS IAM Role、Azure Managed Identity、GCP Default Service Account)。仅在无法使用上述方式时,才考虑使用静态凭证或服务主体,并务必使用 CI/CD 的密钥管理服务(如 GitHub Secrets、GitLab CI Variables)存储敏感信息。

3.2 Provider 配置与认证最佳实践

以下分别展示三大云 Provider 在 Terraform 中的标准配置方式,并给出生产环境推荐的安全配置。

3.2.1 AWS Provider 配置

# 生产环境推荐:使用 IAM 实例角色,无需显式配置凭证
provider "aws" {
  region = "us-east-1"
  # 当运行在 EC2/EKS 上时,SDK 自动从实例元数据获取临时凭证
}

# CI/CD 环境:使用 assume_role 进行跨账号访问
provider "aws" {
  region = "us-west-2"
  assume_role {
    role_arn     = "arn:aws:iam::123456789012:role/TerraformExecutionRole"
    session_name = "TerraformCICD"
  }
}

# 本地开发:通过 AWS_PROFILE 环境变量指定 profile
# export AWS_PROFILE=my-dev-profile
provider "aws" {
  region = "ap-southeast-1"
}

3.2.2 Azure Provider 配置

# 生产环境推荐:使用托管标识,无需管理凭证
provider "azurerm" {
  features {}
  # 当运行在 Azure VM/App Service 上时,自动使用托管标识
}

# CI/CD 环境:使用服务主体,凭证存储在 CI/CD 变量中
provider "azurerm" {
  features {}
  subscription_id = var.arm_subscription_id
  client_id       = var.arm_client_id
  client_secret   = var.arm_client_secret
  tenant_id       = var.arm_tenant_id
}

# 本地开发:使用 Azure CLI 登录
# 运行 az login 后,Provider 自动使用缓存的令牌
provider "azurerm" {
  features {}
}

3.2.3 GCP Provider 配置

# 生产环境推荐:使用默认服务账号,无需配置凭证
provider "google" {
  project = "my-production-project"
  region  = "us-central1"
  # 当运行在 GCE/GKE 上时,自动使用默认服务账号
}

# CI/CD 环境:使用服务账号密钥文件路径
provider "google" {
  project     = var.gcp_project_id
  region      = "europe-west1"
  credentials = file(var.gcp_sa_key_path)
}

# 本地开发:使用 gcloud ADC
# 运行 gcloud auth application-default login 后自动生效
provider "google" {
  project = "my-dev-project"
  region  = "asia-east1"
}
安全警告: 切勿将云服务商的密钥文件(如 GCP JSON Key、AWS Access Key)直接提交到 Git 仓库。始终使用 .gitignore 排除密钥文件,并在 CI/CD 中使用环境变量或密钥管理服务注入凭证。

3.3 多 Provider 混用模式

在跨云资源池场景中,一个 Terraform 配置需要同时管理多个云平台的资源。Terraform 通过 alias 元参数支持在同一配置中定义多个同类型或不同类型的 Provider 实例。

3.3.1 混用模式架构

下图展示了在单个 Terraform 工作区中,如何通过别名配置同时管理 AWS、Azure、GCP 的资源,并实现跨云资源池的编排。

多 Provider 混用模式架构 Terraform Core provider "aws" provider "azurerm" provider "google" alias = "europe" alias = "dev" alias = "asia" aws_vpc.main azurerm_vnet.main google_vpc.main 说明: 每个 Provider 实例可以拥有独立的认证配置和 region,通过 alias 区分。资源通过 provider 参数引用对应的 Provider 实例。

3.3.2 混用配置示例

以下代码展示了如何在同一个 Terraform 配置中定义多个 Provider 实例,并为不同资源指定不同的 Provider。

# 定义默认 AWS Provider(美国东部)
provider "aws" {
  region = "us-east-1"
}

# 定义别名 AWS Provider(欧洲)
provider "aws" {
  alias  = "europe"
  region = "eu-west-1"
  assume_role {
    role_arn = "arn:aws:iam::111111111111:role/EUAdmin"
  }
}

# 定义 Azure Provider(生产订阅)
provider "azurerm" {
  features {}
  subscription_id = "00000000-0000-0000-0000-000000000001"
}

# 定义别名 Azure Provider(开发订阅)
provider "azurerm" {
  alias           = "dev"
  features {}
  subscription_id = "00000000-0000-0000-0000-000000000002"
}

# 定义 GCP Provider(默认)
provider "google" {
  project = "prod-project-123"
  region  = "us-central1"
}

# 使用默认 AWS Provider 创建资源
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "main-vpc"
  }
}

# 使用别名 AWS Provider 创建欧洲资源
resource "aws_vpc" "europe" {
  provider   = aws.europe
  cidr_block = "10.1.0.0/16"
  tags = {
    Name = "europe-vpc"
  }
}

# 使用默认 Azure Provider 创建资源
resource "azurerm_resource_group" "main" {
  name     = "rg-prod-main"
  location = "East US"
}

# 使用别名 Azure Provider 创建开发资源
resource "azurerm_resource_group" "dev" {
  provider = azurerm.dev
  name     = "rg-dev-main"
  location = "West Europe"
}

# 使用 GCP Provider 创建资源
resource "google_compute_network" "main" {
  name                    = "main-network"
  auto_create_subnetworks = false
}

3.4 多 Provider 混用最佳实践

  • 命名规范: 为 Provider 别名使用清晰、一致的命名,如 aws.europe、azurerm.dev、google.asia,避免使用模糊的 aws.primary、aws.secondary。
  • 模块化封装: 将每个云平台的资源封装到独立的子模块中,在根模块中通过 Provider 传递实现解耦。
  • 状态隔离: 对于生产环境和开发环境,建议使用不同的 Terraform 工作区(Workspace)或不同的后端状态文件,避免状态混淆。
  • 依赖管理: 跨云资源之间的依赖关系使用 depends_on 或数据源(Data Source)显式声明,避免隐式依赖导致的执行顺序问题。
  • 凭证最小化: 每个 Provider 实例只授予其管理资源所需的最小权限,遵循云平台的最小权限原则。
跨云编排要点: 在多 Provider 混用模式下,Terraform 会并行执行各 Provider 的资源操作。如果跨云资源之间存在依赖关系(如需要从 AWS 获取 VPC ID 后创建 Azure 对等连接),必须使用 data 数据源或 terraform_remote_state 来获取输出值,确保执行顺序正确。

3.5 Provider 版本管理与锁定

在跨云项目中,管理多个 Provider 的版本至关重要。使用 required_providers 块锁定 Provider 版本,避免因版本升级导致的兼容性问题。

terraform {
  required_version = ">= 1.5.0"

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

执行 terraform init 后,Terraform 会生成 .terraform.lock.hcl 文件,锁定所有 Provider 的精确版本。将该文件纳入版本控制,确保团队和 CI/CD 环境使用一致的 Provider 版本。