4. Provider配置与多环境认证
Terraform 本身并不直接调用云厂商 API,它通过 Provider 插件把 HCL 资源声明翻译成各云平台的 REST 调用。因此,Provider 配置是混合云编排的“入口层”:声明用哪个厂商、以什么身份、访问哪个区域或账号。本节围绕 Provider 声明、多账号多区域认证、环境变量与凭据管理、Provider 别名与多实例配置四条主线展开。
一、Provider 声明与版本约束
每个 Provider 都需要在 required_providers 中声明来源和版本约束,再在 provider 块中给出认证与区域参数。版本约束建议使用悲观约束 ~>,避免次版本升级引入破坏性变更。
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.40"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.95"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.220"
}
}
}
provider "aws" {
region = var.aws_region
}
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
注意 azurerm 的 features {} 块是必填项,即使为空也必须保留;alicloud 的 source 是 aliyun/alicloud,而非 hashicorp 命名空间,写错会导致 terraform init 拉取失败。
二、多账号与多区域认证
混合云场景下,同一厂商往往存在多个账号(如生产账号、测试账号)和多个区域。Terraform 通过 Provider 别名(alias)实现“同一 Provider 多实例”。每个实例拥有独立的认证身份和区域,资源通过 provider = aws.prod 显式绑定。
provider "aws" {
alias = "prod"
region = "cn-north-1"
assume_role {
role_arn = "arn:aws-cn:iam::111122223333:role/TerraformDeploy"
}
}
provider "aws" {
alias = "test"
region = "cn-northwest-1"
assume_role {
role_arn = "arn:aws-cn:iam::444455556666:role/TerraformDeploy"
}
}
resource "aws_s3_bucket" "logs" {
provider = aws.prod
bucket = "corp-prod-logs"
}
未指定 provider 的资源会落到默认 Provider(无 alias 的那个)。因此建议:默认 Provider 只用于单一环境,多环境一律显式绑定别名,避免“资源建错账号”这类高风险事故。跨账号访问通常配合 assume_role,由主账号角色切换到目标账号角色,凭据不落地。
三、环境变量与凭据管理
Provider 认证参数有明确的优先级:显式写在 provider 块中的值 > 环境变量 > 共享凭据文件。生产实践中应遵循“凭据不进代码”原则:HCL 中只保留区域、角色 ARN 等非敏感参数,密钥通过环境变量或外部凭据链注入。
| 云厂商 | 常用环境变量 | 凭据文件 |
|---|---|---|
| AWS | AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_PROFILE | ~/.aws/credentials |
| Azure | ARM_CLIENT_ID / ARM_CLIENT_SECRET / ARM_TENANT_ID / ARM_SUBSCRIPTION_ID | az login 缓存 |
| GCP | GOOGLE_APPLICATION_CREDENTIALS / GOOGLE_PROJECT | 服务账号 JSON |
| 阿里云 | ALICLOUD_ACCESS_KEY / ALICLOUD_SECRET_KEY / ALICLOUD_REGION | ~/.aliyun/config.json |
四、Provider 别名与多实例配置
别名不仅用于多账号,也用于同一账号下的多区域、多订阅。模块化时,Provider 需要通过 providers 参数显式传递给子模块,否则子模块会使用自己的默认 Provider,导致配置失效。
module "network_prod" {
source = "./modules/network"
providers = {
aws = aws.prod
}
vpc_cidr = "10.10.0.0/16"
}
子模块内部则用 configuration_aliases 声明它期望接收的别名:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
configuration_aliases = [aws.prod, aws.test]
}
}
}
下面这张图展示了多环境认证的整体数据流:凭据从环境变量或凭据文件进入 Provider 实例,经别名绑定后驱动不同账号/区域的资源,最终由 Terraform 状态文件统一记录。
五、常见排障要点
- 资源建到默认账号:检查资源是否遗漏
provider参数,或子模块未通过providers接收别名。 - init 拉取失败:核对
source命名空间,如阿里云为aliyun/alicloud。 - 凭据不生效:按“显式参数 > 环境变量 > 凭据文件”顺序排查,确认环境变量名拼写正确。
- 跨账号权限不足:检查
assume_role的信任策略是否允许当前身份扮演目标角色。
把 Provider 配置当作基础设施代码的“身份层”来治理:版本锁定、别名显式、凭据外置、模块透传,四者齐备后,混合云多环境编排才能稳定可复现。