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 的资源,并实现跨云资源池的编排。
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 版本。