如何通过单次terraform apply操作将资源部署至多个指定AWS账户
Great question! You absolutely can deploy resources to multiple specified AWS accounts in a single terraform apply without repeating your Terraform code—dynamic provider configuration is exactly the solution here, and it works seamlessly with the IAM roles you've already set up in each target account. Here's a step-by-step breakdown of how to implement this:
1. Define Your Target Accounts in tfvars
First, configure the list of accounts you want to deploy to in your terraform.tfvars (or a dedicated variables file). This keeps your account details centralized and easy to update:
target_accounts = [ { account_id = "123456789012" role_name = "terraform-deployment-role" # Your pre-created IAM role }, { account_id = "234567890123" role_name = "terraform-deployment-role" }, # Add more accounts as needed ]
2. Configure Dynamic Providers with for_each
Terraform supports dynamic provider blocks, which let you generate a provider instance for each target account using for_each. Each provider gets an alias (we'll use the account ID for clarity) and is configured to assume the corresponding IAM role:
variable "target_accounts" { type = list(object({ account_id = string role_name = string })) description = "List of AWS accounts and their Terraform deployment IAM roles" } # Generate a provider for each target account dynamic "provider" { for_each = var.target_accounts iterator = acc content { alias = acc.value.account_id region = "us-east-1" # Make this a variable if you need multi-region support assume_role { role_arn = "arn:aws:iam::${acc.value.account_id}:role/${acc.value.role_name}" } } }
3. Map Resources to Each Provider
When defining your resources (or modules), use for_each again to create an instance of the resource for each account, and link it to the corresponding provider via the alias:
Example: Deploy an S3 Bucket to Each Account
resource "aws_s3_bucket" "shared_bucket" { for_each = { for acc in var.target_accounts : acc.account_id => acc } provider = aws[each.key] # Reference the provider alias for this account bucket = "shared-config-bucket-${each.key}" # Add your bucket settings here (versioning, policy, etc.) }
Example: Reuse a Module Across Accounts
If you're using Terraform modules, pass the provider alias to the module using the providers block to ensure the module uses the correct account's provider:
module "vpc_deployment" { for_each = { for acc in var.target_accounts : acc.account_id => acc } source = "./modules/vpc" providers = { aws = aws[each.key] } # Pass module variables here (e.g., vpc_cidr, subnet_count) vpc_cidr = "10.${each.value.account_id[-2:]}.0.0/16" }
Key Notes to Keep in Mind
- Permissions: Ensure the credentials running Terraform (whether local AWS CLI creds or an execution role) are allowed to assume each target account's IAM role. Double-check the trust policy on each target role to confirm it permits your initiating account/user.
- State Management: All resources across all accounts will live in a single Terraform state file. This makes it easy to manage deployments centrally, but be sure to secure and back up your state properly (e.g., using an S3 backend with versioning and encryption).
- Flexibility: If you need to deploy to different regions per account, simply add a
regionfield to yourtarget_accountsobjects and reference it in the dynamic provider block.
You mentioned thinking dynamic providers or role switching wouldn't work, but this approach is officially supported by Terraform and is the standard way to handle multi-account deployments without code duplication. By pairing dynamic providers with for_each on your resources, you can deploy to as many specified accounts as needed in one terraform apply run.
内容的提问来源于stack exchange,提问作者MFabricanti

