逐步解說:AMIIDs使用 Lambda 支援的自訂資源進行查詢 - AWS CloudFormation

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

逐步解說:AMIIDs使用 Lambda 支援的自訂資源進行查詢

本逐步解說說明如何使用 Lambda 和自訂資源,在 CloudFormation 範本IDs中動態查詢 Amazon Machine Image (AMI)。這可協助您簡化 CloudFormation 範本AMIIDs中的 更新方式。

當您建立 CloudFormation 範本以啟動 Amazon EC2執行個體時,您必須指定一個 AMI ID,其類似將安裝在執行個體上的作業系統和軟體的範本。正確的 AMI ID 取決於執行個體類型,而 AWS 區域 您正在其中啟動執行個體。這些IDs可能會定期變更,例如 AMI 更新軟體更新時。

您通常會在對應AMIIDs至特定執行個體類型和區域的Mappings區段中指定 AMI ID。這表示若要更新 IDs,您必須在每個範本中手動變更它們。不過,透過使用自訂資源和 Lambda,您可以建立函數,AMIs取得您正在使用的執行個體類型和區域IDs的最新 。如此一來,您就不必在堆疊範本中手動維護 AMI IDs、執行個體類型和 區域之間的映射。

此逐步解說說明如何建立自訂資源,並將 Lambda 函數與其建立關聯,以查詢 AMI IDs。它假設您熟悉自訂資源和 Lambda 函數。如需自訂資源及其運作方式的簡介,請參閱 使用自訂資源建立自訂佈建邏輯。如需有關 Lambda 的資訊,請參閱 AWS Lambda 開發人員指南

注意

CloudFormation 是一項免費服務;不過,您需要支付每個 堆疊中以目前費率包含 AWS 的資源費用,例如 Lambda 函數和EC2執行個體。如需 AWS 定價的詳細資訊,請參閱 https://http://aws.amazon.com 中每個產品的詳細資訊頁面。

除了建立自訂資源和 Lambda 函數之外,您也可以使用 AWS Systems Manager 範本中的參數來擷取儲存在 Systems Manager 參數中的最新 AMI ID 值。這可讓您的範本更可重複使用且更易於維護。如需詳細資訊,請參閱使用 CloudFormation提供的參數類型參考現有的資源和 Systems Manager 參數

概觀

下列步驟提供此實作的概觀。

  1. 將包含 Lambda 函數程式碼的範例套件儲存至您要建立EC2執行個體 AWS 區域 的相同 Amazon S3 儲存貯體。

  2. 使用範例範本,透過自訂資源、Lambda 函數、EC2執行個體和 Lambda 用來呼叫 Amazon IAM的角色來建立堆疊EC2。

  3. 堆疊會將 Lambda 函數與自訂資源建立關聯。建立堆疊時, CloudFormation 會叫用函數並傳送資訊,例如請求類型、輸入資料和預先簽署的 Amazon S3URL。

  4. Lambda 函數會使用輸入資料來查詢最新的 AMI ID,並將 AMI ID 作為回應傳送至預先簽署的 URL。

  5. CloudFormation 在預先簽署URL的位置取得回應,並繼續建立堆疊。 CloudFormation 建立執行個體時,它會使用 Lambda 函數提供的 AMI ID 來建立具有最新 的EC2執行個體AMI。

範本演練

如需檢視整個範例範本,請參閱:

以下程式碼片段將說明範例範本的相關部分,協助您了解如何建立 Lambda 函數與自訂資源間的關聯,亦可掌握函數回應的使用方法。

AWS::Lambda::Function 資源 AMIInfoFunction

AWS::Lambda::Function 資源會指定函數的原始程式碼、處理常式名稱、執行期環境和執行角色 Amazon Resource Name (ARN)。

  • Code 屬性會指定儲存範例套件的 Amazon S3 位置 (儲存貯體名稱和檔案名稱)。為了讓您可以在建立堆疊時指定名稱,範例範本會使用 "Ref": "S3Bucket""Ref": "S3Key" 這兩個輸入參數來設定儲存貯體及檔案的名稱。同樣地,對應於.zip套件中來源檔案名稱 ( JavaScript 檔案) 的處理常式名稱也會使用輸入參數 ("Ref": "ModuleName")。由於來源檔案是 JavaScript 程式碼,因此執行時間會指定為 nodejs18.x

  • 對於此演練中使用的程式碼,函數的執行時間超過預設值3秒,因此逾時設定為30秒。若您指定的逾時期間不夠長,則 Lambda 可能會在函數完成前發生逾時,導致堆疊建立失敗。

  • Role 屬性會使用 Fn::GetAtt函數來取得範本中其他地方宣告的LambdaExecutionRole執行角色ARN的 。

JSON

"AMIInfoFunction": { "Type": "AWS::Lambda::Function", "Properties": { "Code": { "S3Bucket": { "Ref": "S3Bucket" }, "S3Key": { "Ref": "S3Key" } }, "Handler": { "Fn::Join" : [ "", [{ "Ref": "ModuleName" },".handler"] ] }, "Runtime": "nodejs18.x", "Timeout": "30", "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] } } }

YAML

AMIInfoFunction: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Ref S3Bucket S3Key: !Ref S3Key Handler: !Sub "${ModuleName}.handler" Runtime: nodejs18.x Timeout: 30 Role: !GetAtt LambdaExecutionRole.Arn

AWS::IAM:Role 資源 LambdaExecutionRole

執行角色會授予 Lambda 函數許可,以將日誌傳送至 AWS 和 呼叫 EC2 DescribeImages API。

JSON

"LambdaExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"Service": ["lambda.amazonaws.com"]}, "Action": ["sts:AssumeRole"] }] }, "Path": "/", "Policies": [{ "PolicyName": "root", "PolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": ["ec2:DescribeImages"], "Resource": "*" }] } }] } }

YAML

LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: root PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: arn:aws:logs:*:*:* - Effect: Allow Action: - ec2:DescribeImages Resource: "*"

自訂::AMIInfo 資源 AMIInfo

對於 Linux 和 Windows 範本,自訂資源會叫用與其相關聯的 Lambda 函數。若要將函數與自訂資源建立關聯,您可以使用Fn::GetAtt內部函數指定 ServiceToken 屬性ARN的 函數。 會將自訂資源宣告中包含的其他屬性,例如 RegionArchitecture, CloudFormation 傳送至 Lambda 函數作為輸入。Lambda 函數則負責判斷這些輸入屬性的正確名稱與數值。

JSON

"AMIInfo": { "Type": "Custom::AMIInfo", "Properties": { "ServiceToken": { "Fn::GetAtt" : ["AMIInfoFunction", "Arn"] }, "Region": { "Ref": "AWS::Region" }, "Architecture": { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } } }

YAML

AMIInfo: Type: Custom::AMIInfo Properties: ServiceToken: !GetAtt AMIInfoFunction.Arn Region: !Ref "AWS::Region" Architecture: Fn::FindInMap: - AWSInstanceType2Arch - !Ref InstanceType - Arch

在 Windows 作業系統中,自訂資源會提供 Windows 版本給 Lambda 函數,而非執行個體的架構。

JSON

"AMIInfo": { "Type": "Custom::AMIInfo", "Properties": { "ServiceToken": { "Fn::GetAtt": ["AMIInfoFunction", "Arn"] }, "Region": { "Ref": "AWS::Region" }, "OSName": { "Ref": "WindowsVersion" } } }

YAML

AMIInfo: Type: Custom::AMIInfo Properties: ServiceToken: !GetAtt AMIInfoFunction.Arn Region: !Ref "AWS::Region" OSName: !Ref "WindowsVersion"

CloudFormation 叫用 Lambda 函數時,函數會使用 AWS 區域 和 執行個體架構或作業系統名稱來篩選映像清單API,以呼叫 EC2 DescribeImages 。然後,函數會依日期排序影像清單,並傳回最新 的 IDAMI。

傳回最新 的 ID 時AMI,函數會將 ID 傳送至回應物件 的 Data 屬性URL中預先簽署的 ID。 自訂資源回應物件資料的結構為名稱/值組,如以下範例所示:

"Data": { "Id": "ami-02354e95b3example" }

AWS::EC2:Instance 資源 SampleInstance

以下程式碼片段會說明從 Lambda 函數取得資料的方法,其會透過 Fn::GetAtt 內部函數,進而提供欲獲取的自訂資源名稱與數值屬性名稱。在本演練中,自訂資源名稱為 AMIInfo,屬性名稱則為 Id

JSON

"SampleInstance": { "Type": "AWS::EC2::Instance", "Properties": { "InstanceType" : { "Ref": "InstanceType" }, "ImageId": { "Fn::GetAtt": [ "AMIInfo", "Id" ] } } }

YAML

SampleInstance: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType ImageId: !GetAtt AMIInfo.Id

必要條件

您必須先擁有 Amazon S3 儲存貯體,才能完成建立堆疊的步驟。當您使用 Lambda 函數建立堆疊時,必須指定包含函數原始程式碼的 Amazon S3 儲存貯體位置。儲存貯體必須與您 AWS 區域 建立堆疊所在的儲存貯體相同。如需有關建立儲存貯體的詳細資訊,請參閱《Amazon Simple Storage Service 使用者指南》中的建立儲存貯體

您還必須具有使用所有對應服務的IAM許可,例如 Lambda、Amazon EC2和 CloudFormation。

步驟 1:將範例 Lambda 套件儲存至 Amazon S3

在此步驟中,您將範例 Lambda 套件 (.zip檔案) 上傳至您的 Amazon S3 儲存貯體。

此套件包含 Lambda 函數和所需程式庫的原始碼。在本演練中,函數並不需使用額外的程式庫。

在 Amazon S3 中儲存範例套件
  1. 從 Amazon S3 下載範例套件。儲存檔案時,請務必使用與範例相同的檔案名稱,例如 amilookup.zipamilookup-win.zip

  2. 開啟位於 首頁 的 Amazon S3 主控台。 https://console.aws.amazon.com/s3/

  3. 在畫面頂端的導覽列上,選擇您在 AWS 區域 其中建立 Amazon S3 儲存貯體的 。

  4. 儲存貯體清單中,選擇儲存貯體的名稱。記下儲存貯體名稱,因為您在建立堆疊時使用它。

  5. 選擇上傳

  6. 上傳 下,對於檔案和資料夾 ,將範例套件上傳到儲存貯體。如需詳細資訊,請參閱 Amazon Simple Storage Service 使用者指南中的上傳物件

步驟 2:啟動堆疊

在此步驟中,您可以從範例範本啟動堆疊。堆疊包含 Lambda 函數、IAM角色 (執行角色)、叫用函數的自訂資源,以及使用函數結果的EC2執行個體。

在堆疊建立期間,自訂資源會叫用 Lambda 函數,並等待函數傳送回應給預先簽署的 Amazon S3URL。在回應中, 函數會傳回與EC2執行個體類型AMI對應的最新 ID,而 AWS 區域 您正在其中建立執行個體。來自函數回應的資料會儲存為自訂資源的屬性,用於指定EC2執行個體的 AMI ID。

建立堆疊
  1. 在 開啟 CloudFormation 主控台https://console.aws.amazon.com/cloudformation/

  2. 選擇 Create Stack (建立堆疊)。

  3. 範本區段中,選擇指定 Amazon S3 範本 URL,然後在文字方塊URL中複製並貼上下列項目:

    Linux 範本

    https://s3.amazonaws.com/cloudformation-examples/lambda/LambdaAMILookupSample.template

    Windows 範本

    https://s3.amazonaws.com/cloudformation-examples/lambda/LambdaAMILookupSample-win.template

  4. 選擇 Next (下一步)

  5. Stack name (堆疊名稱) 欄位中,輸入 SampleEC2Instance

  6. Parameters (參數) 區段中,指定您所建的 Amazon S3 儲存貯體名稱,接著選擇 Next (下一步)

    其他參數的預設值會與範例 .zip 套件所使用的名稱相同。

  7. 在此逐步解說中,您不需要新增標籤或指定進階設定,因此請選擇 Next (下一步)

  8. 確保堆疊名稱和範本URL正確,然後選擇建立

建立堆疊可能需要幾分鐘 CloudFormation 的時間。若要監控進度,請檢視堆疊事件。如需詳細資訊,請參閱從 CloudFormation 主控台檢視堆疊資訊

如果堆疊建立成功,則會建立堆疊中的所有資源,例如 Lambda 函數、自訂資源和EC2執行個體。您已成功使用 Lambda 函數和自訂資源來指定EC2執行個體的 AMI ID。您不需要在此範本AMIIDs中建立和維護 的映射。

若要查看 CloudFormation 用來建立EC2執行個體的 AMI ID,請檢視堆疊輸出。

如果 Lambda 函數傳回錯誤,請在 Logs 主控台 中檢視函數的 CloudWatch 日誌。日誌串流名稱即為自訂資源的實體 ID,您能夠檢視堆疊資源以查詢該名稱。如需詳細資訊,請參閱 Amazon CloudWatch 使用者指南 中的檢視日誌資料

步驟 3:清除資源

您可以刪除堆疊以清除建立的所有堆疊資源,便無需為不必要的資源支付費用。

刪除堆疊
  1. 從 CloudFormation 主控台中選擇範例EC2Instance堆疊。

  2. 選擇 Actions (動作),然後選擇 Delete Stack (刪除堆疊)

  3. 在確認訊息中,選擇 Yes, Delete (是,刪除)

系統將刪除您建立的所有資源。

現在,您已了解如何建立 Lambda 函數並與 搭配使用 CloudFormation,您可以使用此逐步解說中的範例範本和程式碼來建置其他堆疊和函數。

相關資訊