Terraform 创建 Lambda 函数时出错:ResourceConflictException 与 Terraform apply 刚刚创建的资源有关

aas*_*yas 6 terraform terraform-provider-aws

我正在账户的每个 AWS 区域中部署 Lambda 函数,但遇到了奇怪的问题:某些 AWS 区域的应用失败并显示以下错误消息

\n

Terraform 应用时出错

\n
Error: Error creating Lambda function: ResourceConflictException: Function already exist: log-forwarder\n{\n  RespMetadata: {\n    StatusCode: 409,\n    RequestID: "8cfd7260-7c4a-42d2-98c6-6619c7b2804f"\n  },\n  Message_: "Function already exist: log-forwarder",\n  Type: "User"\n}\n
Run Code Online (Sandbox Code Playgroud)\n

上述 Lambda 函数刚刚由失败的同一个 Terraform Apply 创建。

\n

terraform plan 和 init 不会抛出任何有关 TF 配置问题的错误。

\n

plan 和 init 均成功运行。

\n

下面是我的目录结构

\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 log_forwarder.tf\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 log_forwarder_lambdas\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.tf\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 providers.tf\n
Run Code Online (Sandbox Code Playgroud)\n

下面是我的providers.tf文件

\n
provider "aws" {\n  region  = "us-east-1"\n  version = "3.9.0"\n}\nprovider "aws" {\n  alias   = "us-east-2"\n  region  = "us-east-2"\n  version = "3.9.0"\n}\nprovider "aws" {\n  alias   = "us-west-2"\n  region  = "us-west-2"\n  version = "3.9.0"\n}  \nprovider "aws" {\n  alias   = "us-west-1"\n  region  = "us-west-1"\n  version = "3.9.0"\n}\nprovider "aws" {\n  alias   = "ca-central-1"\n  region  = "ca-central-1"\n  version = "3.9.0"\n}\n\n\n... with all the AWS Regions.\n
Run Code Online (Sandbox Code Playgroud)\n

以下是 tf 配置log_forwarder.tf

\n
terraform {\n  required_version = "0.12.25"\n\n  backend "s3" {\n    All the backend Config\n  }\n}\n\n\nresource "aws_iam_role" "log_forwarder" {\n  name = "LogForwarder"\n\n  assume_role_policy = <<EOF\n{\n  "Version": "2012-10-17",\n  "Statement": [\n    {\n      "Sid": "",\n      "Effect": "Allow",\n      "Principal": {\n        "Service": ["lambda.amazonaws.com"]\n      },\n      "Action": "sts:AssumeRole"\n    }\n  ]\n}\nEOF\n}\n\nresource "aws_iam_role_policy" "log_forwarder" {\n  name = "LogForwarder"\n  role = aws_iam_role.log_forwarder.id\n\n  policy = <<EOF\n{\n  "Version": "2012-10-17",\n  "Statement": [\n    {\n      "Effect": "Allow",\n      "Action": [\n        "lambda:ListTags",\n        "logs:CreateLogGroup",\n        "logs:CreateLogStream",\n        "logs:PutLogEvents"\n      ],\n      "Resource": [\n        "arn:aws:logs:*",\n        "arn:aws:lambda:*"\n      ]\n    },\n    {\n      "Effect": "Allow",\n      "Action": [\n        "lambda:InvokeFunction"\n      ],\n      "Resource": "*"\n    },\n        {\n    "Sid": "AWSDatadogPermissionsForCloudtrail",\n    "Effect": "Allow",\n    "Action": ["s3:ListBucket", "s3:GetBucketLocation", "s3:GetObject", "s3:ListObjects"],\n    "Resource": [\n        "arn:aws:s3:::BucketName",\n        "arn:aws:s3:::BucketName/*"\n    ]\n}\n\n  ]\n}\nEOF\n}\n\n\nmodule "DDLogForwarderUSEast1" {\n  source                = "./log_forwarder_lambdas"\n  dd_log_forwarder_role = aws_iam_role.log_forwarder.arn\n  region                = "us-east-1"\n\n}\n\nmodule "DDLogForwarderUSEast2" {\n  source                = "./log_forwarder_lambdas"\n  dd_log_forwarder_role = aws_iam_role.log_forwarder.arn\n  providers             = { aws = aws.us-east-2 }\n  region                = "us-east-2"\n}\n\nmodule "DDLogForwarderUSWest1" {\n  source                = "./log_forwarder_lambdas"\n  dd_log_forwarder_role = aws_iam_role.log_forwarder.arn\n  providers             = { aws = aws.us-west-1 }\n  region                = "us-west-1"\n}\n\nmodule "DDLogForwarderUSWest2" {\n  source                = "./log_forwarder_lambdas"\n  dd_log_forwarder_role = aws_iam_role.log_forwarder.arn\n  region                = "us-west-2"\n  providers             = { aws = aws.us-west-2 }\n}\n\nmodule "DDLogForwarderAPEast1" {\n  source                = "./log_forwarder_lambdas"\n  dd_log_forwarder_role = aws_iam_role.log_forwarder.arn\n  providers             = { aws = aws.ap-east-1 }\n  region                = "ap-east-1"\n}\n\nmodule "DDLogForwarderAPSouth1" {\n  source                = "./log_forwarder_lambdas"\n  dd_log_forwarder_role = aws_iam_role.log_forwarder.arn\n  region                = "ap-south-1"\n  providers             = { aws = aws.ap-south-1 }\n}\n\n... All AWS Regions with different providers \n
Run Code Online (Sandbox Code Playgroud)\n

TF 配置log_forwarder_lambdas/main.tf

\n
variable "region" {}\n\nvariable "account_id" {\n  default = "AWS Account Id"\n}\n\nvariable "dd_log_forwarder_role" {}\n\nvariable "exclude_at_match" {\n  default = "([A-Z]* RequestId: .*)"\n}\n\ndata "aws_s3_bucket" "cloudtrail_bucket" {\n  count  = var.region == "us-west-2" ? 1 : 0\n  bucket = "BucketName"\n}\n\n\nresource "aws_lambda_function" "log_forwarder" {\n  filename      = "${path.cwd}/log_forwarder_lambdas/aws-dd-forwarder-3.16.3.zip"\n  function_name = "log-forwarder"\n  role          = var.dd_log_forwarder_role\n  description   = "Gathers logs from targetted Cloudwatch Log Groups and sends them to DataDog"\n  handler       = "lambda_function.lambda_handler"\n  runtime       = "python3.7"\n  timeout       = 600\n  memory_size   = 1024\n  layers        = ["arn:aws:lambda:${var.region}:464622532012:layer:Datadog-Python37:11"]\n\n\n  environment {\n    variables = {\n      DD_ENHANCED_METRICS = false\n      EXCLUDE_AT_MATCH    = var.exclude_at_match\n    }\n  }\n}\n\nresource "aws_cloudwatch_log_group" "log_forwarder" {\n  name              = "/aws/lambda/${aws_lambda_function.log_forwarder.function_name}"\n  retention_in_days = 90\n}\n\nresource "aws_lambda_permission" "cloudtrail_bucket" {\n  count         = var.region == "us-west-2" ? 1 : 0\n  statement_id  = "AllowExecutionFromS3Bucket"\n  action        = "lambda:InvokeFunction"\n  function_name = aws_lambda_function.log_forwarder.arn\n  principal     = "s3.amazonaws.com"\n  source_arn    = element(data.aws_s3_bucket.cloudtrail_bucket.*.arn, count.index)\n}\n\nresource "aws_s3_bucket_notification" "cloudtrail_bucket_notification" {\n  count  = var.region == "us-west-2" ? 1 : 0\n  bucket = element(data.aws_s3_bucket.cloudtrail_bucket.*.id, count.index)\n\n\n  lambda_function {\n    lambda_function_arn = aws_lambda_function.log_forwarder.arn\n    events              = ["s3:ObjectCreated:*"]\n  }\n\n  depends_on = [aws_lambda_permission.cloudtrail_bucket, aws_cloudwatch_log_group.log_forwarder]\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在本例中我使用 TF 0.12.25。

\n

到目前为止我尝试过的事情。

\n
    \n
  1. 每次运行 Terraform init/plan/apply 循环时,从根模块中删除 .terraform 文件夹
  2. \n
  3. 我已经尝试尽可能地重构代码。
  4. \n
  5. 我在本地运行 TF 计划/应用周期,没有任何 CI。
  6. \n
\n

Jef*_*men 6

乍一看,Lambda 函数可能不处于您的 Terraform 状态(无论出于何种原因)。您是否更改过后端/删除了后端数据?

运行terraform showand/orterraform state show并查看冲突的 Lambda 函数是否位于您所在的州。
如果不是,但它已存在于 AWS 中,您可以将其导入。
请参阅此处: https: //registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function#import


更新:

根据您的评论,由于资源存在于 AWS 中但不存在于该州,因此这是一个预期错误。(Terraform 不知道资源存在,因此尝试创建它;AWS 知道它已经存在,因此返回错误。)

你有两个选择:

  • 删除AWS中的资源并再次运行Terraform;或者
  • 将现有资源导入 Terraform(推荐)。

尝试类似的方法:

terraform import module.DDLogForwarderUSEast1.aws_lambda_function.log-forwarder log-forwarder
Run Code Online (Sandbox Code Playgroud)

(如果在其他区域尝试此操作,请确保您设置了正确的提供商/区域!)