Terraform CloudWatch 保留逻辑

5
我正在尝试为我的terraform脚本添加逻辑,以便在创建lambda时添加CW保留逻辑,以便我们的日志在30天后清除。 我所看到的是,当运行terraform以更新先前部署的lambda(在添加新保留逻辑之前)时,我的作业失败,并显示以下错误信息。
aws_cloudwatch_log_group.lambda-deploy:发生1个错误: aws_cloudwatch_log_group.lambda-deploy:创建CloudWatch Log Group失败:ResourceAlreadyExistsException:指定的日志组已存在状态代码:400,请求ID:e500eb50-4a81-11e9-9c08-7152b4a0ad31:CloudWatch日志组'/aws/lambda/{lambda-name}'已经存在。
以下是我设置terraform代码的方式:
resource "aws_lambda_function" "lambda-deploy" {
  filename      = "${var.filename}"
  function_name = "${var.functionname}"
  role          = "${var.role}"
  handler       = "${var.handler}"
  runtime       = "${var.runtime}"
  publish       = "${var.publish}"
  memory_size   = "${var.memory_size}"
  timeout       = "${var.timeout}"
  description   = "${var.description}"

  layers = "${var.layers}"

  environment {
    variables = "${var.envVars}"
  }

  tags {
    PLATFORM        = "${var.tag_PLATFORM}"
    BUSINESS_UNIT   = "${var.tag_BUSINESS_UNIT}"
    CLIENT          = "${var.tag_CLIENT}"
    BUSINESS_REGION = "${var.tag_BUSINESS_REGION}"
  }

  vpc_config {
    subnet_ids         = "${var.subnet_ids}"
    security_group_ids = "${var.security_group_ids}"
  }
}

#Below logic will add cloud watch retention logic so logs rotate after 30 days.
resource "aws_cloudwatch_log_group" "lambda-deploy" {
  name              = "/aws/lambda/${aws_lambda_function.lambda-deploy.function_name}"
  retention_in_days = "30"
}

我的问题是,aws_cloudwatch_log_group 资源能否检查 CloudWatch 日志组是否已创建并仅更新保留策略,而不是尝试创建日志组?
3个回答

3
  1. 注释掉name参数

例如,上面的例子:

resource "aws_cloudwatch_log_group" "lambda-deploy" {
  name = "/aws/lambda/${aws_lambda_function.lambda-deploy.function_name}"
  retention_in_days = "30"
}  

Becomes:

resource "aws_cloudwatch_log_group" "lambda-deploy" {
  #name = "/aws/lambda/${aws_lambda_function.lambda-deploy.function_name}"
  retention_in_days = "30"
}
  1. 导入资源

    terraform import aws_cloudwatch_log_group.lambda-deploy /aws/lambda/${aws_lambda_function.lambda-deploy.function_name}

这里的${aws_lambda_function.lambda-deploy.function_name}是指在AWS上的函数名称。

  1. 取消注释'name'参数并运行terraform plan,你的日志组现在已由terraform管理...轻松愉快!

“Where ${aws_lambda_function.lambda-deploy.function_name} is what is in AWS.” 这句话的意思不太清楚,请您详细说明一下? - nunop
我不明白你为什么注释掉了名称,然后又取消了注释。这是没有必要的(如果您的日志组是从已标记的 git 存储库加载超过 1 个模块,则会带来严重的麻烦)。只需用“/aws/lambda/function_name”名称创建日志组,像 #2 中一样导入它,然后应用于同步事物即可。 - user1169420

0

从技术上讲,它可以检测到是否存在并选择性地不创建它。假设你可以创建一个数据块来导入预先存在的日志组,然后使用动态计数的资源来打开或关闭它。但是你不想这样做,这种奇怪的黑客将永远存在于你的基础架构代码中。你希望保持你的terraform干净,并且专注于从头开始重新创建你的基础架构。

假设你已经有了一个lambda函数,该函数使用AWSLambdaBasicExecutionRole在terraform之外创建了自己的日志组,并且没有保留设置,现在你想要在terraform中添加保留设置控制,你会遇到一些麻烦。Terraform将想要创建该日志组,因为它不知道它已经存在,但是无法创建,因为名称正在使用中。

因此,您必须导入现有的日志组以映射到您在terraform中声明的资源,然后当您应用时,terraform将调整现有的日志组以符合您的TF配置。

今天早上我遇到了这种情况,我的lambda函数(和其他东西)是在一个模块中创建的,该模块加载在大约10个不同的堆栈(在3个环境中)中,我不想完全手动完成这个过程,所以我将分享这个小型bash命令集,以使它更容易。这很hacky,并且依赖于(不断变化的)terraform控制台输出,但对于我来说,在Terraform v0.14.4上,应用程序的输出会失败,如下所示:
以下命令将捕获该应用程序输出,从最后两行中解析出资源名称空间和aws名称,然后执行导入操作。这不是一个优化的脚本,只是我为完成工作而凑合出来的东西。
terraform apply 2>&1 | tee out.txt
resource=$(cat out.txt | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g" | grep Creating | grep cloudwatch | cut -f 1 -d:)
name=$(cat out.txt | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g" | grep Creating | grep exists | cut -f 2 -d\')
terraform import $resource $name
terraform apply
rm out.txt

错误:没有配置文件应用程序需要存在配置。没有配置的情况下应用会标记所有内容为销毁,这通常不是所需的。如果您想要销毁所有内容,请运行'terraform destroy'。 - DragonKnight

0

由于您没有向我们展示Lambda函数的IAM角色策略,我只能猜测。

我的感觉是Lambda的IAM角色和策略具有logs:CreateLogGroup权限。因此,Lambda函数将负责创建日志组(如果不存在)

当您进行更新时,此日志组不受Terraform管理,它会报告问题。

您可以尝试删除logs:CreateLogGroup权限并删除日志组,然后再次尝试吗?


你也可以导入现有的日志组,而不是删除它并让Terraform重新创建它。 - ydaetskcoR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接