Резервное копирование сервера AWS EC2 через Lambda

Опубликовано: 17.07.2017
Автор: Виталий Бочкарев
Поддержать автора статьи по этой ссылке

Для того, чтобы обеспечить автоматическое резервное сохранение серверов в Amazon Web Services EC2 я предлагаю воспользоваться скриптом Python, который запускается через сервис AWS Lambda.

Логика скрипта:

  1. Проверить все работающие серверы на наличие метки Backup со значением Yes.
  2. Создать снимок со всех дисков сервера, где указана метка резервного копирования.
  3. Проверить старые автоматические снимки дисков (имя снимка начинается с autosnapshot) на предмет устаревания (более 2 дней).
  4. Удалить старые снимки дисков, найденные на предыдущем шаге.

Код скрипта:

import boto3
import json, datetime
from datetime import tzinfo, timedelta, datetime


print('Loading function')

def lambda_handler(event, context):
   regions = [context.invoked_function_arn.split(':')[3]]
   if 'regions' in event:
       regions = event['regions']

   retention_days = 2
   if 'retention_days' in event:
       retention_days = event['retention_days']

   print("AWS snapshot backups stated at %s...\n" % datetime.now())
   
   for region in regions:
       print("Region: %s" % region)
       create_region_snapshots(region, retention_days)
       
   print("\nAWS snapshot backups completed at %s\n" % datetime.now())

# create snapshot for region
def create_region_snapshots(region, retention_days):
   ec2 = boto3.resource('ec2', region_name=region)
   instances = ec2.instances.filter(
       Filters=[
           {'Name': 'instance-state-name', 'Values': ['running']},
           {'Name': 'tag:Backup', 'Values':['yes','Yes']}
       ])
   for i in instances:
       instance_name = filter(lambda tag: tag['Key'] == 'Name', i.tags)[0]['Value']
       print("\tInstance: %s - %s" % (instance_name, i.id))
       volumes = ec2.volumes.filter(Filters=[{'Name': 'attachment.instance-id', \
         'Values': [i.id]}])
       snapshot_volumes(instance_name, retention_days, volumes)

# create and prune snapshots for volume
def snapshot_volumes(instance_name, retention_days, volumes):
   for v in volumes:
       print("\t\tVolume found: \t%s" % v.volume_id)
       create_volume_snapshot(instance_name, v)
       prune_volume_snapshots(retention_days, v)

# create snapshot for volume
def create_volume_snapshot(instance_name, volume):
   snapname = '%s-%s' % (instance_name,
       datetime.now().strftime("%Y.%m.%d") )
   description = 'autosnapshot %s %s %s' % (instance_name, volume.volume_id,
       datetime.now().strftime("%Y.%m.%d %H:%M:%S") )
   snapshot = volume.create_snapshot(Description=description)
   if snapshot:
       snapshot.create_tags(Tags=[{'Key': 'Name', 'Value': snapname}])
       print("\t\tSnapshot created with description [%s]" % description)

# find and delete snapshots older than retention_days
def prune_volume_snapshots(retention_days, volume):
   for s in volume.snapshots.all():
       now = datetime.now(s.start_time.tzinfo)
       old_snapshot = ( now - s.start_time ) > timedelta(days=retention_days)
       if not old_snapshot or not s.description.startswith('autosnapshot '): continue
       print("\t\tDeleting snapshot [%s - %s] created [%s]" % ( s.snapshot_id, \
         s.description, str( s.start_time )))
       try:
         s.delete()
       except:
         print("\t\tError: snapshot [%s - %s] is blocked and can't be deleted" % ( \
           s.snapshot_id, s.description))

Настройка Lambda функции:

  1. Перейти в AWS Lambda через Services --> Lambda.
  2. Создать новую функцию через Create a Lambda Function.
  3. Выбрать пустую функцию Blank function.
  4. Выбрать триггер CloudWatch Events и создать новое правило для событий:
    Имя: cwr-BackupService.
    Описание: Backup schedule for Lambda.
    Тип: Schedule expression.
    Расписание: rate(1 day).
    Включено: Yes.
  5. Создать саму функцию:
    Имя: lam-BackupService.
    Описание: Backup service for EC2.
    Обработчик: Python 2.7.
    Тип кода: Edit code inline.
    Код: вставить код скрипта.
    Обработчик: lambda_function.lambda_handler.
    Роль: Create custom role (после создания роли будет Choose existing role).
    Имя роли: LAM-BackupService (откроется новое окно, где надо ввести имя роли и нажать Allow).
  6. В дополнительных настройках функции установить:
    Память: 128 MB.
    Время выполнения: 5 minutes (чем больше серверов и их размер, тем дольше будет выполняться функция).
    VPC: no VPC.
  7. Проверить все параметры и создать функцию.

Использование функции в EC2:

  1. Перейти в AWS EC2 через Services --> EC2.
  2. Выбрать любой работающий сервер.
  3. На вкладке Tags нажать Add/Edit Tags.
  4. Создать метку Backup со значением Yes.
  5. Вернуться в AWS Lambda через Services --> Lambda.
  6. Выбрать функцию lam-BackupService.
  7. Нажать кнопку Test - функция запустится, а под ней будет отображен лог работы.
    START RequestId: 0f1ec135-6ac3-11e7-a2f9-79390a179184 Version: $LATEST
    AWS snapshot backups stated at 2017-07-17 07:39:26.504412...
    
    Region: eu-west-1
    MyTestServer - i-09c37a1234565c80b
    Volume found: vol-09b7f123456f1bb2b
    Snapshot created with description [autosnapshot MyTestServer vol-09b7f123456f1bb2b ...]
    
    AWS snapshot backups completed at 2017-07-17 07:39:31.038931
    
    END RequestId: 0f1ec135-6ac3-11e7-a2f9-79390a179184
    REPORT RequestId: 0f1ec135-6ac3-11e7-a2f9-79390a179184 Duration: 4534.80 ms Billed Duration: 4600 ms
  8. Вернуться в AWS EC2 через Services --> EC2.
  9. Перейти на вкладку снимков томов Snapshots - здесь можно найти только что сделанный снимок с диска сервера.
  10. Перейти в AWS CloudWatch через Services --> CloudWatch.
  11. Перейти на вкладку журналов Logs и выбрать журнал /aws/lambda/lam-BackupService.
  12. Выбрав поток вывода функции от нужной даты, можно посмотреть ход выполнения операции резервного копирования за любой день.

Функция резервного копирования готова к работе.

Примечание. Длительность хранения снимков томов можно отрегулировать параметром retention_days в теле функции или указать этот параметр во входящих параметрах к функции в триггере cwr-BackupService.