Use terraform to set up a lambda function triggered by a scheduled event source

I would like to run an AWS lambda function every five minutes. In the AWS Management Console this is easy to set up, under the lambda function's "Event Sources" tab, but how do I set it up with Terraform?

I tried to use an aws_lambda_event_source_mapping resource, but it turns out that the API it uses only supports events from Kinesis and DynamoDB. When I try to use it with a scheduled event source, creation times out.

73151 次浏览

You can use an aws_cloudwatch_event_target resource to tie the scheduled event source (event rule) to your lambda function. You need to grant it permission to invoke your lambda function; you can use an aws_lambda_permission resource for this.

Example:

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
}

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"
}

最后是指定策略 check-foo-policy.json的 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"
}

请注意,不能为与日志相关的操作指定 Resource 限制。abc:SomeAction可能是 ssm:GetParameter,带有一个类似于 "arn:aws:ssm:us-east-1:${your-aws-account-id}:parameter/some/parameter/path/*的资源数组

作为公认答案的补充。通常情况下,人们希望通过 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中,并且压缩文件和它所基于的源代码之间永远不会出现不匹配。