使用CloudFormation更新现有的日志组

时间:2019-03-13 08:55:21

标签: amazon-web-services amazon-cloudformation amazon-cloudwatch

我有一个lambda,它具有一个日志组,例如LG-1,其保留时间设置为“永不过期”(默认)。我需要将此“永不过期”更改为1个月。我正在使用CloudFormation进行此操作。由于日志组已经存在,当我尝试使用模板中的更改再次部署lambda时:

LambdaFunctionLogGroup:
Type: 'AWS::Logs::LogGroup'
DependsOn: MyLambda
Properties:
  RetentionInDays: 30
  LogGroupName: !Join 
    - ''
    - - /aws/lambda/
      - !Ref MyLambda

更新失败,并显示错误:

  

[LogGroup名称]已经存在。

一种可行的解决方案是删除日志组,然后再次进行新的更改以创建日志组,如上图所示。

但是我需要在不删除日志组的情况下执行此操作,因为这将导致删除我以前拥有的所有日志。

有没有可行的解决方法?

3 个答案:

答案 0 :(得分:3)

我认为不可能从CF中操纵已经存在于堆栈之外的资源。

一种解决方法是更改​​my-lambda-v2之类的Lambda的名称,以将旧日志组与新日志组保持在一起。

一个月后,您可以删除旧的。

答案 1 :(得分:1)

在cloudformation模板中使用customresource支持的lambda。自定义资源将在第一次时自动触发,并更新现有日志组的保留策略。如果需要,可以每次触发一次定制资源lambda,然后使用jinja2之类的模板引擎。

import boto3

client = boto3.client('logs')
response = client.put_retention_policy(
    logGroupName='string',
    retentionInDays=123
)

您基本上可以使用“自定义资源”使CF模板(几乎)做您想做的一切

更多信息(Boto3,您可以找到所使用语言的相应SDK)-https://boto3.amazonaws.com/v1/documentation/api/1.9.42/reference/services/logs.html#CloudWatchLogs.Client.put_retention_policy

编辑:在CloudFormation模板中,它看起来类似于以下内容:

  LogRetentionSetFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src
      Handler: set_retention_period.handler
      Role: !GetAtt LambdaRole.Arn
      DeploymentPreference:
        Type: AllAtOnce

  PermissionForLogRetentionSetup:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:invokeFunction
      FunctionName:
        Fn::GetAtt: [ LogRetentionSetFunction, Arn ]
      Principal: lambda.amazonaws.com

  InvokeLambdaFunctionToSetLogRetention:
    DependsOn: [PermissionForLogRetentionSetup]
    Type: Custom::SetLogRetention
    Properties:
      ServiceToken: !GetAtt LogRetentionSetFunction.Arn
      StackName: !Ref AWS::StackName
      AnyVariable: "Choose whatever you want to send"     
      Tags:
        'owner': !Ref owner
        'task': !Ref task

lambda函数将具有根据我之前指定的代码设置日志保留的代码。

有关更多信息,请谷歌“自定义资源支持的lambda”。另外,为了让您早日入门,我在下面添加了墨水: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html

答案 2 :(得分:0)

@ttulka回答:

“ ..无法从CF中操纵已经存在于堆栈之外的资源。”

但是实际上问题比这更普遍,并且适用于在堆栈内部 创建的资源。它与AWS CloudFormation资源"Replacement policy"有关。对于某些资源,CloudFormation“更新”资源的方式是创建新资源,然后删除旧资源(这称为"Replacement"更新策略)。这意味着在一段时间内,您将拥有两个相同类型的资源,并且同时存在许多相同的属性。但是,如果某个资源属性必须是唯一的,则如果两个资源对此属性具有相同的值,则这两个资源不能同时存在,因此... CloudFormation会崩溃。

AWS::Logs::LogGroup.LogGroupName属性就是这样的属性之一。 AWS::CloudWatch::Alarm.AlarmName是另一个示例。

一种解决方法是取消设置名称,以便使用随机名称,执行更新,然后将名称重新设置为可预测的固定值,然后再次更新。


Rant:这是一个烦人的问题,确实不应该存在。即AWS CF应该足够聪明,不必使用这种奇怪的笨拙资源替换实现。但是...这就是适合您的AWS CF ...