使用 terraform 设置由预定事件源触发的 lambda 函数

Posted

技术标签:

【中文标题】使用 terraform 设置由预定事件源触发的 lambda 函数【英文标题】:Use terraform to set up a lambda function triggered by a scheduled event source 【发布时间】:2020-11-20 09:28:22 【问题描述】:

我想每五分钟运行一次 AWS lambda 函数。在 AWS 管理控制台中,这很容易在 lambda 函数的“事件源”选项卡下进行设置,但是如何使用 Terraform 进行设置?

我尝试使用an aws_lambda_event_source_mapping resource,但事实证明the API it uses 仅支持来自 Kinesis 和 DynamoDB 的事件。当我尝试将它与计划的事件源一起使用时,创建超时。

【问题讨论】:

在控制台中,我可以看到以下内容:![enter image description here](i.stack.imgur.com/Qh0w7.png) 即使它说规则状态是“启用”,我仍然必须启用触发器本身。不知道为什么 Terraform 自己不这样做。 【参考方案1】:

您可以使用aws_cloudwatch_event_target 资源将计划的事件源(事件规则)绑定到您的 lambda 函数。您需要授予它调用 lambda 函数的权限;您可以为此使用aws_lambda_permission 资源。

例子:

resource "aws_lambda_function" "check_foo" 
    filename = "check_foo.zip"
    function_name = "checkFoo"
    role = "arn:aws:iam::424242:role/something"
    handler = "index.handler"


resource "aws_cloudwatch_event_rule" "every_five_minutes" 
    name = "every-five-minutes"
    description = "Fires every five minutes"
    schedule_expression = "rate(5 minutes)"


resource "aws_cloudwatch_event_target" "check_foo_every_five_minutes" 
    rule = "$aws_cloudwatch_event_rule.every_five_minutes.name"
    target_id = "check_foo"
    arn = "$aws_lambda_function.check_foo.arn"


resource "aws_lambda_permission" "allow_cloudwatch_to_call_check_foo" 
    statement_id = "AllowExecutionFromCloudWatch"
    action = "lambda:InvokeFunction"
    function_name = "$aws_lambda_function.check_foo.function_name"
    principal = "events.amazonaws.com"
    source_arn = "$aws_cloudwatch_event_rule.every_five_minutes.arn"

【讨论】:

有什么技巧可以解决这个问题吗?我可以在控制台中看到 cloudwatch 事件规则看起来正确,并且在 lambda 控制台中它被列为触发器。似乎计时器正在触发,但调用没有成功,而且我没有看到在 cloudwatch 日志中调用 lambda 的证据。 CloudWatch 事件计时器本身是否有任何日志? 这里调用函数的payload是什么? @xtra:事件可能看起来的示例:docs.aws.amazon.com/AmazonCloudWatch/latest/events/… 为我工作。实际上我缺少的是 aws_lambda_permission。当我们手动创建 CW 规则时,AWS 会这样做。但是对于 Terraform,我们也需要调用它。 我使用上述所有资源部署了我的 terraform 代码,但在目标 lambda 函数的云监视中看不到日志。我可以看到在 Eventbridge 中创建的规则,并且目标也设置为 lambda 函数,但我看不到 lambda 函数中的触发器。我怎么知道它是否在预定的时间运行?任何帮助表示赞赏。谢谢【参考方案2】:

Verbjorns Ljosa 的回答仅包括 cloudwatch 调用 lambda 的权限。您是否指定了允许 lambda 执行其操作的正确策略和 iam 角色?

resource "aws_iam_role" "check_foo_role" 
  name="check-foo-assume-role"
  assume_role_policy="assume_role_policy.json"

assume_role_policy.json


  "Version": "2012-10-17",
  "Statement": [
    
      "Action": "sts:AssumeRole",
      "Principal": 
        "Service": "lambda.amazonaws.com"
      ,
      "Effect": "Allow",
      "Sid": ""
    
  ]

以及引用上述资源 iam 角色的策略,即像

resource "iam_role_policy" "check-foo-policy" 
  name="check-foo-lambda-policy"
  # referencing the iam role above
  role="$aws_iam_role.check_foo_role.id"
  policy="check-foo-policy.json"

最后是指定策略的 json,check-foo-policy.json


  "Version": "2012-10-17",
  "Statement": [
    
  "Effect": "Allow",
  "Action": [
    "logs:CreateLogGroup",
    "logs:CreateLogStream",
    "logs:PutLogEvents"
  ],
  "Resource": ["*"]
,

  "Effect": "Allow",
  "Action": [
    "abc:SomeAction",
    "abc:AnotherAction",
  ],
  "Resource": "some-arn-matching-the-actions"

请注意,您不能为与日志相关的操作指定资源限制。 abc:SomeAction 可能是 ssm:GetParameter,并带有一个附带的资源,例如 "arn:aws:ssm:us-east-1:$your-aws-account-id:parameter/some/parameter/path/*

【讨论】:

【参考方案3】:

作为已接受答案的补充。很多时候,人们希望 lambda 的 zip 文件也由 terraform 创建。为此,可以使用archive_file data source:

data "archive_file" "lambda_zip" 
    type        = "zip"
    source_dir  = "src"
    output_path = "check_foo.zip"


resource "aws_lambda_function" "check_foo" 
    filename = "check_foo.zip"
    function_name = "checkFoo"
    role = "arn:aws:iam::424242:role/something"
    handler = "index.handler"


# then the rest from the accepted answer to trigger this

如果代码受版本控制,这将特别有用,因为您可以将check_foo.zip 添加到.gitignore,并且 zip 文件和它所基于的源代码之间永远不会不匹配。

【讨论】:

以上是关于使用 terraform 设置由预定事件源触发的 lambda 函数的主要内容,如果未能解决你的问题,请参考以下文章

schedult 上的 aws 自定义事件以触发 lambda 使用 Terraform

如何将输入转换器用于 ECS Fargate 启动类型和 Terraform CloudWatch 事件触发器

如何将 AWS cloudwatch 事件添加到基于具有 terraform 的容器映像的 aws_lambda_function?

设置数据源时事件的触发

Terraform 多个 cloudwatch 事件触发相同的 lambda 函数

AVAudioPlayer 可以在预定义的时间间隔触发事件吗?