處理 Amazon ECS 事件 - Amazon Elastic Container Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

處理 Amazon ECS 事件

Amazon ECS 會傳送事件至少一次。這意味著您可能會收到給定事件的多個副本。此外,可能不會依事件發生順序將事件交付至事件接聽程式。

為了正確排序事件,每個事件的 detail 區段都會包含 version 屬性。每次資源變更狀態時,此 version 都會遞增。重複事件在 detail 物件中具有相同的 version。如果您要將 Amazon ECS 容器執行個體和任務狀態複寫在一起 EventBridge,則可以將 Amazon ECS API 報告的資源版本與資源中version EventBridge 報告的版本進行比較,以確認事件串流中的版本是最新的。較高版本屬性編號的事件應該視為比較低版本編號的事件晚發生。

範例:處理 AWS Lambda 函式中的事件

下列範例顯示使用 Python 3.9 撰寫的 Lambda 函數,以同時擷取任務和容器執行個體狀態變更事件,並將其儲存至兩個 Amazon DynamoDB 資料表中的其中一個:

  • ECS CtrInstanceState — 儲存容器執行個體的最新狀態。資料表 ID 是容器執行個體的 containerInstanceArn 值。

  • ECS TaskState — 儲存任務的最新狀態。資料表 ID 是任務的 taskArn 值。

import json import boto3 def lambda_handler(event, context): id_name = "" new_record = {} # For debugging so you can see raw event format. print('Here is the event:') print((json.dumps(event))) if event["source"] != "aws.ecs": raise ValueError("Function only supports input from events with a source type of: aws.ecs") # Switch on task/container events. table_name = "" if event["detail-type"] == "ECS Task State Change": table_name = "ECSTaskState" id_name = "taskArn" event_id = event["detail"]["taskArn"] elif event["detail-type"] == "ECS Container Instance State Change": table_name = "ECSCtrInstanceState" id_name = "containerInstanceArn" event_id = event["detail"]["containerInstanceArn"] else: raise ValueError("detail-type for event is not a supported type. Exiting without saving event.") new_record["cw_version"] = event["version"] new_record.update(event["detail"]) # "status" is a reserved word in DDB, but it appears in containerPort # state change messages. if "status" in event: new_record["current_status"] = event["status"] new_record.pop("status") # Look first to see if you have received a newer version of an event ID. # If the version is OLDER than what you have on file, do not process it. # Otherwise, update the associated record with this latest information. print("Looking for recent event with same ID...") dynamodb = boto3.resource("dynamodb", region_name="us-east-1") table = dynamodb.Table(table_name) saved_event = table.get_item( Key={ id_name : event_id } ) if "Item" in saved_event: # Compare events and reconcile. print(("EXISTING EVENT DETECTED: Id " + event_id + " - reconciling")) if saved_event["Item"]["version"] < event["detail"]["version"]: print("Received event is a more recent version than the stored event - updating") table.put_item( Item=new_record ) else: print("Received event is an older version than the stored event - ignoring") else: print(("Saving new event - ID " + event_id)) table.put_item( Item=new_record )

下列 Fargate 範例顯示使用 Python 3.9 撰寫的 Lambda 函數,該函數可擷取任務狀態變更事件,並將其儲存至下列 Amazon DynamoDB 表格:

import json import boto3 def lambda_handler(event, context): id_name = "" new_record = {} # For debugging so you can see raw event format. print('Here is the event:') print((json.dumps(event))) if event["source"] != "aws.ecs": raise ValueError("Function only supports input from events with a source type of: aws.ecs") # Switch on task/container events. table_name = "" if event["detail-type"] == "ECS Task State Change": table_name = "ECSTaskState" id_name = "taskArn" event_id = event["detail"]["taskArn"] else: raise ValueError("detail-type for event is not a supported type. Exiting without saving event.") new_record["cw_version"] = event["version"] new_record.update(event["detail"]) # "status" is a reserved word in DDB, but it appears in containerPort # state change messages. if "status" in event: new_record["current_status"] = event["status"] new_record.pop("status") # Look first to see if you have received a newer version of an event ID. # If the version is OLDER than what you have on file, do not process it. # Otherwise, update the associated record with this latest information. print("Looking for recent event with same ID...") dynamodb = boto3.resource("dynamodb", region_name="us-east-1") table = dynamodb.Table(table_name) saved_event = table.get_item( Key={ id_name : event_id } ) if "Item" in saved_event: # Compare events and reconcile. print(("EXISTING EVENT DETECTED: Id " + event_id + " - reconciling")) if saved_event["Item"]["version"] < event["detail"]["version"]: print("Received event is a more recent version than the stored event - updating") table.put_item( Item=new_record ) else: print("Received event is an older version than the stored event - ignoring") else: print(("Saving new event - ID " + event_id)) table.put_item( Item=new_record )