0
votes

I am trying to delete old RDS snapshots using the following python script for AWS Lambda, but when I try to run the script, it gives me the error "Task timed out after [whatever timeout period I've specified]." I've tried increasing the timeout period to a few minutes, which is way more time than this task should take, so I am fairly confident that it is not because I have too short a timeout period. Furthermore, this code works just fine when run from an EC2 instance rather than from Lambda.

import boto3
import pprint
import time
import re
import datetime

def lambda_handler(event, context):

    DAYS_EXPIRE = 2

    client = boto3.client('rds', region_name='us-east-1')

    snapshots = client.describe_db_snapshots(
            DBInstanceIdentifier='test-rds-instance',
            SnapshotType='manual',
            MaxRecords=100
    )

    list_snapshots = snapshots['DBSnapshots']
    for snap in list_snapshots:
        dbs_id = snap['DBSnapshotIdentifier']
        delta_datetime = datetime.timedelta(days=DAYS_EXPIRE)
        acceptable_datetime = datetime.datetime.now() - delta_datetime
        datestring = re.search(r'\d{4}-\d{2}-\d{2}-\d{2}-\d{2}$', dbs_id).group()
        datetime_snapshot = datetime.datetime.strptime(datestring, '%Y-%m-%d-%H-%M')
        if (datetime_snapshot < acceptable_datetime):
            print "Deleting" + dbs_id
            client.delete_db_snapshot(DBSnapshotIdentifier=dbs_id)

I tried commenting out various parts and rerunning in order to figure out where the error was occurring, and I think it's here:

snapshots = client.describe_db_snapshots(
            DBInstanceIdentifier='test-rds-instance',
            SnapshotType='manual',
            MaxRecords=100
    )

I'm not sure why, since it's working outside of Lambda, but I think that it is an issue with the connection. The script has an IAM policy attached to it which allows it VPC for Lambda access and full RDS access. I don't know if security groups restrict Lambda requests or not, but just in case, I modified the security group of the RDS instance to accept all inbound traffic. The RDS instance is publicly accessible. I also tried modifying the client definition to include the RDS endpoint as given in the console (although this threw the error "invalid endpoint") as well as to take in access key id and access key. However this didn't work either. Any suggestions?

1
Are you running Lambda and rds in same aws region?notionquest

1 Answers

3
votes

This statement makes no sense:

The script has an IAM policy attached to it which allows it VPC for Lambda access and full RDS access.

The IAM policy and the VPC are two completely different things. Also, you aren't opening a connection to your database in your Lambda function anywhere, so the stuff about the database being publically accessible isn't relevant. All your code is doing is making calls to the AWS API to manage resources in your AWS account. For that your Lambda function just needs Internet access and the appropriate IAM role.

It sounds like you have probably placed your Lambda function inside your VPC. When you do that a Lambda function can only access resources inside your VPC. That means your function can't access the AWS API or the Internet. You can fix this by adding a NAT gateway to your VPC.

However, since your Lambda function isn't actually accessing anything in your VPC, the easiest and cheapest solution would be to remove your Lambda function from your VPC. Then it should be able to make the AWS API calls to manage your RDS resources.