AWS Lambda & EventBridge | Find Unused EBS Volumes On Weekly Basis And Notify Via Email
Play this article
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
- 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
- We will invoke the client for EC2
client = boto3.client('ec2')
- 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>)
- 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'}] }, ], )
- 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.
- Now we will traverse the dict using for loop to print list of instances launched by "run_instances" method.
Entire Code is listed belowfor i in resp['Instances']: print("Instance ID Created is :{} Instance Type Created is : {}" .format(i['InstanceId'],i['InstanceType']))
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
- 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
- We will invoke the client for EC2
client = boto3.client('ec2')
- To launch EBS volumes we will have to use create_volume() , you can get the official documentation for this function here
To view entire github code please click hereresponse = ec2.create_volume( AvailabilityZone='us-east-1a', Size=20, VolumeType='gp2', TagSpecifications=[ { 'ResourceType': 'volume', 'Tags': [ { 'Key': 'Name', 'Value': 'Unused_Vol1' }, ] }, ], )
Create SNS Topic And Subscribe
- Open the Amazon SNS console, and then choose Topics from the navigation pane.
- Choose Create topic.
- For Name, enter a name for your topic[Notify-Unused-Volumes].
- For Display name, enter a display name for your topic and choose create topic
- After topic creation click on the Subscriptions tab, choose Create subscription.
- For Protocol, choose Email -> For Endpoint, enter the email address where you want to receive the notifications -> Choose Create subscription.
- A subscription confirmation email is sent to the address you entered. Choose Confirm subscription in the email.
- When you click on confirm you will get below message which confirms your subscription
- Now go back to Topics->EC2-State-Change-Notify and you can see its status has changed from pending to confirmed.
Note the SNS topic ARN you created. You use this topic when creating the EventBridge rule.
Create Lambda Function To Fetch Unused EBS Volumes
- Goto Lambda console and click on create function
- 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.
- Goto code editor and start writing the code.
- 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
- We will invoke the client for EC2
ec2 = boto3.client('ec2')
- We will invoke the client for EC2
sns_client = boto3.client('sns')
- Create empty list to save unused volume id's.
unused_volumes = []
- 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()
- 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)
- 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
To view entire github code please click heresns_client.publish( TopicArn='<SNS Topic ARN>', Subject='Warning - Unused Volume List', Message=str(unused_volumes) )
Using Amazon EventBridge Schedule Lambda On Weekly Basis
- Open Amazon Eventbridge service and open rules. And click on create rule
- 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
- Now lets create our rule to start EC2 instance. First we will define name and description as below
- 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 *
- Select target as the lambda function and select our lambda function to start EC2 instance and click on create.
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.