使用 Automation、AWS Lambda 和 Parameter Store 來更新黃金 AMI - AWS Systems Manager

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

使用 Automation、AWS Lambda 和 Parameter Store 來更新黃金 AMI

在以下範例使用的模型中,組織會維護並定期修補其自有的專屬 AMIs,而非從 Amazon Elastic Compute Cloud (Amazon EC2) AMIs 建立。

以下程序示範如何自動將作業系統 (OS) 修補程式套用至已視為是最近期或最新 AMI 的 AMI。在範例中,參數 SourceAmiId 的預設值是由稱為 latestAmi 的 AWS Systems Manager Parameter Store 參數定義。latestAmi 的值是由在自動化結束時呼叫的 AWS Lambda 函數更新。此自動化程序可將耗費在修補 AMIs 的時間與心力降至最低,原因在於修補一律會套用最新的 AMI。Parameter Store 和 Automation 是 AWS Systems Manager 的功能。

開始之前

設定 Automation 角色和 (選用) Automation 的 Amazon EventBridge。如需更多詳細資訊,請參閱 設定自動化

任務 1:建立 Systems Manager Parameter Store 參數

在 Parameter Store 中建立字串參數,使用以下資訊:

  • Name (名稱)latestAmi

  • :AMI ID。例如: ami-188d6e0e

如需建立 Parameter Store 字串參數的詳細資訊,請參閱 建立 Systems Manager 參數

任務 2:建立 AWS Lambda 的 IAM 角色

使用以下程序為 AWS Lambda 建立 IAM 服務角色。這些政策會提供 Lambda 許可,以使用 Lambda 函數和 Systems Manager 來更新 latestAmi 參數的值。

建立適用於 Lambda 的 IAM 服務角色
  1. 登入 AWS Management Console,並開啟位於 https://console.aws.amazon.com/iam/ 的 IAM 主控台。

  2. 在導覽窗格中,選擇 Policies (政策),然後選擇 Create policy (建立政策)

  3. 請選擇 JSON 標籤。

  4. 將預設內容取代為以下政策。將每個範例資源預留位置取代為您自己的資訊。

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "arn:aws:logs:region:123456789012:*" }, { "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": [ "arn:aws:logs:region:123456789012:log-group:/aws/lambda/function name:*" ] } ] }
  5. 選擇 下一步:標籤

  6. (選用) 新增一個或多個標籤鍵值組來組織、追蹤或控制對此政策的存取。

  7. 選擇 下一步:檢閱

  8. Review Policy (檢閱政策) 頁面上 Name (名稱)中,輸入該內嵌政策的名稱,例如 amiLambda

  9. 選擇 建立政策

  10. 重複步驟 2 和 3。

  11. 貼上下列政策。將每個範例資源預留位置取代為您自己的資訊。

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ssm:PutParameter", "Resource": "arn:aws:ssm:region:123456789012:parameter/latestAmi" }, { "Effect": "Allow", "Action": "ssm:DescribeParameters", "Resource": "*" } ] }
  12. 選擇 下一步:標籤

  13. (選用) 新增一個或多個標籤鍵值組來組織、追蹤或控制對此政策的存取。

  14. 選擇 下一步:檢閱

  15. Review Policy (檢閱政策) 頁面上 Name (名稱)中,輸入該內嵌政策的名稱,例如 amiParameter

  16. 選擇 建立政策

  17. 在導覽窗格中,選擇 Roles (角色),然後選擇 Create role (建立角色)

  18. 使用案例下,隨即選擇 Lambda,然後選擇下一步

  19. 新增許可頁面上,使用搜尋欄位找出您之前建立的兩個政策。

  20. 選取政策旁的核取方塊,然後選擇下一步

  21. 對於 Role name (角色名稱),輸入新角色的名稱,例如 lambda-ssm-role 或另一個您喜好的名稱。

    注意

    因為有各種實體可能會參照角色,所以您無法在建立角色之後變更角色名稱。

  22. (選用) 新增一或多個標籤鍵值組來整理、追蹤或控制此角色的存取權,然後選擇建立角色

任務 3:建立 AWS Lambda 函數

使用以下程序建立可自動更新 latestAmi 參數值的 Lambda 函數。

若要建立 Lambda 函數
  1. 請登入 AWS Management Console,並開啟位於 https://console.aws.amazon.com/lambda/ 的 AWS Lambda 主控台。

  2. 選擇 建立函數

  3. Create function (建立函數) 頁面上,選擇 Author from scratch (從頭開始撰寫)

  4. 針對 函數名稱 ,請輸入 Automation-UpdateSsmParam

  5. 針對執行階段,選擇 Python 3.8

  6. 架構中,選取 Lambda 用來執行函數的電腦處理器類型:x86_64arm64

  7. 許可區段中,展開變更預設執行角色

  8. 選擇 Use an existing role (使用現有角色),然後為您在任務 2 中建立的 Lambda 選擇服務角色。

  9. 選擇 建立函數

  10. 程式碼來源區域的 lambda_function 索引標籤中,刪除欄位中預先填入的程式碼,接著貼上以下範本程式碼。

    from __future__ import print_function import json import boto3 print('Loading function') #Updates an SSM parameter #Expects parameterName, parameterValue def lambda_handler(event, context): print("Received event: " + json.dumps(event, indent=2)) # get SSM client client = boto3.client('ssm') #confirm parameter exists before updating it response = client.describe_parameters( Filters=[ { 'Key': 'Name', 'Values': [ event['parameterName'] ] }, ] ) if not response['Parameters']: print('No such parameter') return 'SSM parameter not found.' #if parameter has a Description field, update it PLUS the Value if 'Description' in response['Parameters'][0]: description = response['Parameters'][0]['Description'] response = client.put_parameter( Name=event['parameterName'], Value=event['parameterValue'], Description=description, Type='String', Overwrite=True ) #otherwise just update Value else: response = client.put_parameter( Name=event['parameterName'], Value=event['parameterValue'], Type='String', Overwrite=True ) responseString = 'Updated parameter %s with value %s.' % (event['parameterName'], event['parameterValue']) return responseString
  11. 選擇檔案、儲存

  12. 若要測試 Lambda 函數,請從測試功能表,選擇設定測試事件

  13. 針對 Event name (事件名稱),輸入測試事件的名稱,例如 MyTestEvent

  14. 將現有文字取代為以下的 JSON。把 AMI ID 取代為您自己的資訊以設定 latestAmi 參數值。

    { "parameterName":"latestAmi", "parameterValue":"AMI ID" }
  15. 選擇 Save (儲存)。

  16. 選擇 Test (測試) 以測試函數。在執行結果索引標籤上,狀態應報告為成功,同時包含與更新有關的其他詳細資訊。

任務 4:建立 Runbook 並修補 AMI

使用以下程序建立和執行 Runbook,以修補您針對 latestAmi 參數指定的 AMI。自動化工作流程完成後,latestAmi 的值會以新修補的 AMI 之 ID 更新。後續的自動化會使用由先前執行建立的 AMI。

建立和執行 Runbook
  1. 開啟位於 https://console.aws.amazon.com/systems-manager/ 的 AWS Systems Manager 主控台。

  2. 在導覽窗格中,選擇 Documents (文件)

    -或-

    如果 AWS Systems Manager 首頁先開啟,選擇選單圖示 ( 
    The menu icon
  ) 以開啟導覽窗格,然後在導覽窗格中,選擇 Documents (文件)。

  3. 建立文件中,選擇自動化

  4. 對於 Name (名稱),輸入 UpdateMyLatestWindowsAmi

  5. 選擇 Editor (編輯器) 標籤,然後選擇 Edit (編輯)

  6. 出現提示時選擇確定

  7. 文件編輯器欄位中,使用以下 YAML 範例執行手冊內容取代預設內容。

    --- description: Systems Manager Automation Demo - Patch AMI and Update ASG schemaVersion: '0.3' assumeRole: '{{ AutomationAssumeRole }}' parameters: AutomationAssumeRole: type: String description: '(Required) The ARN of the role that allows Automation to perform the actions on your behalf. If no role is specified, Systems Manager Automation uses your IAM permissions to execute this document.' default: '' SourceAMI: type: String description: The ID of the AMI you want to patch. default: '{{ ssm:latestAmi }}' SubnetId: type: String description: The ID of the subnet where the instance from the SourceAMI parameter is launched. SecurityGroupIds: type: StringList description: The IDs of the security groups to associate with the instance that's launched from the SourceAMI parameter. NewAMI: type: String description: The name of of newly patched AMI. default: 'patchedAMI-{{global:DATE_TIME}}' InstanceProfile: type: String description: The name of the IAM instance profile you want the source instance to use. SnapshotId: type: String description: (Optional) The snapshot ID to use to retrieve a patch baseline snapshot. default: '' RebootOption: type: String description: '(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.' allowedValues: - NoReboot - RebootIfNeeded default: RebootIfNeeded Operation: type: String description: (Optional) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline. allowedValues: - Install - Scan default: Install mainSteps: - name: startInstances action: 'aws:runInstances' timeoutSeconds: 1200 maxAttempts: 1 onFailure: Abort inputs: ImageId: '{{ SourceAMI }}' InstanceType: m5.large MinInstanceCount: 1 MaxInstanceCount: 1 IamInstanceProfileName: '{{ InstanceProfile }}' SubnetId: '{{ SubnetId }}' SecurityGroupIds: '{{ SecurityGroupIds }}' - name: verifyInstanceManaged action: 'aws:waitForAwsResourceProperty' timeoutSeconds: 600 inputs: Service: ssm Api: DescribeInstanceInformation InstanceInformationFilterList: - key: InstanceIds valueSet: - '{{ startInstances.InstanceIds }}' PropertySelector: '$.InstanceInformationList[0].PingStatus' DesiredValues: - Online onFailure: 'step:terminateInstance' - name: installPatches action: 'aws:runCommand' timeoutSeconds: 7200 onFailure: Abort inputs: DocumentName: AWS-RunPatchBaseline Parameters: SnapshotId: '{{SnapshotId}}' RebootOption: '{{RebootOption}}' Operation: '{{Operation}}' InstanceIds: - '{{ startInstances.InstanceIds }}' - name: stopInstance action: 'aws:changeInstanceState' maxAttempts: 1 onFailure: Continue inputs: InstanceIds: - '{{ startInstances.InstanceIds }}' DesiredState: stopped - name: createImage action: 'aws:createImage' maxAttempts: 1 onFailure: Continue inputs: InstanceId: '{{ startInstances.InstanceIds }}' ImageName: '{{ NewAMI }}' NoReboot: false ImageDescription: Patched AMI created by Automation - name: terminateInstance action: 'aws:changeInstanceState' maxAttempts: 1 onFailure: Continue inputs: InstanceIds: - '{{ startInstances.InstanceIds }}' DesiredState: terminated - name: updateSsmParam action: aws:invokeLambdaFunction timeoutSeconds: 1200 maxAttempts: 1 onFailure: Abort inputs: FunctionName: Automation-UpdateSsmParam Payload: '{"parameterName":"latestAmi", "parameterValue":"{{createImage.ImageId}}"}' outputs: - createImage.ImageId
  8. 選擇 Create automation (建立自動化)

  9. 在導覽窗格中,選擇 Automation (自動化),接著選擇 Execute automation (執行自動化)

  10. Choose document (選擇文件) 頁面中,選擇 Owned by me (我所擁有) 索引標籤。

  11. 搜尋 UpdateMyLatestWindowsAmi Runbook,然後選擇 UpdateMyLatestWindowsAmi 卡中的按鈕。

  12. 選擇 Next (下一步)

  13. 選擇 Simple execution (簡單執行)

  14. 請為輸入參數指定值。

  15. 選擇 Execute (執行)

  16. 自動化完成後,在導覽窗格中選擇 Parameter Store 並確認 latestAmi 的新值符合自動化傳回的值。您也可以在 Amazon EC2 主控台的 AMIs 部分確認新的 AMI ID 符合自動化輸出。