本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
逐步解說:使用 Lambda 支援的自訂資源建立延遲機制
此逐步解說展示如何使用範例 CloudFormation 範本來設定和啟動 Lambda 支援的自訂資源。此範本會建立延遲機制,可暫停堆疊部署一段指定時間。當您需要在資源佈建期間刻意加入延遲時,例如等待資源穩定後再建立相依資源,這項功能相當實用。
注意
雖然先前建議 Lambda 後端自訂資源用於擷取 AMI IDs,但現在建議使用 AWS Systems Manager 參數。此方法可讓您的範本更具可重複使用性,且更易於維護。如需詳細資訊,請參閱從 Systems Manager Parameter Store 取得純文字值。
概觀
本操作指南使用的堆疊範例範本,會建立一個 Lambda 支援的自訂資源。此自訂資源會在堆疊建立期間加入可設定的延遲 (預設為 60 秒)。僅當自訂資源的屬性被修改時,堆疊更新期間才會發生延遲。
此範本會佈建以下資源:
-
自訂資源,
-
Lambda 函式,以及
-
讓 Lambda 將日誌寫入 CloudWatch 的 IAM 角色。
它還定義了兩個輸出:
-
函數實際等待的時間。
-
每次執行 Lambda 函式時產生的唯一識別碼。
注意
CloudFormation 是免費服務,但 Lambda 會根據您函數的請求次數和程式碼執行時間收費。如需 Lambda 定價的詳細資訊,請參閱 AWS Lambda 定價
範例範本
以下是具備延遲機制的 Lambda 支援自訂資源範例範本:
JSON
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "LambdaExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Statement": [{ "Effect": "Allow", "Principal": { "Service": ["lambda.amazonaws.com"] }, "Action": ["sts:AssumeRole"] }] }, "Path": "/", "Policies": [{ "PolicyName": "AllowLogs", "PolicyDocument": { "Statement": [{ "Effect": "Allow", "Action": ["logs:*"], "Resource": "*" }] } }] } }, "CFNWaiter": { "Type": "AWS::Lambda::Function", "Properties": { "Handler": "index.handler", "Runtime": "python3.9", "Timeout": 900, "Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn"] }, "Code": { "ZipFile": { "Fn::Join": ["\n", [ "from time import sleep", "import json", "import cfnresponse", "import uuid", "", "def handler(event, context):", " wait_seconds = 0", " id = str(uuid.uuid1())", " if event[\"RequestType\"] in [\"Create\", \"Update\"]:", " wait_seconds = int(event[\"ResourceProperties\"].get(\"ServiceTimeout\", 0))", " sleep(wait_seconds)", " response = {", " \"TimeWaited\": wait_seconds,", " \"Id\": id ", " }", " cfnresponse.send(event, context, cfnresponse.SUCCESS, response, \"Waiter-\"+id)" ]]} } } }, "CFNWaiterCustomResource": { "Type": "AWS::CloudFormation::CustomResource", "Properties": { "ServiceToken": { "Fn::GetAtt": ["CFNWaiter", "Arn"] }, "ServiceTimeout": 60 } } }, "Outputs": { "TimeWaited": { "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "TimeWaited"] }, "Export": { "Name": "TimeWaited" } }, "WaiterId": { "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "Id"] }, "Export": { "Name": "WaiterId" } } } }
YAML
AWSTemplateFormatVersion: "2010-09-09" Resources: LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: "Allow" Principal: Service: - "lambda.amazonaws.com" Action: - "sts:AssumeRole" Path: "/" Policies: - PolicyName: "AllowLogs" PolicyDocument: Statement: - Effect: "Allow" Action: - "logs:*" Resource: "*" CFNWaiter: Type: AWS::Lambda::Function Properties: Handler: index.handler Runtime: python3.9 Timeout: 900 Role: !GetAtt LambdaExecutionRole.Arn Code: ZipFile: !Sub | from time import sleep import json import cfnresponse import uuid def handler(event, context): wait_seconds = 0 id = str(uuid.uuid1()) if event["RequestType"] in ["Create", "Update"]: wait_seconds = int(event["ResourceProperties"].get("ServiceTimeout", 0)) sleep(wait_seconds) response = { "TimeWaited": wait_seconds, "Id": id } cfnresponse.send(event, context, cfnresponse.SUCCESS, response, "Waiter-"+id) CFNWaiterCustomResource: Type: "AWS::CloudFormation::CustomResource" Properties: ServiceToken: !GetAtt CFNWaiter.Arn ServiceTimeout: 60 Outputs: TimeWaited: Value: !GetAtt CFNWaiterCustomResource.TimeWaited Export: Name: TimeWaited WaiterId: Value: !GetAtt CFNWaiterCustomResource.Id Export: Name: WaiterId
範例範本逐步解說
以下程式碼片段將說明範例範本的相關部分,協助您了解 Lambda 函式如何與自訂資源相關聯,並了解其輸出。
- AWS::Lambda::Function 資源
CFNWaiter -
AWS::Lambda::Function資源會指定函式的原始程式碼、處理常式名稱、執行時期環境,以及執行角色的 Amazon Resource Name (ARN)。由於使用 Python 原始程式碼,因此
Handler屬性設定為index.handler。如需有關使用內嵌函數原始程式碼時可接受處理常式識別碼的詳細資訊,請參閱 AWS::Lambda::Function Code。由於原始檔是 Python 程式碼,
Runtime指定為python3.9。Timeout設定為 900 秒。Role屬性會使用Fn::GetAtt函數來擷取範本中AWS::IAM::Role資源所宣告的LambdaExecutionRole執行角色 ARN。Code屬性會使用 Python 函數來內嵌定義函數程式碼。範例範本中的 Python 函式會執行下列動作:-
使用 UUID 建立唯一 ID
-
檢查請求是建立請求還是更新請求
-
在
Create或Update請求期間為ServiceTimeout指定的持續時間休眠 -
傳回等待時間及唯一 ID
-
JSON
... "CFNWaiter": { "Type": "AWS::Lambda::Function", "Properties": { "Handler": "index.handler", "Runtime": "python3.9", "Timeout": 900, "Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn"] }, "Code": { "ZipFile": { "Fn::Join": ["\n", [ "from time import sleep", "import json", "import cfnresponse", "import uuid", "", "def handler(event, context):", " wait_seconds = 0", " id = str(uuid.uuid1())", " if event[\"RequestType\"] in [\"Create\", \"Update\"]:", " wait_seconds = int(event[\"ResourceProperties\"].get(\"ServiceTimeout\", 0))", " sleep(wait_seconds)", " response = {", " \"TimeWaited\": wait_seconds,", " \"Id\": id ", " }", " cfnresponse.send(event, context, cfnresponse.SUCCESS, response, \"Waiter-\"+id)" ]]} } } }, ...
YAML
... CFNWaiter: Type: AWS::Lambda::Function Properties: Handler: index.handler Runtime: python3.9 Timeout: 900 Role: !GetAtt LambdaExecutionRole.Arn Code: ZipFile: !Sub | from time import sleep import json import cfnresponse import uuid def handler(event, context): wait_seconds = 0 id = str(uuid.uuid1()) if event["RequestType"] in ["Create", "Update"]: wait_seconds = int(event["ResourceProperties"].get("ServiceTimeout", 0)) sleep(wait_seconds) response = { "TimeWaited": wait_seconds, "Id": id } cfnresponse.send(event, context, cfnresponse.SUCCESS, response, "Waiter-"+id) ...
- AWS::IAM::Role 資源
LambdaExecutionRole -
AWS::IAM:Role資源會為 Lambda 函式建立執行角色,其中包含允許 Lambda 使用該角色的擔任角色政策。此外,它還包含一個允許存取 CloudWatch Logs 的政策。
JSON
... "LambdaExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Statement": [{ "Effect": "Allow", "Principal": { "Service": ["lambda.amazonaws.com"] }, "Action": ["sts:AssumeRole"] }] }, "Path": "/", "Policies": [{ "PolicyName": "AllowLogs", "PolicyDocument": { "Statement": [{ "Effect": "Allow", "Action": ["logs:*"], "Resource": "*" }] } }] } }, ...
YAML
... LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: "Allow" Principal: Service: - "lambda.amazonaws.com" Action: - "sts:AssumeRole" Path: "/" Policies: - PolicyName: "AllowLogs" PolicyDocument: Statement: - Effect: "Allow" Action: - "logs:*" Resource: "*" ...
- AWS::CloudFormation::CustomResource 資源
CFNWaiterCustomResource -
自訂資源會透過
!GetAtt CFNWaiter.Arn,使用 Lambda 函式的 ARN 與其建立關聯。根據ServiceTimeout中的設定,它會為建立和更新操作實作 60 秒的等待時間。僅當屬性被修改時,才會在更新操作中調用此資源。
JSON
... "CFNWaiterCustomResource": { "Type": "AWS::CloudFormation::CustomResource", "Properties": { "ServiceToken": { "Fn::GetAtt": ["CFNWaiter", "Arn"] }, "ServiceTimeout": 60 } } }, ...
YAML
... CFNWaiterCustomResource: Type: "AWS::CloudFormation::CustomResource" Properties: ServiceToken: !GetAtt CFNWaiter.Arn ServiceTimeout: 60 ...
Outputs-
此範本的
Outputs為TimeWaited和WaiterId。TimeWaited數值會使用Fn::GetAtt函數,提供等待程式資源實際等待的時間。WaiterId會使用Fn::GetAtt函數來提供產生並與執行相關聯的唯一 ID。
JSON
... "Outputs": { "TimeWaited": { "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "TimeWaited"] }, "Export": { "Name": "TimeWaited" } }, "WaiterId": { "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "Id"] }, "Export": { "Name": "WaiterId" } } } } ...
YAML
... Outputs: TimeWaited: Value: !GetAtt CFNWaiterCustomResource.TimeWaited Export: Name: TimeWaited WaiterId: Value: !GetAtt CFNWaiterCustomResource.Id Export: Name: WaiterId ...
先決條件
您必須具備使用所有對應服務 (如 Lambda 和 CloudFormation) 的 IAM 許可。
啟動堆疊
建立堆疊
-
從 範例範本 區段尋找您偏好設定的範本 (YAML 或 JSON),並將其儲存到名為
samplelambdabackedcustomresource.template的機器。 -
開啟位在 https://console.aws.amazon.com/cloudformation/
的 CloudFormation 主控台。 -
從堆疊頁面的右上角,選擇建立堆疊,並選擇使用新資源 (標準)。
-
對於先決條件 - 準備範本,選取選擇現有範本。
-
對於指定範本下,選擇上傳範本檔案,然後選擇選擇檔案。
-
選取您先前儲存的
samplelambdabackedcustomresource.template範本檔案。 -
選擇下一步。
-
對於秘密名稱,輸入
SampleCustomResourceStack,然後選擇下一步。 -
在此逐步解說中,您不需要新增標籤或指定進階設定,因此請選擇 Next (下一步)。
-
確定堆疊名稱正確,然後選擇更新。
CloudFormation 可能需要幾分鐘的時間來建立您的堆疊。若要監控進度,請檢視堆疊事件。如需詳細資訊,請參閱在 CloudFormation 主控台中檢視堆疊資訊。
若堆疊建立成功,則系統會一併建立堆疊中所有資源 (如 Lambda 函式和自訂資源)。您已成功使用 Lambda 函式和自訂資源。
若 Lambda 函式回傳錯誤訊息,則可以在 CloudWatch Logs 的主控台
清除資源
您可以刪除堆疊以清除建立的所有堆疊資源,便無需為不必要的資源支付費用。
刪除堆疊
-
從 CloudFormation 主控台選擇 SampleCustomResourceStack 堆疊。
-
選擇 Actions (動作),然後選擇 Delete Stack (刪除堆疊)。
-
在確認訊息中,選擇 Yes, Delete (是,刪除)。
系統將刪除您建立的所有資源。
現在,您已經了解如何建立並使用 Lambda 支援的自訂資源,即可善用本逐步說明的範例範本和程式碼來建置其他堆疊及函數。