Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Varun Chandak
committed
Feb 3, 2019
1 parent
c7aff5b
commit 6ab401d
Showing
3 changed files
with
159 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# AMI Backups and Retention using AWS Lambda | ||
|
||
--- | ||
#### NOTE: AMI and Instance Names and Name Tags must be between 3 and 128 characters long, and may contain letters, numbers, '(', ')', '.', '-', '/' and '_' only. Not following this nomenclature will lead to failure of the lambda function. | ||
--- | ||
|
||
Here, we are using 2 AWS Lambda functions viz., **createAMI** and **deleteAMI**, which will create AMIs and delete AMIs, respectively. Both these functions are explained in detail below. **<u>Please note that both the lambda functions cover all the regions.</u>** | ||
|
||
## createAMI | ||
|
||
**Table of details:** | ||
|
||
| Name | Value | | ||
| --------------------------- | ----------------- | | ||
| Name of the Lambda Function | createAMI | | ||
| Timeout | 5 min | | ||
| Role Permissions | `ec2:*` | | ||
| Runtime | `python2.7` | | ||
| File Name | `createAMI.py` | | ||
| Schedule | `rate(5 minutes)` | | ||
|
||
**Documentation:** | ||
|
||
The lambda function make use of tags on EC2 intances which provides all the information required to create an AMI. The table below explains the tags required. | ||
|
||
| Tag Name | Format | Default Value | | ||
| --------- | ------------ | ------------- | | ||
| AMIBackup | Yes/No | No | | ||
| AMITime | HH:MM | 15:00 | | ||
| Reboot | Yes/No | No | | ||
| Retention | Whole Number | 7 | | ||
|
||
In the above table: | ||
|
||
- `AMIBackup`: It is used to specify which Instance has to be backed up. | ||
- `AMITime`: It is used to specify the time when the AMI has to be created. | ||
- `Reboot`: It is used to specify if the instance has to be rebooted when creating the AMI. | ||
- `Retention`: It is used to specify the AMI retention period in **days**. | ||
|
||
--- | ||
|
||
## deleteAMI | ||
|
||
**Table of details:** | ||
|
||
| Name | Value | | ||
| --------------------------- | --------------------- | | ||
| Name of the Lambda Function | deleteAMI | | ||
| Timeout | 5 min | | ||
| Role Permissions | `ec2:*` | | ||
| Runtime | `python2.7` | | ||
| File Name | `deleteAMI.py` | | ||
| Schedule | `cron(00 15 * * ? *)` | | ||
|
||
**Documentation:** | ||
|
||
The lambda function make use of tags on EC2 intances which provides all the information required to delete an AMI. The tags are copied from the instance to AMI via **createAMI** function. The table below explains the tags required. | ||
|
||
| Tag Name | Format | Default Value | | ||
| --------- | ------------ | -------------------- | | ||
| AMIBackup | Yes/No | Copied from Instance | | ||
| AMITime | HH:MM | Copied from Instance | | ||
| Reboot | Yes/No | Copied from Instance | | ||
| Retention | Whole Number | Copied from Instance | | ||
|
||
In the above table(s): | ||
|
||
* `AMIBackup`: It is used to specify which Instance has to be backed up. **deleteAMI** will only get triggered if this tag is present with `Yes` value. | ||
* `AMITime`: It is used to specify the time when the AMI has to be created. | ||
* `Reboot`: It is used to specify if the instance has to be rebooted when creating the AMI. | ||
* `Retention`: It is used to specify the AMI retention period in **days**. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
def lambda_handler(event, context): | ||
# TODO implement | ||
import boto3 | ||
import datetime | ||
|
||
client = boto3.client('ec2') | ||
regions = [region['RegionName'] for region in client.describe_regions()['Regions']] | ||
for regionnaire in regions: | ||
print regionnaire | ||
ec2 = boto3.client("ec2", region_name=regionnaire) | ||
instances_list = ec2.describe_instances() | ||
nowtime = datetime.datetime.now().strftime('%d%m%Y-%H-%M') | ||
for reservation in instances_list['Reservations']: | ||
for instance in reservation['Instances']: | ||
ami = False | ||
reboot = False | ||
retention = 7 | ||
# UTC Time for IST Zone | ||
timeToCreate = "18:30" | ||
instanceName = "Unnamed" | ||
if instance.get("Tags",None) != None: | ||
tags = instance["Tags"] | ||
for tag in tags: | ||
if(tag["Key"] == "AMIBackup" and tag["Value"] == "Yes"): | ||
ami = True | ||
if(tag["Key"] == "Reboot" and tag["Value"] == "Yes"): | ||
reboot = True | ||
if(tag["Key"] == "AMITime"): | ||
timeToCreate = tag["Value"] | ||
if(tag["Key"] == "Retention"): | ||
retention = tag["Value"] | ||
if(tag["Key"] == "Name"): | ||
instanceName = tag["Value"] | ||
if(ami==True): | ||
timeToCreate = datetime.datetime.strptime(timeToCreate,"%H:%M") | ||
currTimeStr = datetime.datetime.now().strftime("%H:%M") | ||
currTime = datetime.datetime.strptime(currTimeStr,"%H:%M") | ||
delta = currTime - timeToCreate | ||
deltaMinutes = abs(delta.total_seconds()) | ||
if(deltaMinutes < 900): | ||
createImageResponse = ec2.create_image( | ||
InstanceId = instance['InstanceId'], | ||
NoReboot=(not reboot), | ||
DryRun=False, | ||
Description= instanceName + "-" + str(nowtime), | ||
Name= instanceName + "-" + str(nowtime) | ||
) | ||
imageId = createImageResponse["ImageId"] | ||
print imageId | ||
final_tags = [] | ||
for tag in tags: | ||
if not (tag['Key']=="Name"): | ||
final_tags.append(tag) | ||
if not (tag['Key'].startswith("aws:") or tag['Value'].startswith("aws:")): | ||
final_tags.append(tag) | ||
ec2.create_tags(Resources=[imageId],Tags=final_tags) | ||
return 'createAMI run successfully' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
def lambda_handler(event, context): | ||
import boto3 | ||
import datetime | ||
import time | ||
|
||
client = boto3.client('ec2') | ||
regions = [region['RegionName'] for region in client.describe_regions()['Regions']] | ||
for regionnaire in regions: | ||
print regionnaire | ||
ec2 = boto3.client("ec2", region_name=regionnaire) | ||
response = ec2.describe_images(Owners=['self'],DryRun=False) | ||
for i in range(len(response['Images'])): | ||
ami = False | ||
retention = 7 | ||
creationDate = response["Images"][i]["CreationDate"][:10] | ||
AMIdate = datetime.datetime.strptime(creationDate, '%Y-%m-%d') | ||
timeStampNow = datetime.datetime.now() | ||
if response['Images'][i].get("Tags",None) != None : | ||
tags = response['Images'][i]['Tags'] | ||
for tag in tags: | ||
if(tag["Key"] == "AMIBackup" and tag["Value"] == "Yes"): | ||
ami = True | ||
if(tag["Key"] == "Retention"): | ||
retention = tag["Value"] | ||
if(ami==True): | ||
if (timeStampNow - AMIdate).days >= int(retention): | ||
print str("Deleting AMI: ") + response["Images"][i]["ImageId"] | ||
deregisterImageResponse = client.deregister_image(ImageId=response['Images'][i]['ImageId']) | ||
time.sleep(1) | ||
for k in range(len(response['Images'][i]['BlockDeviceMappings'])): | ||
deleteSnapshotResponse = client.delete_snapshot(SnapshotId=response['Images'][i]['BlockDeviceMappings'][k]['Ebs']['SnapshotId']) |