

• Amazon Systems Manager CloudWatch 控制面板在 2026 年 4 月 30 日之后将不再可用。客户可以像现在一样继续使用 Amazon CloudWatch 控制台来查看、创建和管理其 Amazon CloudWatch 控制面板。有关更多信息，请参阅 [Amazon CloudWatch 控制面板文档](https://docs.amazonaws.cn/AmazonCloudWatch/latest/monitoring/CloudWatch_Dashboards.html)。

# 使用 Automation、Amazon Lambda 和 Parameter Store 来更新黄金 AMI
<a name="automation-tutorial-update-patch-golden-ami"></a>

以下示例使用组织维护和定期修补自己专有 AMIs 的模型，而非构建自 Amazon Elastic Compute Cloud (Amazon EC2) AMIs。

以下过程说明了如何将操作系统（OS）补丁自动应用到已被视为最新的 AMI 或*最新* AMI。在示例中，参数 `SourceAmiId` 的默认值由名为 `latestAmi` 的 Amazon Systems Manager Parameter Store 参数定义。`latestAmi` 的值由调用的 Amazon Lambda 函数在自动化结束时更新。由于采用了此自动化流程，修补 AMIs 所需的时间和工作量可最大限度减少，因为修补操作始终都应用到最新的 AMI。Parameter Store 和 Automation 都是 Amazon Systems Manager 的工具。

**开始前的准备工作**  
配置自动化角色以及（可选）为自动化配置 Amazon EventBridge。有关更多信息，请参阅 [设置自动化](automation-setup.md)。

**Topics**
+ [任务 1：在 Systems Manager Parameter Store 中创建一个参数](#create-parameter-ami)
+ [任务 2：为 Amazon Lambda 创建 IAM 角色](#create-lambda-role)
+ [任务 3：创建 Amazon Lambda 函数](#create-lambda-function)
+ [任务 4：创建运行手册并修补 AMI](#create-custom-ami-update-runbook)

## 任务 1：在 Systems Manager Parameter Store 中创建一个参数
<a name="create-parameter-ami"></a>

在 Parameter Store 中创建一个使用以下信息的字符串参数：
+ **名称**：`latestAmi`。
+ **值**：AMI ID。例如：` ami-188d6e0e`。

有关如何创建 Parameter Store 字符串参数的信息，请参阅 [在 Systems Manager 中创建 Parameter Store 参数](sysman-paramstore-su-create.md)。

## 任务 2：为 Amazon Lambda 创建 IAM 角色
<a name="create-lambda-role"></a>

使用以下过程为 Amazon Lambda 创建 IAM 服务角色。这些策略授予 Lambda 权限，以便使用 Lambda 函数和 Systems Manager 来更新 `latestAmi` 参数的值。

**为 Lambda 创建 IAM 服务角色**

1. 登录 Amazon Web Services 管理控制台，然后通过以下网址打开 IAM 控制台：[https://console.aws.amazon.com/iam/](https://console.amazonaws.cn/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. 在导航窗格中，选择 **Roles（角色）**，然后选择 **Create role（创建角色）**。

1. 直接在**使用案例**下，选择 **Lambda**，然后选择**下一步**。

1. 在**添加权限**页面上，使用**搜索**字段查找之前创建的两个策略。

1. 选中策略旁边的复选框，然后选择**下一步**。

1. 对于**角色名称**，请输入新角色的名称，如 **lambda-ssm-role**或所需其他名称。
**注意**  
由于多个实体可能引用该角色，因此创建角色后无法更改角色的名称。

1. （可选）添加一个或多个标签键值对，以组织、追踪或控制对此角色的访问，然后选择**创建角色**。

## 任务 3：创建 Amazon Lambda 函数
<a name="create-lambda-function"></a>

使用以下过程创建 Lambda 函数，该函数自动更新 `latestAmi` 参数的值。

**创建 Lambda 函数**

1. 通过以下网址登录 Amazon Web Services 管理控制台 并打开 Amazon Lambda 控制台：[https://console.aws.amazon.com/lambda/](https://console.amazonaws.cn/lambda/)。

1. 选择**创建函数**。

1. 在**创建函数**页面上，选择**从头开始创作**。

1. 对于**函数名称**，请输入 **Automation-UpdateSsmParam**。

1. 对于**运行时系统**，选择 **Python 3.11**。

1. 对于**架构**，选择 Lambda 用于运行该函数的计算机处理器类型，即 **x86\$164** 或 **arm64**，

1. 在**权限**部分中，展开**更改默认执行角色**。

1. 选择**使用现有角色**，然后为您在任务 2 中创建的 Lambda 选择服务角色。

1. 选择**创建函数**。

1. 在**代码源**区域中的 **lambda\$1function** 选项卡上，删除该字段中的预填充代码，然后粘贴以下代码示例。

   ```
   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. 对于**事件名称**，输入测试事件的名称，如 **MyTestEvent**。

1. 使用以下 JSON 替换现有文本。将 *AMI ID* 替换为您自己的信息来设置 `latestAmi` 参数值。

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

1. 选择**保存**。

1. 选择**测试**以测试该函数。在**执行结果**选项卡上，应将状态报告为**已成功**，以及有关更新的其他详细信息。

## 任务 4：创建运行手册并修补 AMI
<a name="create-custom-ami-update-runbook"></a>

使用以下过程创建并运行运行手册，该文档修补您为 **latestAmi** 参数指定的 AMI。在自动化完成后，使用新修补的 AMI 的 ID 更新 **latestAmi** 的值。后续自动化使用先前执行创建的 AMI。

**创建运行手册并运行**

1. 访问 [https://console.aws.amazon.com/systems-manager/](https://console.amazonaws.cn/systems-manager/)，打开 Amazon Systems Manager 控制台。

1. 在导航窗格中，选择**文档**。

1. 对于**创建文档**，选择**自动化**。

1. 对于**名称**，请输入 **UpdateMyLatestWindowsAmi**。

1. 选择**编辑器**选项卡，然后选择**编辑**。

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. 选择**创建自动化**。

1. 在导航窗格中，选择**自动化**，然后选择**执行自动化**。

1. 在 **Choose document**（选择文档）页面上，选择 **Owned by me**（我拥有的）选项卡。

1. 搜索 **UpdateMyLatestWindowsAmi** 运行手册，然后选择 **UpdateMyLatestWindowsAmi** 卡中的按钮。

1. 选择**下一步**。

1. 选择**简单执行**。

1. 指定输入参数的值。

1. 选择**执行**。

1. 自动化完成后，在导航窗格中选择 **Parameter Store**，并确认 `latestAmi` 的新值与自动化返回的值匹配。您还可以验证新 AMI ID 与 Amazon EC2 控制台的 **AMI** 部分中的自动化输出匹配。