Kembalikan volume root dari snapshot terbaru - AWS Systems Manager

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Kembalikan volume root dari snapshot terbaru

Sistem operasi pada volume akar dapat rusak karena berbagai alasan. Misalnya, setelah operasi patching, instance mungkin gagal boot dengan sukses karena kernel atau registri rusak. Mengotomatiskan tugas pemecahan masalah umum, seperti memulihkan volume root dari snapshot terbaru yang diambil sebelum operasi patch, dapat mengurangi waktu henti dan mempercepat upaya pemecahan masalah Anda. AWS Systems Manager Tindakan otomatisasi dapat membantu Anda mencapai hal ini. Otomatisasi adalah kemampuan AWS Systems Manager.

Contoh AWS Systems Manager runbook berikut melakukan tindakan ini:

  • Menggunakan aws:executeAwsApi tindakan otomatisasi untuk mengambil detail dari volume akar instans.

  • Menggunakan aws:executeScript tindakan otomatisasi untuk mengambil snapshot terbaru untuk volume akar.

  • Menggunakan aws:branch otomatisasi tindakan untuk melanjutkan otomatisasi jika snapshot ditemukan untuk volume akar.

YAML
--- description: Custom Automation Troubleshooting Example 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 use this runbook." default: '' InstanceId: type: String description: "(Required) The Instance Id whose root EBS volume you want to restore the latest Snapshot." default: '' mainSteps: - name: getInstanceDetails action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: DescribeInstances InstanceIds: - "{{ InstanceId }}" outputs: - Name: availabilityZone Selector: "$.Reservations[0].Instances[0].Placement.AvailabilityZone" Type: String - Name: rootDeviceName Selector: "$.Reservations[0].Instances[0].RootDeviceName" Type: String nextStep: getRootVolumeId - name: getRootVolumeId action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: DescribeVolumes Filters: - Name: attachment.device Values: ["{{ getInstanceDetails.rootDeviceName }}"] - Name: attachment.instance-id Values: ["{{ InstanceId }}"] outputs: - Name: rootVolumeId Selector: "$.Volumes[0].VolumeId" Type: String nextStep: getSnapshotsByStartTime - name: getSnapshotsByStartTime action: aws:executeScript timeoutSeconds: 45 onFailure: Abort inputs: Runtime: python3.8 Handler: getSnapshotsByStartTime InputPayload: rootVolumeId : "{{ getRootVolumeId.rootVolumeId }}" Script: |- def getSnapshotsByStartTime(events,context): import boto3 #Initialize client ec2 = boto3.client('ec2') rootVolumeId = events['rootVolumeId'] snapshotsQuery = ec2.describe_snapshots( Filters=[ { "Name": "volume-id", "Values": [rootVolumeId] } ] ) if not snapshotsQuery['Snapshots']: noSnapshotFoundString = "NoSnapshotFound" return { 'noSnapshotFound' : noSnapshotFoundString } else: jsonSnapshots = snapshotsQuery['Snapshots'] sortedSnapshots = sorted(jsonSnapshots, key=lambda k: k['StartTime'], reverse=True) latestSortedSnapshotId = sortedSnapshots[0]['SnapshotId'] return { 'latestSnapshotId' : latestSortedSnapshotId } outputs: - Name: Payload Selector: $.Payload Type: StringMap - Name: latestSnapshotId Selector: $.Payload.latestSnapshotId Type: String - Name: noSnapshotFound Selector: $.Payload.noSnapshotFound Type: String nextStep: branchFromResults - name: branchFromResults action: aws:branch onFailure: Abort inputs: Choices: - NextStep: createNewRootVolumeFromSnapshot Not: Variable: "{{ getSnapshotsByStartTime.noSnapshotFound }}" StringEquals: "NoSnapshotFound" isEnd: true - name: createNewRootVolumeFromSnapshot action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: CreateVolume AvailabilityZone: "{{ getInstanceDetails.availabilityZone }}" SnapshotId: "{{ getSnapshotsByStartTime.latestSnapshotId }}" outputs: - Name: newRootVolumeId Selector: "$.VolumeId" Type: String nextStep: stopInstance - name: stopInstance action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: StopInstances InstanceIds: - "{{ InstanceId }}" nextStep: verifyVolumeAvailability - name: verifyVolumeAvailability action: aws:waitForAwsResourceProperty timeoutSeconds: 120 inputs: Service: ec2 Api: DescribeVolumes VolumeIds: - "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}" PropertySelector: "$.Volumes[0].State" DesiredValues: - "available" nextStep: verifyInstanceStopped - name: verifyInstanceStopped action: aws:waitForAwsResourceProperty timeoutSeconds: 120 inputs: Service: ec2 Api: DescribeInstances InstanceIds: - "{{ InstanceId }}" PropertySelector: "$.Reservations[0].Instances[0].State.Name" DesiredValues: - "stopped" nextStep: detachRootVolume - name: detachRootVolume action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: DetachVolume VolumeId: "{{ getRootVolumeId.rootVolumeId }}" nextStep: verifyRootVolumeDetached - name: verifyRootVolumeDetached action: aws:waitForAwsResourceProperty timeoutSeconds: 30 inputs: Service: ec2 Api: DescribeVolumes VolumeIds: - "{{ getRootVolumeId.rootVolumeId }}" PropertySelector: "$.Volumes[0].State" DesiredValues: - "available" nextStep: attachNewRootVolume - name: attachNewRootVolume action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: AttachVolume Device: "{{ getInstanceDetails.rootDeviceName }}" InstanceId: "{{ InstanceId }}" VolumeId: "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}" nextStep: verifyNewRootVolumeAttached - name: verifyNewRootVolumeAttached action: aws:waitForAwsResourceProperty timeoutSeconds: 30 inputs: Service: ec2 Api: DescribeVolumes VolumeIds: - "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}" PropertySelector: "$.Volumes[0].Attachments[0].State" DesiredValues: - "attached" nextStep: startInstance - name: startInstance action: aws:executeAwsApi onFailure: Abort inputs: Service: ec2 Api: StartInstances InstanceIds: - "{{ InstanceId }}"
JSON
{ "description": "Custom Automation Troubleshooting Example", "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 run this runbook.", "default": "" }, "InstanceId": { "type": "String", "description": "(Required) The Instance Id whose root EBS volume you want to restore the latest Snapshot.", "default": "" } }, "mainSteps": [ { "name": "getInstanceDetails", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "DescribeInstances", "InstanceIds": [ "{{ InstanceId }}" ] }, "outputs": [ { "Name": "availabilityZone", "Selector": "$.Reservations[0].Instances[0].Placement.AvailabilityZone", "Type": "String" }, { "Name": "rootDeviceName", "Selector": "$.Reservations[0].Instances[0].RootDeviceName", "Type": "String" } ], "nextStep": "getRootVolumeId" }, { "name": "getRootVolumeId", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "DescribeVolumes", "Filters": [ { "Name": "attachment.device", "Values": [ "{{ getInstanceDetails.rootDeviceName }}" ] }, { "Name": "attachment.instance-id", "Values": [ "{{ InstanceId }}" ] } ] }, "outputs": [ { "Name": "rootVolumeId", "Selector": "$.Volumes[0].VolumeId", "Type": "String" } ], "nextStep": "getSnapshotsByStartTime" }, { "name": "getSnapshotsByStartTime", "action": "aws:executeScript", "timeoutSeconds": 45, "onFailure": "Continue", "inputs": { "Runtime": "python3.8", "Handler": "getSnapshotsByStartTime", "InputPayload": { "rootVolumeId": "{{ getRootVolumeId.rootVolumeId }}" }, "Attachment": "getSnapshotsByStartTime.py" }, "outputs": [ { "Name": "Payload", "Selector": "$.Payload", "Type": "StringMap" }, { "Name": "latestSnapshotId", "Selector": "$.Payload.latestSnapshotId", "Type": "String" }, { "Name": "noSnapshotFound", "Selector": "$.Payload.noSnapshotFound", "Type": "String" } ], "nextStep": "branchFromResults" }, { "name": "branchFromResults", "action": "aws:branch", "onFailure": "Abort", "inputs": { "Choices": [ { "NextStep": "createNewRootVolumeFromSnapshot", "Not": { "Variable": "{{ getSnapshotsByStartTime.noSnapshotFound }}", "StringEquals": "NoSnapshotFound" } } ] }, "isEnd": true }, { "name": "createNewRootVolumeFromSnapshot", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "CreateVolume", "AvailabilityZone": "{{ getInstanceDetails.availabilityZone }}", "SnapshotId": "{{ getSnapshotsByStartTime.latestSnapshotId }}" }, "outputs": [ { "Name": "newRootVolumeId", "Selector": "$.VolumeId", "Type": "String" } ], "nextStep": "stopInstance" }, { "name": "stopInstance", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "StopInstances", "InstanceIds": [ "{{ InstanceId }}" ] }, "nextStep": "verifyVolumeAvailability" }, { "name": "verifyVolumeAvailability", "action": "aws:waitForAwsResourceProperty", "timeoutSeconds": 120, "inputs": { "Service": "ec2", "Api": "DescribeVolumes", "VolumeIds": [ "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}" ], "PropertySelector": "$.Volumes[0].State", "DesiredValues": [ "available" ] }, "nextStep": "verifyInstanceStopped" }, { "name": "verifyInstanceStopped", "action": "aws:waitForAwsResourceProperty", "timeoutSeconds": 120, "inputs": { "Service": "ec2", "Api": "DescribeInstances", "InstanceIds": [ "{{ InstanceId }}" ], "PropertySelector": "$.Reservations[0].Instances[0].State.Name", "DesiredValues": [ "stopped" ] }, "nextStep": "detachRootVolume" }, { "name": "detachRootVolume", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "DetachVolume", "VolumeId": "{{ getRootVolumeId.rootVolumeId }}" }, "nextStep": "verifyRootVolumeDetached" }, { "name": "verifyRootVolumeDetached", "action": "aws:waitForAwsResourceProperty", "timeoutSeconds": 30, "inputs": { "Service": "ec2", "Api": "DescribeVolumes", "VolumeIds": [ "{{ getRootVolumeId.rootVolumeId }}" ], "PropertySelector": "$.Volumes[0].State", "DesiredValues": [ "available" ] }, "nextStep": "attachNewRootVolume" }, { "name": "attachNewRootVolume", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "AttachVolume", "Device": "{{ getInstanceDetails.rootDeviceName }}", "InstanceId": "{{ InstanceId }}", "VolumeId": "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}" }, "nextStep": "verifyNewRootVolumeAttached" }, { "name": "verifyNewRootVolumeAttached", "action": "aws:waitForAwsResourceProperty", "timeoutSeconds": 30, "inputs": { "Service": "ec2", "Api": "DescribeVolumes", "VolumeIds": [ "{{ createNewRootVolumeFromSnapshot.newRootVolumeId }}" ], "PropertySelector": "$.Volumes[0].Attachments[0].State", "DesiredValues": [ "attached" ] }, "nextStep": "startInstance" }, { "name": "startInstance", "action": "aws:executeAwsApi", "onFailure": "Abort", "inputs": { "Service": "ec2", "Api": "StartInstances", "InstanceIds": [ "{{ InstanceId }}" ] } } ], "files": { "getSnapshotsByStartTime.py": { "checksums": { "sha256": "sampleETagValue" } } } }