【问题标题】:Cleaning up AMIs and EBS Snapshots via AWS Lambda通过 AWS Lambda 清理 AMI 和 EBS 快照
【发布时间】:2020-12-05 02:00:19
【问题描述】:

我在本地机器上创建了以下 lambda 函数,因此我可以部署它并每天通过 cloudwatch 事件 cron 表达式运行它,以清理所需的 AMI 及其快照。它还负责处理废弃的 EBS 快照。

删除 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')

【问题讨论】:

  • 有效吗?如果是这样,则无需改进!
  • 是的,按预期工作!我想知道在其中开发 lambda 函数和 python 代码的最佳实践。所以想从社区那里获得想法来改进它。
  • Lambda 函数中的逻辑不能被归类为“最佳实践”——它应该只是做你想让它做的事情。如果您谈论 Lambda 本身的“最佳实践”,它通常会围绕将 Lambda 用于短期功能、是否附加到 VPC、使用后清理 /tmp、使用全局变量在执行之间保留数据并正确使用来自event 的数据。这些都与您的用例无关。

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


【解决方案1】:

您在这里似乎确实存在逻辑问题,如果您遇到不超过 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

【讨论】:

  • 您在答案中发布的代码应该可以工作。您已建议将 break 更改为 continue,但在您的代码 sn-p 中没有这样做。
猜你喜欢
  • 2020-11-16
  • 1970-01-01
  • 2011-10-22
  • 2020-07-10
  • 2013-06-28
  • 2020-01-23
  • 2012-11-29
  • 2011-10-23
  • 2017-10-22
相关资源
最近更新 更多