古いAMIを定期的に削除する – SSM Automationランブックバージョン
以下のページで、DLMを使用して、定期的に古いAMIを削除する方法をご紹介しました。
またStep Functionsを使用して、定期的に古いAMIを削除する方法もご紹介しました。
今回は上記と同じ内容を、SSM Automationランブックを使用して実行します。
構築する環境
SSM Automationランブックを作成します。
ランブックの実行内容ですが、以下を実行します。
- 作成されてから1時間以上経過したAMIを検索して、タグを設定する。
- タグが付与されているAMIに対して、AWSが所有するランブックAWS-DeleteImageを実行する。
EventBridgeルールを作成します。
定期的(1時間に1回)、ランブックを実行するように設定します。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-soa/tree/main/02/005
テンプレートファイルのポイント解説
SSM Automationランブック
Resources:
DeleteImageRunbook:
Type: AWS::SSM::Document
Properties:
Content:
assumeRole: "{{AutomationAssumeRole}}"
description: Create an AMI for an EC2 instance with a specific tag.
schemaVersion: "0.3"
parameters:
AutomationAssumeRole:
type: String
description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
default: !GetAtt DeleteImageRunbookRole.Arn
AccountId:
type: String
description: (Required) The ID of Account.
default: !Ref AWS::AccountId
Region:
type: String
description: (Required) The Region.
default: !Ref AWS::Region
TagKey:
type: String
description: (Required) The tag key of Image.
default: !Ref TagKey
TagValue:
type: String
description: (Required) The tag value of Image.
default: !Ref TagValue
ValidHours:
type: Integer
description: (Required) The expired hours.
default: !Ref ValidHours
mainSteps:
- name: setTagToExpiredImages
action: aws:executeScript
inputs:
Runtime: python3.8
Handler: handler
InputPayload:
AccountId: "{{AccountId}}"
Region: "{{Region}}"
TagKey: "{{TagKey}}"
TagValue: "{{TagValue}}"
ValidHours: "{{ValidHours}}"
Script: |-
import boto3
import datetime
import json
def handler(events, context):
account_id = events['AccountId']
region = events['Region']
tag_key = events['TagKey']
tag_value = events['TagValue']
valid_hours = int(events['ValidHours'])
client = boto3.client('ec2', region_name=region)
now = datetime.datetime.now(datetime.timezone.utc)
response = client.describe_images(
Owners=[account_id])
create_tags_results = []
for image in response['Images']:
creation_date_str = image['CreationDate']
creation_date_dt = datetime.datetime.fromisoformat(creation_date_str.replace('Z', '+00:00'))
diff = now - creation_date_dt
diff_hour = diff.seconds / (60 * 60)
if diff_hour > valid_hours:
result = client.create_tags(
Resources=[
image['ImageId']],
Tags=[
{
'Key': tag_key,
'Value': tag_value
}],
)
create_tags_results.append(result)
return {'createTagResults': json.dumps(create_tags_results)}
outputs:
- Name: createTagResults
Selector: $.Payload.creataTagResults
Type: String
- name: deleteTagedImages
action: aws:executeAutomation
maxAttempts: 1
timeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
onFailure: Abort
inputs:
DocumentName: AWS-DeleteImage
TargetParameterName: ImageId
Targets:
- Key: "tag:{{TagKey}}"
Values:
- "{{TagValue}}"
outputs:
- Name: deleteImage
Selector: "$"
Type: String
DocumentFormat: YAML
DocumentType: Automation
Name: !Sub "${Prefix}-DeleteImageRunbook"
Code language: YAML (yaml)
古いAMIを削除するために、SSM Automationランブックを作成します。
ランブックを自作する方法については、以下のページをご確認ください。
ポイントはステップに関する設定です。
1つ目のステップ
このステップでは、古いAMIにタグを設定します。
actionsプロパティに「aws:executeScript」と設定することで、任意のコードを実行することができます。
指定されたランタイムとハンドラを使用して、提供された Python または PowerShell スクリプトを実行します。
aws:executeScript – スクリプトを実行する
実行するコードは、Step Functionsバージョンと概ね同様です。
変更点としては、作成されてから1時間以上経過したAMIを発見した場合は、タグを設定するという点です。
以下のタグを設定します。
- タグ名:DeleteImage
- タグの値:true
2つ目のステップ
このステップでは、AMIを削除します。
actionsプロパティに「aws:executeAutomation」と設定することで、ランブック内から別のランブックを実行することができます。
inputs内のDocumentNameプロパティに「AWS-DeleteImage」を指定することで、AMIを削除します。
Targetsプロパティに先述のタグ情報を、TargetParameterNameに「ImageId」を指定することで、タグが付与されているAMIを対象として、AWS-DeleteImageが実行されます。
ランブック用IAMロール
Resources:
DeleteImageRunbookRole:
Type: AWS::IAM::Role
DeletionPolicy: Delete
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- ssm.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole
Policies:
- PolicyName: SetTagAndDeleteImagePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- tag:GetResources
Resource:
- "*"
Code language: YAML (yaml)
AWS管理ポリシーAmazonSSMAutomationRoleに加えて、インラインポリシーでtag:GetResourcesを許可するように設定します。
EventBridgeルール
Resources:
EventsRule:
Type: AWS::Events::Rule
Properties:
Name: !Sub "${Prefix}-EventsRule"
ScheduleExpression: rate(1 hour)
State: ENABLED
Targets:
- Arn: !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${Runbook}:$DEFAULT"
Id: !Ref Runbook
RoleArn: !GetAtt EventsRuleRole.Arn
Code language: YAML (yaml)
ランブックを定期的に実行するために、EventBridgeルールを作成します。
ScheduleExpressionプロパティに「rate(1 hour)」と指定することで、1時間ごとにランブックを実行できます。
Targetsプロパティに、先述のランブックのARN等を指定します。
Resources:
EventsRuleRole:
Type: AWS::IAM::Role
DeletionPolicy: Delete
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service: events.amazonaws.com
Policies:
- PolicyName: !Sub "${Prefix}-StartAutomationExecutionPolicy"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: ssm:StartAutomationExecution
Resource: !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${Runbook}:$DEFAULT"
- Effect: Allow
Action: iam:PassRole
Resource: !Ref RunbookRoleArn
Code language: YAML (yaml)
インラインポリシーで2つのアクションを許可します。
1つ目はssm:StartAutomationExecutionです。
文字通り、ランブックの実行を許可する内容です。
2つ目はiam:PassRoleです。
先ほど確認したSSM Automationランブック用のIAMロールを、ランブックに渡すためです。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- SSM Automationランブック:soa-02-005-DeleteImageRunbook
- EventBridgeルール:soa-02-005-EventsRule
AWSマネージメントコンソールから各種リソースを確認します。
SSM Automaitonランブックを確認します。
正常にランブックが作成されています。
EventBridgeルールを確認します。
1時間ごとにランブックを実行する内容です。
動作確認
AMI作成
任意のEC2インスタンスからAMIを作成します。
AMIとともにスナップショットも作成されました。
ランブック実行1回目
1回目のランブック実行が自動的に始まります。
実行の詳細を確認します。
ランブック内の2ステップが正常に終了したことがわかります。
両ステップの状況を確認します。
1つ目のステップです。
Outputsを見ると、スクリプトの実行結果が空です。
つまり作成から1時間以上経過しているAMIが存在しなかったため、タグ付け等の処理を実行せずに終了しました。
2つ目のステップです。
タグ名が「DeleteImage」で、値が「true」のAMIに対して、SSM AutomationランブックAWS-DeleteImageを実行するステップです。
以下がこのランブックの実行結果です。
該当のタグが付与されているAMIがなかったため、何も実行されずに終了しました。
このように削除条件を満たすAMIがない場合は、何も実行せずに終了します。
ランブック実行2回目
1時間後、2回目のランブック実行が自動的に始まります。
実行の詳細を確認します。
今回もランブック内の2ステップが正常に終了したことがわかります。
両ステップの状況を確認します。
1つ目のステップです。
Outputsを見ると、スクリプトの実行結果が1つありました。
つまり作成から1時間以上経過したため、先ほどのAMIにタグが設定されたということです。
2つ目のステップです。
タグ名が「DeleteImage」で、値が「true」のAMIに対して、SSM AutomationランブックAWS-DeleteImageを実行するステップです。
以下がこのランブックの実行結果です。
Step nameに先ほど生成したAMIのIDが確認できます。
ステップの実行内容を確認します。
ランブックAWS-DeleteImageの実行が開始されました。
このランブックで実行された内容を確認します。
タグ付けしたAMIの削除が正常に実行されました。
最後にAMIやスナップショットを確認します。
確かにAMI等が削除されました。
まとめ
SSM Automationランブックを使用して、定期的に古いAMIを削除する方法もご紹介しました。