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


75

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

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


在控制台中,我可以看到以下内容:![在此处输入图像描述](i.stack.imgur.com/Qh0w7.png)即使它说规则状态为“ ENABLED”,我仍然必须启用触发器本身。不知道为什么Terraform本身不这样做。
yangmillstheory

Answers:


147

您可以使用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}"
}

1
关于此问题的任何提示吗?我可以在控制台中看到cloudwatch事件规则看起来正确,并且在lambda控制台中它被列为触发器。似乎计时器正在触发,但是调用未成功,并且我看不到任何证据都可以在cloudwatch日志中调用lambda。cloudwatch事件计时器本身是否有任何日志?
彼得·里昂斯

函数在此处调用的有效负载是什么?
xtra

1
@xtra:例如什么样的事件可能看起来像:docs.aws.amazon.com/AmazonCloudWatch/latest/events/...
Vebjorn Ljosa

2
为我工作。实际上我缺少的是aws_lambda_permission。当我们手动创建CW规则时,AWS会这样做。但是对于Terraform,我们也需要调用它。
Anuradha Fernando

5

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/*


1

作为已接受答案的补充。通常,人们常常希望通过terraform创建lambda的zip文件。为此,可以使用archive_file数据源

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文件与其所基于的源代码之间绝不会出现不匹配的情况。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.