

• 2026 年 4 月 30 日之後將不再提供 AWS Systems Manager CloudWatch Dashboard。客戶可以繼續使用 Amazon CloudWatch 主控台來檢視、建立和管理其 Amazon CloudWatch 儀表板，就像現在一樣。如需詳細資訊，請參閱 [Amazon CloudWatch Dashboard 文件](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Dashboards.html)。

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

# AMI 使用自動化更新黃金 AWS Lambda，以及 Parameter Store
<a name="automation-tutorial-update-patch-golden-ami"></a>

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

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

**開始之前**  
設定 Automation 角色和 (選用) Automation 的 Amazon EventBridge。如需詳細資訊，請參閱[設定自動化](automation-setup.md)。

**Topics**
+ [任務 1：建立 Systems Manager Parameter Store 參數](#create-parameter-ami)
+ [任務 2：建立 的 IAM 角色 AWS Lambda](#create-lambda-role)
+ [任務 3：建立 AWS Lambda 函數](#create-lambda-function)
+ [任務 4：建立 Runbook 並修補 AMI](#create-custom-ami-update-runbook)

## 任務 1：建立 Systems Manager Parameter Store 參數
<a name="create-parameter-ami"></a>

在 Parameter Store 中建立字串參數，使用以下資訊：
+ **Name (名稱)**：`latestAmi`。
+ **值**：AMI ID。例如：` ami-188d6e0e`。

如需建立 Parameter Store 字串參數的詳細資訊，請參閱 [在 Systems Manager 中建立 Parameter Store 參數](sysman-paramstore-su-create.md)。

## 任務 2：建立 的 IAM 角色 AWS Lambda
<a name="create-lambda-role"></a>

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

**建立適用於 Lambda 的 IAM 服務角色**

1. 登入 AWS 管理主控台 並開啟位於 https：//[https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/) 的 IAM 主控台。

1. 在導覽窗格中，選擇**政策**，然後選擇**建立政策**。

1. 選擇 **JSON** 標籤。

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

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "logs:CreateLogGroup",
               "Resource": "arn:aws:logs:{{us-east-1}}:{{111122223333}}:*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "logs:CreateLogStream",
                   "logs:PutLogEvents"
               ],
               "Resource": [
                   "arn:aws:logs:{{us-east-1}}:{{111122223333}}:log-group:/aws/lambda/{{function name}}:*"
               ]
           }
       ]
   }
   ```

------

1. 選擇下**一步：標籤**。

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

1. 選擇下**一步：檢閱**。

1. 在**檢閱政策**頁面上**名稱**中，輸入該內嵌政策的名稱，例如 **amiLambda**。

1. 選擇**建立政策**。

1. 重複步驟 2 和 3。

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

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "ssm:PutParameter",
               "Resource": "arn:aws:ssm:{{us-east-1}}:{{111122223333}}:parameter/{{latestAmi}}"
           },
           {
               "Effect": "Allow",
               "Action": "ssm:DescribeParameters",
               "Resource": "*"
           }
       ]
   }
   ```

------

1. 選擇下**一步：標籤**。

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

1. 選擇下**一步：檢閱**。

1. 在**檢閱政策**頁面上**名稱**中，輸入該內嵌政策的名稱，例如 **amiParameter**。

1. 選擇**建立政策**。

1. 在導覽窗格中，選擇**角色**，然後選擇**建立角色**。

1. 在**使用案例**下，隨即選擇 **Lambda**，然後選擇**下一步**。

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

1. 選取政策旁的核取方塊，然後選擇**下一步**。

1. 對於 **Role name (角色名稱)**，輸入新角色的名稱，例如 **lambda-ssm-role** 或另一個您喜好的名稱。
**注意**  
因為有各種實體可能會參照角色，所以您無法在建立角色之後變更角色名稱。

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

## 任務 3：建立 AWS Lambda 函數
<a name="create-lambda-function"></a>

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

**建立 Lambda 函數**

1. 登入 AWS 管理主控台 並在 https：//[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) 開啟 AWS Lambda 主控台。

1. 選擇**建立函數**。

1. 在 **Create function (建立函數)** 頁面上，選擇 **Author from scratch (從頭開始撰寫)**。

1. 針對**函數名稱**，請輸入 **Automation-UpdateSsmParam**。

1. 針對**執行期**，選擇 **Python 3.11。**

1. 在**架構**中，選取 Lambda 用來執行函數的電腦處理器類型：**x86\_64** 或 **arm64**。

1. 在**許可**區段中，展開**變更預設執行角色**。

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

1. 選擇**建立函數**。

1. 在**程式碼來源**區域的 **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
   ```

1. 選擇**檔案、儲存**。

1. 若要測試 Lambda 函數，請從**測試**功能表，選擇**設定測試事件**。

1. 針對 **Event name (事件名稱)**，輸入測試事件的名稱，例如 **MyTestEvent**。

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

   ```
   {
      "parameterName":"latestAmi",
      "parameterValue":"{{AMI ID}}"
   }
   ```

1. 選擇**儲存**。

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

## 任務 4：建立 Runbook 並修補 AMI
<a name="create-custom-ami-update-runbook"></a>

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

**建立和執行 Runbook**

1. 在 https：//[https://console.aws.amazon.com/systems-manager/](https://console.aws.amazon.com/systems-manager/) 開啟 AWS Systems Manager 主控台。

1. 在導覽窗格中，選擇 **Documents (文件)**。

1. 在**建立文件**中，選擇**自動化**。

1. 對於**名稱**，輸入 **UpdateMyLatestWindowsAmi**。

1. 選擇 **Editor (編輯器)** 標籤，然後選擇 **Edit (編輯)**。

1. 出現提示時選擇**確定**。

1. 在**文件編輯器**欄位中，使用以下 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
   ```

1. 選擇 **Create automation (建立自動化)**。

1. 在導覽窗格中，選擇 **Automation (自動化)**，接著選擇 **Execute automation (執行自動化)**。

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

1. 搜尋 **UpdateMyLatestWindowsAmi** Runbook，然後選擇 **UpdateMyLatestWindowsAmi** 卡中的按鈕。

1. 選擇**下一步**。

1. 選擇 **Simple execution (簡單執行)**。

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

1. 選擇 **Execute (執行)**。

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