使用 Automation、Amazon Lambda 和 Parameter Store 来更新黄金 AMI - Amazon Systems Manager
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用 Automation、Amazon Lambda 和 Parameter Store 来更新黄金 AMI

以下示例使用组织维护和定期修补自己专有 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 和自动化是 Amazon Systems Manager 的功能。

开始前的准备工作

配置自动化角色以及(可选)为自动化配置 Amazon EventBridge。有关更多信息,请参阅设置自动化

任务 1:在 Systems Manager Parameter Store 中创建一个参数

在 Parameter Store 中创建一个使用以下信息的字符串参数:

  • 名称latestAmi

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

有关如何创建 Parameter Store 字符串参数的信息,请参阅 创建 Systems Manager 参数

任务 2:为 Amazon Lambda 创建 IAM 角色

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

为 Lambda 创建 IAM 服务角色
  1. 登录Amazon Web Services Management Console,然后通过以下网址打开 IAM 控制台:https://console.aws.amazon.com/iam/

  2. 在导航窗格中选择策略,然后选择创建策略

  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. 选择 Next: Review(下一步: 审核)

  8. 查看策略页面上,对于名称,输入内联策略的名称,例如 amiLambda

  9. 选择 Create policy(创建策略)

  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. 选择 Next: Review(下一步: 审核)

  15. 查看策略页面上,对于名称,输入内联策略的名称,例如 amiParameter

  16. 选择 Create policy(创建策略)

  17. 在导航窗格中,选择 Roles (角色),然后选择 Create role (创建角色)

  18. 直接在应用场景下,选择 Lambda,然后选择下一步

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

  20. 选中策略旁边的复选框,然后选择下一步

  21. 对于角色名称,请输入新角色的名称,如 lambda-ssm-role 或所需的其他名称。

    注意

    由于多个实体可能引用该角色,因此创建角色后无法更改角色的名称。

  22. (可选)添加一个或多个标签键值对,以组织、追踪或控制对此角色的访问,然后选择创建角色

任务 3:创建 Amazon Lambda 函数

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

创建 Lambda 函数
  1. 登录到 Amazon Web Services Management Console,然后通过以下网址打开 Amazon Lambda 控制台:https://console.aws.amazon.com/lambda/

  2. 选择 Create function(创建函数)。

  3. 创建函数页面上,选择从 Scratch 开始创作

  4. 对于 Function name(函数名称),请输入 Automation-UpdateSsmParam

  5. 对于运行时,选择 Python 3.8

  6. 对于架构,选择 Lambda 用于运行该函数的计算机处理器类型,即 x86_64arm64

  7. 权限部分中,展开更改默认执行角色

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

  9. 选择 Create function(创建函数)。

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

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

    { "parameterName":"latestAmi", "parameterValue":"AMI ID" }
  15. 选择 Save(保存)。

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

任务 4:创建运行手册并修补 AMI

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

创建运行手册并运行
  1. 访问 https://console.aws.amazon.com/systems-manager/,打开 Amazon Systems Manager 控制台。

  2. 在导航窗格中,选择 文档

    -或者-

    如果首先打开 Amazon Systems Manager 主页,选择菜单图标 ( 
    The menu icon
  ) 以打开导航窗格,然后在导航窗格中选择 Documents(文档)。

  3. 对于创建文档,选择自动化

  4. 对于 Name(名称),请输入 UpdateMyLatestWindowsAmi

  5. 选择编辑器 选项卡,然后选择编辑

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

  9. 在导航窗格中,选择自动化,然后选择执行自动化

  10. Choose document(选择文档)页面上,选择 Owned by me(我拥有的)选项卡。

  11. 搜索 UpdateMyLatestWindowsAmi 运行手册,然后选择 UpdateMyLatestWindowsAmi 卡中的按钮。

  12. 选择下一步

  13. 选择简单执行

  14. 指定输入参数的值。

  15. 选择执行

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