通过AWS Lambda清理AMI和EBS快照

时间:2020-07-30 22:04:12

标签: python-3.x amazon-web-services aws-lambda boto3

我已经在本地计算机上创建了以下lambda函数,因此我可以每天通过cloudwatch事件cron表达式对其进行部署和运行,以清理所需的AMI及其SnapShots。它还可以处理废弃的EBS SnapShot。

删除AMI的标准是首先找到没有DoNotDelete:true标记的AMI,如果它已存在7天以上,则将其标记为要删除。该功能可免除AWS Launch Configuration当前正在使用的AMI。

我肯定有几种方法可以优化此lambda函数和代码,并且我想知道如何进一步改进/优化它。

import boto3
from datetime import timedelta, datetime, timezone
import logging
import botocore

#Intialize logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)



def ami_cleanup(event,context):
    '''Clean AMIs and its associated SnapShots which are older than 7 Days and without "DoNotDelete=true" tag in a AWS Region
    Exempt AMI which is currently being used in AWS Launch Config'''
    ec2 = boto3.client('ec2')
    autoscaling = boto3.client('autoscaling')
    ami_response = ec2.describe_images(Owners=['self'])
    snapshot_response = ec2.describe_snapshots(OwnerIds=['self'])
    lc_response = autoscaling.describe_launch_configurations()
    amis = {}
    amidnd = []
    for i in ami_response['Images']:
        for tag in i.get('Tags',''):
             if 'DoNotDelete' in tag.values():
                 amidnd.append(i.get('ImageId'))
                 break
    for ami in lc_response['LaunchConfigurations']:
        if ami['ImageId'] not in amidnd:
            amidnd.append(ami['ImageId'])
    for i in ami_response['Images']:
        if i.get('Tags') == None or i['ImageId'] not in amidnd:
            amis[i.get('ImageId')] = i.get('CreationDate')
    if not amis:
        logger.info('No AMIs and SnapShots found to be deregister')
    else:
        for ami,cdate in amis.items():
            if cdate < (datetime.now(timezone.utc)-timedelta(days=7)).isoformat():
                logger.info('De-registering...'+ami)
                ec2.deregister_image(ImageId=ami)
                for snapshot in snapshot_response['Snapshots']:
                    if  ami in snapshot.get('Description',''):
                        logger.info('Deleting '+snapshot.get('SnapshotId') + " of "+ami)
                        ec2.delete_snapshot(SnapshotId=snapshot.get('SnapshotId'))
            else:
                logger.info('No AMIs and SnapShots found to be older than 7 days')
                break
    abandon_snap_clean(ami_response,snapshot_response)


def abandon_snap_clean(ami_response,snapshot_response):
    '''Clean abandon ebs snapshots of which no AMI has been found'''
    snapdndids = []
    for i in ami_response['Images']:
        for snap in i['BlockDeviceMappings']:
            if 'Ebs' in snap.keys():
                snapdndids.append(snap['Ebs']['SnapshotId'])
    for snapid in snapshot_response['Snapshots']:
        if snapid['SnapshotId'] not in snapdndids:
            try:
                logger.info('Deleting abandon snapshots '+snapid['SnapshotId'])
                ec2.delete_snapshot(SnapshotId=snapid['SnapshotId'])
            except botocore.exceptions.ClientError as error:
                if error.response['Error']['Code'] == 'InvalidSnapshot.InUse':
                    logger.info('SnapShotId '+snapid['SnapShotId']+' is already being used by an AMI')
                else:
                    raise error
        else:
            logger.info('No abandon EBS SnapShots found to clean up')
            break
    else:
        logger.info('No SnapShots found')

1 个答案:

答案 0 :(得分:2)

这里似乎确实存在逻辑问题,如果遇到的图像不超过7天,则循环会中断,而其他图像可能仍超过7天。将break切换为continue

           if cdate < (datetime.now(timezone.utc)-timedelta(days=7)).isoformat():
               logger.info('De-registering...'+ami)
               ec2.deregister_image(ImageId=ami)
               for snapshot in snapshot_response['Snapshots']:
                   if  ami in snapshot.get('Description',''):
                       logger.info('Deleting '+snapshot.get('SnapshotId') + " of "+ami)
                       ec2.delete_snapshot(SnapshotId=snapshot.get('SnapshotId'))
           else:
               logger.info('No AMIs and SnapShots found to be older than 7 days')
               continue