AWS Lambda & EventBridge | Find Unused EBS Volumes On Weekly Basis And Notify Via Email

AWS Lambda & EventBridge | Find Unused EBS Volumes On Weekly Basis And Notify Via Email

Prerequisite

An AWS Account An IAM User with:

  • AWS Management Console access to verify your EC2 instances launched,listed and terminated.
  • The IAM permissions required to perform IAM, EC2, and CloudWatch activities. IAM policy creation and AWS Application Programming Interface (API) permissions are outside this article’s scope. Always adhere to the principle of least privilege when authorizing accounts to perform actions. Administrative access to an EC2 Instance.

Create new role for our lambda functions. :- Create new role named Lambda_Unused and attach below policies to it.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "sns:ListSubscriptionsByTopic",
                "sns:GetTopicAttributes",
                "sns:ListSMSSandboxPhoneNumbers",
                "logs:*",
                "sns:ListTopics",
                "sns:ListSubscriptions",
                "ec2:DescribeVolumeAttribute",
                "sns:ListOriginationNumbers",
                "sns:ListEndpointsByPlatformApplication",
                "sns:Publish",
                "ec2:DescribeVolumeStatus",
                "ec2:DescribeVolumes",
                "sns:ListPlatformApplications"
            ],
            "Resource": "*"
        }
    ]
}

Launch 2 AWS EC2 Instance Using Boto3 Script

  1. 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
    
  2. We will invoke the client for EC2
    client = boto3.client('ec2')
    
  3. To launch EC2 instances we have to use method "run_instances()". This method helps us launch AWS EC2 instances based on our requirement.
    response =client.run_instances(<arguments>)
    
  4. Goto link where you will find all arguments list. Based on your requirement you can put this arguments to launch your EC2 instances. This document also mentions datatype of the parameter.
    Note:- Arguments which are with "REQUIRED" tags mentioned in documentation is mandatory, if you don't specify those arguments code block to launch EC2 will not execute successfully.
    Example:- "MinCount", "MaxCount".
    Below code will launch EC2 instance based on your provided input.
    resp=client.run_instances(ImageId='ami-0742b4e673072066f',
                           InstanceType='t2.micro',
                           MinCount=2,
                           MaxCount=2,
                           KeyName='CustomVPC',
                           TagSpecifications=[
                               {
                                   'ResourceType': 'instance',
                                   'Tags': [{'Key': 'Name','Value': 'Linux Server'},
                                            {'Key': 'Env','Value': 'Dev'}]
                               },
                           ],
                           )
    
  5. Once above method will run it will launch EC2 and launched EC2 information will be captured in variable "resp". It will return infomation in dictonary, so "resp" would be a dictonary.
  6. Now we will traverse the dict using for loop to print list of instances launched by "run_instances" method.
    for i in resp['Instances']:
    print("Instance ID Created is :{} Instance Type Created is : {}" .format(i['InstanceId'],i['InstanceType']))
    
    Entire Code is listed below
    import boto3
    client = boto3.client('ec2')
    resp=client.run_instances(ImageId='ami-0742b4e673072066f',
                          InstanceType='t2.micro',
                          MinCount=2,
                          MaxCount=2,
                          KeyName=<Your Keyname>,
                          TagSpecifications=[
                              {
                                  'ResourceType': 'instance',
                                  'Tags': [{'Key': 'Name','Value': 'Linux Server'},
                                           {'Key': 'Env','Value': 'Dev'}]
                              },
                          ],
                          )
    for i in resp['Instances']:
    print("Instance ID Created is :{} Instance Type Created is : {}" .format(i['InstanceId'],i['InstanceType']))
    

Create EBS Volumes Using Boto3 Script

  1. 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
    
  2. We will invoke the client for EC2
    client = boto3.client('ec2')
    
  3. To launch EBS volumes we will have to use create_volume() , you can get the official documentation for this function here
    response = ec2.create_volume(
     AvailabilityZone='us-east-1a',
     Size=20,
     VolumeType='gp2',
     TagSpecifications=[
         {
             'ResourceType': 'volume',
             'Tags': [
                 {
                     'Key': 'Name',
                     'Value': 'Unused_Vol1'
                 },
             ]
         },
     ],
    )
    
    To view entire github code please click here

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-Volumes]. 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 Lambda Function To Fetch Unused EBS Volumes

  1. Goto Lambda console and click on create function image.png
  2. Select "Author From Scratch" , Function name = unused_volumes, 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. We will invoke the client for EC2
    sns_client = boto3.client('sns')
    
  7. Create empty list to save unused volume id's.
    unused_volumes = []
    
  8. Now we will call describe_volumes() function to get the list of all existing volumes in our account and save the returned dict in volumes , you can get the official documentation for this function here
    import boto3
    ec2 = boto3.client('ec2')
    sns_client = boto3.client('sns')
    unused_volumes = []
    volumes = ec2.describe_volumes()
    
  9. Now lets traverse the dictonary volumes and check which all volume id's are having attachment as null using if condition and append the volume id's to our empty list.
    def lambda_handler(event, context):
     unused_volumes = []
     for vol in volumes['Volumes']:
         if len(vol['Attachments']) == 0:
             vol1 = ("-----Unused Volume ID = {}------".format(vol['VolumeId']))
             unused_volumes.append(vol1)
    
  10. Now we will use publish() function to send email with list of volume ids and configure the email message and subject accordingly, you can get the official documentation for this function here
    sns_client.publish(
    TopicArn='<SNS Topic ARN>',
    Subject='Warning - Unused Volume List',
    Message=str(unused_volumes)
    )
    
    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

  1. 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
  2. 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 EBS Volumes
  • Terminate EC2 instances
  • Delete Role Created for Lambda

Conclusion

This lambda function runs on weekly basis and provides the list of unused Volumes so it can be checked further and deleted if not required 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!