AWS Lambda & EventBridge | Deregister Unused AMI In Account On Weekly Basis And Notify Via Email

AWS Lambda & EventBridge | Deregister Unused AMI In Account On Weekly Basis And Notify Via Email

In this blog we are going to check for list of Unused AMI on weekly basis and deregister those AMI from account using AWS Lambda function in python.

Create Role For Lambda Using below Policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeImages",
                "ec2:DeregisterImage",
                "ec2:DescribeInstances",
                "ec2:DescribeTags",
                "logs:*",
                "ec2:DescribeImageAttribute",
                "ec2:DescribeInstanceTypes",
                "ec2:DescribeInstanceStatus"
            ],
            "Resource": "*"
        }
    ]
}

Create SNS Topic And Subscribe

  1. Open the Amazon SNS console, and then choose Topics from the navigation pane. image.png
  2. Choose Create topic. image.png
  3. For Name, enter a name for your topic[Notify-Unused-AMI]. image.png
  4. For Display name, enter a display name for your topic and choose create topic image.png
  5. After topic creation click on the Subscriptions tab, choose Create subscription. image.png
  6. For Protocol, choose Email -> For Endpoint, enter the email address where you want to receive the notifications -> Choose Create subscription. image.png image.png
  7. A subscription confirmation email is sent to the address you entered. Choose Confirm subscription in the email. image.png
  8. When you click on confirm you will get below message which confirms your subscription image.png
  9. Now go back to Topics->EC2-State-Change-Notify and you can see its status has changed from pending to confirmed. image.png Note the SNS topic ARN you created. You use this topic when creating the EventBridge rule.

Create AWS Lambda Python Function To Find Unused AMI And Deregister it.

  1. Goto Lambda console and click on create function image.png
  2. Select "Author From Scratch" , Function name = unused_ami, Runtime= Python and role we created with above policy attached to this blog and click on create function. image.png
  3. Goto code editor and start writing the code. image.png
  4. Python code in one module gains access to the code in another module by the process of importing it. The import statement combines two operations it searches for the named module, then it binds the results of that search to a name in the local scope.
    import boto3
    
  5. We will invoke the client for EC2
    ec2 = boto3.client('ec2')
    
  6. First we will call describe_instances() function to fetch list of all EC2 instances in our account and save the dictonary returned in variable, you can get the official documentation for this function here
    instances = ec2.describe_instances()
    
  7. Lets create empty list to save image id's which are in use by instances.
    def lambda_handler(event, context):
     used_ami = []  # Create empty list to save used ami
    
  8. Traverse through instances dictionary to fetch instance state [running/stopped]. If ec2 is in running state we will append Image ID of that EC2 to our empty list.
    def lambda_handler(event, context):
     used_ami = []  # Create empty list to save used ami
     for reservation in instances['Reservations']:
         for instance in reservation['Instances']:
             state = instance['State']
             state = (state['Name'])
             if state == 'running':
                 used_ami.append(instance['ImageId'])
    
  9. Above code will result in duplicate values into the list, to remove duplicate values we will write below code
     # Remove duplicate entries from list
     used_ami = list(set(used_ami))
    
  10. We will call now describe_images() function to get list of custom AMI from our account and save the returned dictionary in variable. You can view this function official documentation here
    In areguments for this function we will filter image id's based on its state, if its in available state then only we will fetch it. Owners can be anyone of your choice [Amazon Web Services account IDs, self , amazon , and aws-marketplace]
    images = ec2.describe_images(
        Filters=[
            {
                'Name': 'state',
                'Values': ['available']
            },
        ],
        Owners=['self'],
    )
    
  11. We will traverse returned dictionaty now from above function and fetch image id's and append them to our custom ami list.
    # Traverse dictonary returned and fetch Image ID and append in list
    custom_ami = []  # Create empty list to save custom ami
    for image in images['Images']:
        custom_ami.append(image['ImageId'])
    
  12. Now we will check if custom ami id's that we have with used ami list. If its not available in used ami list we will dregister the AMI using deregister_image(ImageId='string') function, you can get the official documentation for this function here
    deregister_list = []
    for ami in custom_ami:
        if ami not in used_ami:
            print("AMI {} has been deregistered".format(ami))
            ec2.deregister_image(ImageId=ami)
            deg = ("-----Unused AMI ID = {} is Deregistered------".format(ami))
            deregister_list.append(deg)
    
  13. Now we will use publish() function to send email with list of ami ids and configure the email message and subject accordingly, you can get the official documentation for this function here
    sns_client = boto3.client('sns')
    sns_client.publish(
    TopicArn='<SNS Topic ARN>',
    Subject='Alert - Unused AMI's Is Deregistered',
    Message=str(deregister_list)
    )
    return "success"
    
    To view entire github code please click here

Using Amazon EventBridge Schedule Lambda On Weekly Basis

  1. Open Amazon Eventbridge service and open rules. And click on create rule image.png
  2. Now we will create rule and schedule it. For scheduling you we will have to use cron expression as displayed below. You can find official documentation here image.png
  3. Now lets create our rule to start EC2 instance. First we will define name and description as below image.png
  4. Now we will define Cron job expression where we will define that this job should run on 11 am IST only on saturday . Expression would be
    0 11 ? * 7 *
    
    image.png
  5. Select target as the lambda function and select our lambda function to start EC2 instance and click on create. image.png

Youtube Tutorial

Resource Cleanup

  • Delete EventBridge Rule.
  • Delete Lambda
  • Delete SNS Topic
  • Delete Role Created for Lambda

Conclusion

In this blog we are going to check for list of Unused AMI on weekly basis and deregister those AMI from account using AWS Lambda function in python to save cost.

Stay tuned for my next blog.....

So, did you find my content helpful? If you did or like my other content, feel free to buy me a coffee. Thanks.

Did you find this article valuable?

Support Dheeraj Choudhary by becoming a sponsor. Any amount is appreciated!