如何通过Terraform跨区域部署存储在us-east-1 S3桶的Lambda代码?
Absolutely, you can deploy Lambda code from a single-region S3 bucket across regions using Terraform—you just need to work around S3's regional endpoint restriction that’s causing that PermanentRedirect error. Here are two reliable approaches:
Approach 1: Use S3 Cross-Region Replication (CRR) (Recommended)
This method automatically syncs your Lambda code from the us-east-1 bucket to a dedicated us-west-2 bucket. Lambda can then pull the code from a same-region bucket, which eliminates the redirect issue entirely. It’s ideal for ongoing deployments since it keeps your code in sync automatically.
First, set up two AWS providers (one for each region) in your Terraform config, then configure replication:
# Configure AWS providers for both regions provider "aws" { alias = "us_east_1" region = "us-east-1" } provider "aws" { alias = "us_west_2" region = "us-west-2" } # Source bucket (pre-existing in us-east-1) data "aws_s3_bucket" "lambda_source" { provider = aws.us_east_1 bucket = "your-precreated-us-east-1-bucket" } # Target bucket in us-west-2 for replicated code resource "aws_s3_bucket" "lambda_target" { provider = aws.us_west_2 bucket = "your-lambda-code-us-west-2" versioning { enabled = true # Required for CRR } } # IAM role for S3 replication resource "aws_iam_role" "s3_replication_role" { name = "lambda-code-replication-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "s3.amazonaws.com" } } ] }) } # Policy to grant replication permissions resource "aws_iam_role_policy" "s3_replication_policy" { name = "lambda-code-replication-policy" role = aws_iam_role.s3_replication_role.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = ["s3:GetObjectVersionForReplication", "s3:GetObjectVersionAcl"] Effect = "Allow" Resource = "${data.aws_s3_bucket.lambda_source.arn}/path/to/your/lambda.zip" }, { Action = ["s3:ReplicateObject", "s3:ReplicateTags"] Effect = "Allow" Resource = "${aws_s3_bucket.lambda_target.arn}/path/to/your/lambda.zip" } ] }) } # Enable replication from source to target bucket resource "aws_s3_bucket_replication_configuration" "lambda_code_replication" { provider = aws.us_east_1 bucket = data.aws_s3_bucket.lambda_source.name role = aws_iam_role.s3_replication_role.arn rule { id = "replicate-lambda-code" status = "Enabled" destination { bucket = aws_s3_bucket.lambda_target.arn storage_class = "STANDARD" } filter { prefix = "path/to/your/" # Match the prefix where your Lambda code lives } } } # Deploy Lambda in us-west-2 using the replicated bucket resource "aws_lambda_function" "cross_region_lambda" { provider = aws.us_west_2 function_name = "my-cross-region-function" s3_bucket = aws_s3_bucket.lambda_target.name s3_key = "path/to/your/lambda.zip" handler = "index.handler" runtime = "nodejs18.x" # Adjust to your runtime role = aws_iam_role.lambda_exec_role.arn # Create this role separately with Lambda permissions }
Approach 2: Copy Code to Target Region Bucket During Deployment
If you don’t want permanent replication, you can copy the Lambda code from the us-east-1 bucket to a temporary us-west-2 bucket as part of your Terraform workflow. This works well for one-off deployments.
We’ll use a null_resource with the AWS CLI to handle the cross-region copy:
# Configure dual-region providers (same as Approach 1) provider "aws" { alias = "us_east_1" region = "us-east-1" } provider "aws" { alias = "us_west_2" region = "us-west-2" } # Temporary bucket in us-west-2 resource "aws_s3_bucket" "temp_lambda_bucket" { provider = aws.us_west_2 bucket = "temp-lambda-code-us-west-2" } # Fetch metadata from the source S3 object to trigger updates when code changes data "aws_s3_object" "lambda_source_code" { provider = aws.us_east_1 bucket = "your-precreated-us-east-1-bucket" key = "path/to/your/lambda.zip" } # Copy code from us-east-1 to us-west-2 using AWS CLI resource "null_resource" "copy_lambda_code" { triggers = { source_etag = data.aws_s3_object.lambda_source_code.etag # Re-run if code changes } provisioner "local-exec" { command = "aws s3 cp s3://${data.aws_s3_object.lambda_source_code.bucket}/${data.aws_s3_object.lambda_source_code.key} s3://${aws_s3_bucket.temp_lambda_bucket.name}/lambda.zip --region us-west-2" } } # Deploy Lambda using the temporary bucket resource "aws_lambda_function" "cross_region_lambda" { provider = aws.us_west_2 function_name = "my-cross-region-function" s3_bucket = aws_s3_bucket.temp_lambda_bucket.name s3_key = "lambda.zip" handler = "index.handler" runtime = "nodejs18.x" role = aws_iam_role.lambda_exec_role.arn depends_on = [null_resource.copy_lambda_code] # Wait for copy to finish }
Why You Saw That Error
When you tried to point the us-west-2 Lambda directly to the us-east-1 S3 bucket, Lambda used the us-west-2 S3 endpoint (s3.us-west-2.amazonaws.com) to fetch the code. S3 responded with a redirect because the bucket lives in a different region, but Lambda’s API doesn’t follow redirects—hence the InvalidParameterValueException.
内容的提问来源于stack exchange,提问作者Todd

