Verwenden Sie terraform, um eine Lambda-Funktion einzurichten, die von einer geplanten Ereignisquelle ausgelöst wird

75

Ich möchte alle fünf Minuten eine AWS-Lambda-Funktion ausführen. In der AWS Management Console ist dies auf der Registerkarte "Ereignisquellen" der Lambda-Funktion einfach einzurichten. Wie richte ich es jedoch mit Terraform ein ?

Ich habe versucht, eine aws_lambda_event_source_mappingRessource zu verwenden , aber es stellt sich heraus, dass die verwendete API nur Ereignisse von Kinesis und DynamoDB unterstützt. Wenn ich versuche, es mit einer geplanten Ereignisquelle zu verwenden, läuft die Erstellung ab.

Vebjorn Ljosa
quelle
In der Konsole kann ich Folgendes sehen : ! [Bildbeschreibung hier eingeben ] ( i.stack.imgur.com/Qh0w7.png ) Obwohl der Regelstatus "AKTIVIERT" lautet, muss ich den Trigger selbst aktivieren . Ich bin mir nicht sicher, warum Terraform dies nicht selbst tut.
Yangmillstheory

Antworten:

147

Sie können eine aws_cloudwatch_event_targetRessource verwenden, um die geplante Ereignisquelle (Ereignisregel) mit Ihrer Lambda-Funktion zu verknüpfen. Sie müssen ihm die Berechtigung erteilen, Ihre Lambda-Funktion aufzurufen. Sie können hierfür eine aws_lambda_permissionRessource verwenden.

Beispiel:

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}"
}
Vebjorn Ljosa
quelle
1
Irgendwelche Tipps zur Fehlerbehebung? Ich kann in der Konsole sehen, dass die Cloudwatch-Ereignisregel korrekt aussieht und in der Lambda-Konsole als Auslöser aufgeführt ist. Es scheint, als würde der Timer ausgelöst, aber die Aufrufe sind nicht erfolgreich und ich sehe keine Hinweise darauf, dass das Lambda in Cloudwatch-Protokollen aufgerufen wird. Gibt es Protokolle für den Cloudwatch-Ereignis-Timer selbst?
Peter Lyons
Mit welcher Nutzlast wird die Funktion hier aufgerufen?
xtra
1
@xtra: Beispiel, wie das Ereignis aussehen könnte: docs.aws.amazon.com/AmazonCloudWatch/latest/events/…
Vebjorn Ljosa
2
Hat für mich gearbeitet. Eigentlich fehlte mir die aws_lambda_permission. Wenn wir die CW-Regel manuell erstellen, führt AWS dies aus. Aber für Terraform müssen wir dies auch aufrufen.
Anuradha Fernando
5

Die Antwort von Verbjorns Ljosa enthält nur die Berechtigung für Cloudwatch, das Lambda aufzurufen. Haben Sie die richtige Richtlinie und iam-Rolle angegeben, mit der das Lambda seine Aktionen ausführen kann?

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

mit assume_role_policy.json

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

und eine Richtlinie, die auf die obige Ressourcen-IAM-Rolle verweist, dh so etwas wie

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

und schließlich der json, der die Politik spezifiziert , 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"
}

Beachten Sie, dass Sie keine Ressourcenbeschränkung für die protokollbezogenen Aktionen angeben können. abc:SomeActionkönnte ssm:GetParametermit einer begleitenden Ressource arn wie sein"arn:aws:ssm:us-east-1:${your-aws-account-id}:parameter/some/parameter/path/*

johan mårtensson
quelle
1

Als Ergänzung zur akzeptierten Antwort. Oft möchte man, dass die Zip-Datei für das Lambda auch von Terraform erstellt wird. Dazu kann man die Datenquelle archive_file verwenden :

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

Das ist besonders hilfreich , wenn der Code unter Versionskontrolle ist, denn dann können Sie das Add check_foo.zipauf die .gitignoreund es kann nie eine missmatch zwischen der Zip - Datei und dem Quellcode sein , dass es basiert.

Falk Tandetzky
quelle