Lambda Terraform cloudwatch保留逻辑

Lambda Terraform cloudwatch保留逻辑,lambda,terraform,serverless,Lambda,Terraform,Serverless,我正在尝试将逻辑添加到terraform脚本中,以便在创建lambda时添加CW保留逻辑,以便在30天后清除日志。我看到的是,当运行terraform来更新现有的lambda(在添加新的保留逻辑之前部署的)时,我的作业会失败,并出现以下错误 aws_cloudwatch_log_group.lambda-deploy:发生1个错误: aws_cloudwatch_log_group.lambda-deploy:创建cloudwatch日志组失败:ResourceReadyExistsExce

我正在尝试将逻辑添加到terraform脚本中,以便在创建lambda时添加CW保留逻辑,以便在30天后清除日志。我看到的是,当运行terraform来更新现有的lambda(在添加新的保留逻辑之前部署的)时,我的作业会失败,并出现以下错误

  • aws_cloudwatch_log_group.lambda-deploy:发生1个错误:

  • aws_cloudwatch_log_group.lambda-deploy:创建cloudwatch日志组失败:ResourceReadyExistsException:指定的日志组已存在状态代码:400,请求id:e500eb50-4a81-11e9-9c08-7152b4a0ad31:cloudwatch日志组“/aws/lambda/{lambda name}”已存在

下面是我如何设置地形代码的:

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\u cloudwatch\u log\u group资源是否可以检查是否已经创建了cloudwatch组,并且只更新保留策略而不是尝试创建日志组?

因为您没有向我们展示lambda函数的iam角色策略,我不得不猜测

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

更新时,此日志组不由terraform管理,它将报告问题

能否删除权限
日志:CreateLogGroup
并删除日志组,然后重试

  • 注释掉name参数
  • 例如,上面的例子:

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

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

    terraform导入aws\u cloudwatch\u log\u group.lambda-deploy/aws/lambda/${aws\u lambda\u function.lambda deploy.function\u name}

  • 其中,
    ${aws\u lambda\u function.lambda deploy.function\u name}
    是aws中的内容

  • 取消对“name”参数的注释并运行
    terraform plan
    ,您的日志组现在由terraform管理…呸
    从技术上讲,它可以检测它是否存在,也可以选择不创建它。假设,您可以创建一个数据块来导入预先存在的日志组,然后创建一个具有动态计数的资源来打开或关闭创建。但你不会想这样做的,wierd黑客会永远在你的infra代码中。您希望保持您的地形干净,并且能够从头开始重新创建您的基础设施

    假设您已经有了一个lambda,该lambda具有AWSLambdaBasicExecutionRole,在terraform之外创建了自己的日志组,而没有保留设置,现在您想要将保留设置控件添加到terraform,您就有点麻烦了。Terraform希望创建该日志组,因为它不知道它存在,但无法创建,因为名称正在使用中

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

    今天早上我正处于这种情况,我的lambda(和其他东西)是在一个模块中创建的,它被加载到大约10个不同的堆栈中(在3种环境中),我不想完全手工完成这项工作,所以我将与大家分享我编写的一组bash命令,以使它更简单。这是有问题的,取决于(不断变化的)terraform控制台输出,但对于我今天在terraform v0.14.4上的应用程序,其输出将失败如下:

    是否要执行这些操作?Terraform将执行以下操作: 上述行动。只接受“是”进行批准

    输入一个值:是

    module.api\u gateway.aws\u cloudwatch\u log\u group.this:正在创建

    错误:创建CloudWatch日志组失败: ResourceReadyExistsException:指定的日志组已存在 存在:CloudWatch日志组 “API-Gateway-Execution-Logs_7pnv677kwa/0”已存在

    以下命令将捕获应用输出,解析最后两行中的资源名称空间和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重新创建它。不清楚您所说的“aws中的${aws_lambda_function.lambda deploy.function_name}是什么意思。您能详细说明一下吗?我不明白您为什么要注释掉这个名称,然后取消注释它。这是不必要的(如果您的日志组是从标记的git repos深度加载的1个或多个模块,这将是一个严重的麻烦)。只需使用/aws/lambda/function_名称创建日志组,像#2中那样导入它,然后应用于同步。