Olá, abaixo apresento 3 scripts em Python 2.7 para inserir no Lambda e executar via agendamento no Cloudwatch com o objetivo de gerar Snapshots das EC2 e também criar AMIs destas maquinas, excluindo após um período de retenção.
Com isto, você terá snapshots e AMI dos servidores e os mais antigos serão excluídos.
No IAM (Identi Access Management) você deverá criar 1 role, aqui eu a chamei de "AWS_backup" e ela possui 2 polices.
Uma para o EC2 (snapshot da instancia) e outra para o AMI.
Segue o código:
Policy 'ec2-snapshot': { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:*" ], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": "ec2:Describe*", "Resource": "*" }, { "Effect": "Allow", "Action": [ "ec2:CreateSnapshot", "ec2:DeleteSnapshot", "ec2:CreateTags", "ec2:ModifySnapshotAttribute", "ec2:ResetSnapshotAttribute" ], "Resource": [ "*" ] } ] } Policy 'AMI-backup': { "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1476467851000", "Effect": "Allow", "Action": [ "ec2:CreateImage", "ec2:DeregisterImage", "ec2:DescribeImageAttribute", "ec2:DescribeImages" ], "Resource": [ "*" ] } ] }
Após isto, vamos criar o script responsável por criar e tagear os snapshots (script no lambda com python 2.7), nomeie-e com o nome que desejar, lembre-se da descrição também (importante!), você usará o nome dele posteriormente para agendar a execução.
No seu script, você precisará trocar o nome da região (eu utilizo a 'us-east-1').
Outra coisa que deverá mudar é a "Key-tag".
Para determinar quais servidores (EC2) terão seus snapshots e AMI criados automaticamente, eu criei uma tag chamada "Backup" e para todas as maquinas que eu quero o snapshot, coloquei a tag como "True" (como na imagem abaixo):
Script:
import boto3 import collections import datetime ec = boto3.client('ec2', region_name='us-east-1') #begins lambda function def lambda_handler(event, context): reservations = ec.describe_instances( Filters=[ {'Name': 'tag-key', 'Values': ['Backup', 'True']}, ] ).get( 'Reservations', [] ) instances = sum( [ [i for i in r['Instances']] for r in reservations ], []) print "Number of the Instances : %d" % len(instances) to_tag = collections.defaultdict(list) for instance in instances: try: retention_days = [ int(t.get('Value')) for t in instance['Tags'] if t['Key'] == 'Retention'][0] except IndexError: # Please give your retention period day retention_days = 5 for dev in instance['BlockDeviceMappings']: if dev.get('Ebs', None) is None: continue vol_id = dev['Ebs']['VolumeId'] for name in instance['Tags']: # To store the instance tag value Instancename= name['Value'] # To store the instance key value key= name['Key'] # Below the code is create Snapshot name as instance Name if key == 'Name' : ins_name = Instancename print "Found EBS volume %s on instance %s" % ( vol_id, instance['InstanceId']) #To get all the instance tags deatils for name in instance['Tags']: # To store the instance tag value Instancename= name['Value'] # To store the instance key value key= name['Key'] # Below the code is create Snapshot name as instance Name if key == 'Name' : snap = ec.create_snapshot( VolumeId=vol_id, Description=Instancename, ) print "snap %s" %snap to_tag[retention_days].append(snap['SnapshotId']) print "Retaining snapshot %s of volume %s from instance %s for %d days" % ( snap['SnapshotId'], vol_id, instance['InstanceId'], retention_days, ) for retention_days in to_tag.keys(): delete_date = datetime.date.today() + datetime.timedelta(days=retention_days) snap = snap['Description'] + str('_') # Here to get current date snapshot = snap + str(datetime.date.today()) # to mention the current date formet delete_fmt = delete_date.strftime('%Y-%m-%d') print "Will delete %d snapshots on %s" % (len(to_tag[retention_days]), delete_fmt) # below code is create the name and current date as instance name ec.create_tags( Resources=to_tag[retention_days], Tags=[ {'Key': 'DeleteOn', 'Value': delete_fmt}, {'Key': 'Name', 'Value': snapshot }, ] ) to_tag.clear()
Agora, vamos criar o script responsável por apagar os snapshots antigos.
Novamente, use o Python 2.7 como runtime, note que a tag para deletar é diferente (ele irá criar a tag e inserir como valor a data em que deverá ser deletado) e atente-se ao region_name:
import boto3 import re import datetime #Please mention your region name #below line code is call cross region ec = boto3.client('ec2', region_name='us-east-1') iam = boto3.client('iam') #begins lambda function def lambda_handler(event, context): account_ids = list() try: iam.get_user() except Exception as e: # use the exception message to get the account ID the function executes under account_ids.append(re.search(r'(arn:aws:sts::)([0-9]+)', str(e)).groups()[1]) delete_on = datetime.date.today().strftime('%Y-%m-%d') filters = [ {'Name': 'tag-key', 'Values': ['DeleteOn']}, {'Name': 'tag-value', 'Values': [delete_on]}, ] snapshot_response = ec.describe_snapshots(OwnerIds=account_ids, Filters=filters) for snap in snapshot_response['Snapshots']: print "Deleting snapshot %s" % snap['SnapshotId'] ec.delete_snapshot(SnapshotId=snap['SnapshotId'])
Nosso terceiro e ultimo script será responsável por criar e remover as images das instâncias (AMI), perceba que o tempo de retenção meu é de 5 dias:
import boto3 import collections import datetime ec = boto3.client('ec2') def lambda_handler(event, context): reservations = ec.describe_instances( Filters=[ {'Name': 'tag-key', 'Values': ['backup', 'Backup']}, ] ).get( 'Reservations', [] ) instances = sum( [ [i for i in r['Instances']] for r in reservations ], []) print "Found %d instances that need backing up" % len(instances) to_tag = collections.defaultdict(list) for instance in instances: try: retention_days = [ int(t.get('Value')) for t in instance['Tags'] if t['Key'] == 'Retention'][0] except IndexError: retention_days = 5 finally: create_time = datetime.datetime.now() create_fmt = create_time.strftime('%Y-%m-%d.%H.%M.%S') AMIid = ec.create_image(InstanceId=instance['InstanceId'], Name="Lambda - " + instance['InstanceId'] + " From " + create_fmt, Description="Lambda created AMI of instance " + instance['InstanceId'], NoReboot=True, DryRun=False) to_tag[retention_days].append(AMIid['ImageId']) print "Retaining AMI %s of instance %s for %d days" % ( AMIid['ImageId'], instance['InstanceId'], retention_days, ) for retention_days in to_tag.keys(): delete_date = datetime.date.today() + datetime.timedelta(days=retention_days) delete_fmt = delete_date.strftime('%m-%d-%Y') print "Will delete %d AMIs on %s" % (len(to_tag[retention_days]), delete_fmt) ec.create_tags( Resources=to_tag[retention_days], Tags=[ {'Key': 'DeleteOn', 'Value': delete_fmt}, ] )
Por fim,
O último passo e criar o agendamento para execução disto dentro do Cloudwatch, basta seguir o Wizard e apontar para os scripts criados em Python no Lambda.
Comentários
Postar um comentário