Jelikož v práci používáme pro kritické projekty několik EC2 instancí od Amazonu, museli jsme řešit i nějaké to zálohování. Vedle toho, že databázi máme zálohovanou jako “point-in-time” + hodinové zálohy do S3 úložiště jsme, jsme se rozhodli dělat i snapshoty celých instancí.

Řešení

Před dvěma týdny začala AWS Lambda (je služba, které předhodíte kousek kódu a ona jej pak spouští jako reakci na různé eventy) podporovat vedle node.js a javy i python! Zaradoval, že to budu moci konečně naplno využívat :)

Výsledný postup zálohování je následující:

  • AWS Lambda ve vybraný čas (má integrovaný cron) zavolá naši funkci
  • pomocí API si najdeme všechny instance
  • invokujeme vytvoření snapshotů jejich primárních disků
  • ze seznamu všech snapshotů (které mají název našich instancí), vybere ty které jsou starší než 7 dní
  • smažeme staré snapshoty

Jak to nastavit u sebe?

Kód

Následující kód je potřeba dát do Lambda funkci:

import json
import boto3
import json
import time
import datetime

ec2 = boto3.resource('ec2')

print('Loading function')


def lambda_handler(event, context):
    for i in ec2.instances.all():
            for tag in i.tags:
                if tag['Key'] == 'Name':
                    instance_name = tag['Value']
                    print(instance_name)

            vol_id = i.block_device_mappings[0]['Ebs']['VolumeId']
            print(vol_id)

            volume = ec2.Volume(vol_id)
            print(volume.size)

            snapshot = volume.create_snapshot()
            tag = snapshot.create_tags(
                Tags=[
                {
                    'Key': 'Name',
                    'Value': instance_name
                }
            ]
            )

            snps = ec2.snapshots.filter(
                Filters=[
                    {
                        'Name': 'tag:Name',
                        'Values': [
                            instance_name,
                        ]
                    }
                ]
            )

            for snp in snps:
                if time.time() - int(time.mktime(snp.start_time.timetuple())) > 3600*24*7:
                    print("delete:", snp.snapshot_id)
                    snp.delete()


    return True

Nastavení

Aby funkce mohla dělat všechny ty kouzla, je nutné jí nastavit potřebná práva :)

V IAM vytvoříme novou roli, která bude mít následující “managed policies”:

  • AmazonEC2ReadOnlyAccess
  • AWSLambdaBasicExecutionRole

Dále vytvoříme inline policy, která povolí vytvářet a mazat snapshoty, její definice bude:


{
    "Version": "2015-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateTags"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateSnapshot",
                "ec2:DeleteSnapshot"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

Závěrem

Výhodou tohoto způsobu zálohování je, že pokud potřebujete rychle obnovit zálohu, stačí vytvořit nový EBS disk ze snapshotu a následně přehodit disky/nastartovat novou VPS a přehodit IP.

Zároveň je řešení v podstatě zadarmo, neboť za jeden běh Lambda funkce nezaplatíte ani cent měsíčně :).. platíme pouze snapshot storage podle ceníku (aktuálně $0.095 za GB, data jsou ale ukládána inkrementálně a komprimované).

V případě jakýchkoli dotazů, připomínek, nejasností se neváhejte zeptat (diskuze, email, …) :)