更新 Auto Scaling 群組的 AMIs - AWS Systems Manager

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

更新 Auto Scaling 群組的 AMIs

下列範例使用新修補的 AMI 更新 Auto Scaling 群組。此方法可確保新的映像會自動提供給使用 Auto Scaling 群組的不同運算環境。

此範例中自動化的最後步驟使用 Python 函數來建立使用新修補 AMI 的啟動範本。然後,更新 Auto Scaling 群組以使用新的啟動範本。在此類型的 Auto Scaling 情況下,使用者可以在 Auto Scaling 群組中終止現有的執行個體,以強制新的執行個體啟動並使用新映像。或者,使用者可以等待並允許縮減或擴展事件自然啟動較新的執行個體。

開始之前

開始此範例之前,請先完成以下任務。

  • 設定自動化的IAM角色,功能 AWS Systems Manager。Systems Manager 需要執行個體設定檔角色和服務角色,ARN才能處理自動化作業。如需詳細資訊,請參閱設定自動化

建立 P atchAMIAnd 更新ASG執行手冊

使用下列程序建立修補AMI您為 S ource AMI 參數指定的 P atchAMIAnd Update ASG 執行手冊。此 Runbook 也會更新 Auto Scaling 群組以使用最新且經修補的 AMI。

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

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

  3. Create document (建立文件) 下拉式清單中,選擇 Automation (自動化)。

  4. Name (名稱) 欄位中,輸入 PatchAMIAndUpdateASG

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

  6. 出現提示時選擇 OK (確定),然後在 Document editor (文件編輯器) 欄位中刪除內容。

  7. 在 [文件編輯器] 欄位中,貼上下列YAML範例 runbook 內容。

    --- 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: '(Required) The ID of the AMI you want to patch.' SubnetId: type: String description: '(Required) The ID of the subnet where the instance from the SourceAMI parameter is launched.' SecurityGroupIds: type: StringList description: '(Required) The IDs of the security groups to associate with the instance launched from the SourceAMI parameter.' NewAMI: type: String description: '(Optional) The name of of newly patched AMI.' default: 'patchedAMI-{{global:DATE_TIME}}' TargetASG: type: String description: '(Required) The name of the Auto Scaling group you want to update.' InstanceProfile: type: String description: '(Required) 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: updateASG action: 'aws:executeScript' timeoutSeconds: 300 maxAttempts: 1 onFailure: Abort inputs: Runtime: python3.8 Handler: update_asg InputPayload: TargetASG: '{{TargetASG}}' NewAMI: '{{createImage.ImageId}}' Script: |- from __future__ import print_function import datetime import json import time import boto3 # create auto scaling and ec2 client asg = boto3.client('autoscaling') ec2 = boto3.client('ec2') def update_asg(event, context): print("Received event: " + json.dumps(event, indent=2)) target_asg = event['TargetASG'] new_ami = event['NewAMI'] # get object for the ASG we're going to update, filter by name of target ASG asg_query = asg.describe_auto_scaling_groups(AutoScalingGroupNames=[target_asg]) if 'AutoScalingGroups' not in asg_query or not asg_query['AutoScalingGroups']: return 'No ASG found matching the value you specified.' # gets details of an instance from the ASG that we'll use to model the new launch template after source_instance_id = asg_query.get('AutoScalingGroups')[0]['Instances'][0]['InstanceId'] instance_properties = ec2.describe_instances( InstanceIds=[source_instance_id] ) source_instance = instance_properties['Reservations'][0]['Instances'][0] # create list of security group IDs security_groups = [] for group in source_instance['SecurityGroups']: security_groups.append(group['GroupId']) # create a list of dictionary objects for block device mappings mappings = [] for block in source_instance['BlockDeviceMappings']: volume_query = ec2.describe_volumes( VolumeIds=[block['Ebs']['VolumeId']] ) volume_details = volume_query['Volumes'] device_name = block['DeviceName'] volume_size = volume_details[0]['Size'] volume_type = volume_details[0]['VolumeType'] device = {'DeviceName': device_name, 'Ebs': {'VolumeSize': volume_size, 'VolumeType': volume_type}} mappings.append(device) # create new launch template using details returned from instance in the ASG and specify the newly patched AMI time_stamp = time.time() time_stamp_string = datetime.datetime.fromtimestamp(time_stamp).strftime('%m-%d-%Y_%H-%M-%S') new_template_name = f'{new_ami}_{time_stamp_string}' try: ec2.create_launch_template( LaunchTemplateName=new_template_name, LaunchTemplateData={ 'BlockDeviceMappings': mappings, 'ImageId': new_ami, 'InstanceType': source_instance['InstanceType'], 'IamInstanceProfile': { 'Arn': source_instance['IamInstanceProfile']['Arn'] }, 'KeyName': source_instance['KeyName'], 'SecurityGroupIds': security_groups } ) except Exception as e: return f'Exception caught: {str(e)}' else: # update ASG to use new launch template asg.update_auto_scaling_group( AutoScalingGroupName=target_asg, LaunchTemplate={ 'LaunchTemplateName': new_template_name } ) return f'Updated ASG {target_asg} with new launch template {new_template_name} which uses AMI {new_ami}.' outputs: - createImage.ImageId
  8. 選擇 Create automation (建立自動化)

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

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

  11. 搜索 P atchAMIAnd 更新手ASG冊,然後選擇 P atchAMIAnd 更新ASG卡中的按鈕。

  12. 選擇 Next (下一步)

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

  14. 為輸入參數指定值。確定您指定的 SubnetIdSecurityGroupIds 允許存取公用 Systems Manager 端點,或是 Systems Manager 的介面端點。

  15. 選擇 Execute (執行)

  16. 自動化完成後,在 Amazon EC2 主控台中選擇「自 Auto Scaling」,然後選擇「啟動範本」。確認您已看到新的啟動範本,且其使用新的 AMI。

  17. 選擇 Auto Scaling (Auto Scaling),然後選擇 Auto Scaling Groups (Auto Scaling 群組)。確認 Auto Scaling 群組使用新的啟動範本。

  18. 在您的 Auto Scaling 群組中終止一個或多個執行個體。取代執行個體會以新的 AMI 啟動。