https://oc-technote.com/aws/lambda-%E4%B8%8D%E8%A6%81%E3%81%AAami%E3%82%92%E5%AE%9A%E6%9C%9F%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B/
https://oc-technote.com/aws/lambda-%e4%b8%8d%e8%a6%81%e3%81%aaami%e3%81%a8%e3%82%b9%e3%83%8a%e3%83%83%e3%83%97%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88%e3%82%92%e3%81%be%e3%81%a8%e3%82%81%e3%81%a6%e5%89%8a%e9%99%a4%e3%81%99%e3%82%8b/
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2/client/describe_images.html
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ami-policy.html
Data Lifecycle Managerでは削除のみはできない模様
-- 1. コマンド等のインストール
-- 1.1 aws cli version 2 インストール
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws --version
-- 1.2 jqインストール
sudo yum -y install jq
-- 2. ポリシーの作成
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DeregisterImage",
"ec2:DeleteSnapshot",
"ec2:DescribeSnapshots",
"ec2:DescribeImages"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
aws iam create-policy \
--policy-name policy01 \
--policy-document file://policy01.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
aws iam create-role \
--role-name role01 \
--assume-role-policy-document file://role01.json
-- 4. ポリシーをロールにアタッチ
aws iam attach-role-policy \
--policy-arn arn:aws:iam::999999999999:policy/policy01 \
--role-name role01
-- 5. Lambda関数作成
vim test.py
import boto3
import logging
import time
import datetime as dt
from botocore.exceptions import ClientError
ec2 = boto3.client('ec2')
def get_old_ami():
# Describe target AMIs.
try:
response = ec2.describe_images(
Owners=['999999999999']
)
if response.get('ResponseMetadata', {}).get('HTTPStatusCode', -1) != 200:
raise('# Cannot describe images!')
images = response.get('Images')
print('# All delete-sample images:', len(images))
except ClientError as e:
print(e.response['Error']['Code'])
print(e.response['Error']['Message'])
logging.error("# Describe images error: %s", e)
return
age_in_seconds = 600
old_images = []
epoc_now = int(time.time())
print('# epoc now:', epoc_now)
for image in images:
creation_date = image.get('CreationDate')
datetime = dt.datetime.strptime(creation_date, "%Y-%m-%dT%H:%M:%S.000Z")
epoc_datetime = int(dt.datetime.timestamp(datetime))
if epoc_now - epoc_datetime > age_in_seconds:
old_images.append(image.get('ImageId'))
return old_images
def unregister_ami(delete_ami_id):
# Unregister AMI.
try:
response = ec2.deregister_image(ImageId=str(delete_ami_id))
except ClientError as e:
if e.response['Error']['Code'] == 'InvalidAMIID.Unavailable':
print('InvalidAMIID.Unavailable: ' + delete_ami_id)
return True
elif e.response['Error']['Code'] == 'InvalidAMIID.NotFound':
print('InvalidAMIID.NotFound: ' + delete_ami_id)
return True
else:
print(e.response['Error']['Code'])
print(e.response['Error']['Message'])
raise e
print('Unregister AMI: ' + delete_ami_id)
return response.get('ResponseMetadata', {}).get('HTTPStatusCode', -1) == 200
def delete_related_snapshots(delete_ami_id):
# Get target snapshots.
try:
response = ec2.describe_snapshots(
Filters=[
{
'Name': 'description',
'Values': ['Created by CreateImage(*) for ' + delete_ami_id + '*',]
}
]
)
except ClientError as e:
print(e.response['Error']['Code'])
print(e.response['Error']['Message'])
raise e
# Delete target snapshots.
for snapshot in response['Snapshots']:
try:
response = ec2.delete_snapshot(SnapshotId=snapshot['SnapshotId'])
if response.get('ResponseMetadata', {}).get('HTTPStatusCode', -1) != 200:
raise('# Cannot delete snapshot: %s', snapshot)
print('Delete Snapshot: ' + snapshot['SnapshotId'])
except ClientError as e:
print(e.response['Error']['Code'])
print(e.response['Error']['Message'])
logging.error("# Delete snapshot error: %s", e)
return
def lambda_handler(event, context):
# Get the AMI to be deleted.
delete_amis = get_old_ami()
print('# Target AMIs:', len(delete_amis))
print(delete_amis)
for delete_ami in delete_amis:
# Delete AMI.
unregister_ami(delete_ami)
# Delete Snapshots.
delete_related_snapshots(delete_ami)
return
chmod 755 test.py
zip test.zip test.py
aws lambda create-function \
--function-name func01 \
--zip-file fileb://test.zip \
--handler test.lambda_handler \
--runtime python3.11 \
--role arn:aws:iam::999999999999:role/role01 \
--timeout 900
aws lambda list-functions | grep func01
aws lambda get-function --function-name func01
-- 6. ルールの作成
aws events put-rule \
--name rule01 \
--schedule-expression "rate(1 minute)" \
--state ENABLED \
--description rule01
aws events list-rules
aws events describe-rule --name rule01
-- 7. ターゲットの作成
aws events put-targets \
--rule rule01 \
--targets "Id"="1","Arn"="arn:aws:lambda:ap-northeast-1:999999999999:function:func01"
aws events list-targets-by-rule \
--rule rule01
-- 8. Lambda関数に権限を追加する
aws lambda add-permission \
--function-name func01 \
--statement-id events \
--action lambda:InvokeFunction \
--principal events.amazonaws.com \
--source-arn arn:aws:events:ap-northeast-1:999999999999:rule/rule01
aws lambda get-policy \
--function-name func01 | jq -r .Policy | jq .
-- 9. 動作確認
aws ec2 create-image \
--description "ami001" \
--instance-id i-11111111111111111 \
--name "ami20230808"
aws ec2 describe-images \
--owners self
aws ec2 describe-snapshots \
--owner-ids self
-- 10. クリーンアップ
-- ターゲットの削除
aws events list-targets-by-rule \
--rule rule01
aws events remove-targets \
--rule rule01 \
--ids 1
-- ルールの削除
aws events list-rules
aws events delete-rule \
--name rule01
-- Lambda関数の削除
aws lambda get-function --function-name func01
aws lambda delete-function --function-name func01
-- ロールの削除
aws iam list-roles | grep role01
aws iam detach-role-policy \
--role-name role01 \
--policy-arn arn:aws:iam::999999999999:policy/policy01
aws iam delete-role --role-name role01
-- ポリシーの削除
aws iam list-policies | grep policy01
aws iam delete-policy \
--policy-arn arn:aws:iam::999999999999:policy/policy01