高能!实现全自动EBS备份[中国区]

我们总是希望机器能为人类多做些事儿,再多做些,再多做些...现在利用cloudwatch + 无服务器化函数Lambda,我们可以实现指定ec2实例磁盘的全自动备份...通过这个教程,我们可以初步感受到无服务器化(serverless)的魅力...懒人福音,大神利器。

-- D.C

内容较多,耐心加载...

要实现全自动这个骚操作,我们会用到两个aws服务:

逻辑关系是: CloudWatch -> lambda -> 备份/删除操作

为lambda创建Policy和Role

我们知道aws对安全是控制得很严的,什么服务有权调用什么服务,那是要用Role里面的Policy来规定的。所以首先我们就要为lambda创建Policy和Role。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "ec2:Describe*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:*Snapshot*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

iam_policy1

iam_policy2

iam_role_create

iam_role_policy

iam_role_review

创建Lambda函数

所有对EC2的信息获取,判断,对EBS的备份,删除过期备份等等功能,都是通过aws的无服务器化服务lambda 函数来完成的,我们以后会用的越来越多的。

lambda_create

lambda_name

import json
import urllib.parse


import boto3
from datetime import datetime,timedelta

print('Loading function')

ec2 = boto3.resource('ec2')

def lambda_handler(event, context):
    instances = ec2.instances.filter(Filters=[{'Name': 'tag:AutoBackup', 'Values': ['yes',]}]).all()
    for instance in instances:
        print("Find AutoSnapshot tagged intance:", instance.id)
        for volume in instance.volumes.all():
            print("Create snapshot for volume: "+volume.id)
            ec2.create_snapshot(VolumeId=volume.id, Description=instance.private_dns_name+" "+volume.id)

lambda_name

lambda_name

这段代码的意思是找到tag的Key是AutoBackup,Value是yes的ec2机器,再找到这台ec2上磁盘对应的snapshot,判断是否过期(是否超过10分钟),过期则将其删除(Purge)。

如果需要修改Purge的周期,可以在代码中修改timedelta函数里面的参数,比如说:如果要设置Purge 12个小时前的快照,可以把minutes=10改成hours=12;如果要设置Purge 7天前的快照,可以改成days=7

一般来说,如果我要每周备份一次,那么就可以将删除周期设置成days=8,保险一点。

import json
import urllib.parse


import boto3
from datetime import datetime,timedelta

print('Loading function')

ec2 = boto3.resource('ec2')

def lambda_handler(event, context):
    instances = ec2.instances.filter(Filters=[{'Name': 'tag:AutoBackup', 'Values': ['yes',]}]).all()
    for instance in instances:
        print("Find AutoSnapshot tagged intance:", instance.id)
        for volume in instance.volumes.all():
            print("Find Volume:" ,volume.id)
            snapshots = ec2.snapshots.filter(Filters=[{'Name': 'volume-id', 'Values': [volume.id]}]).all()
            for snapshot in snapshots:
                if (datetime.utcnow()-snapshot.start_time.replace(tzinfo=None))>timedelta(minutes=10):
                    print ("find old snapshot and delete: ", snapshot.id)
                    snapshot.delete()
                else:
                    print ("newer snapshot: ", snapshot.id)

lambda_list

CloudWatch event设定周期触发

虽然我们设定了一‘备’一‘删’两个函数,但是还缺少一个周期性的触发器,用来触发这两个动作,那么调用CloudWatch Event这个服务就在合适不过啦。

cwe_create

cwe_config1

cwe_config2

cwe_list

给EC2穿上tag马甲

万事俱备,只差马甲了。给我们要自动备份的ec2打上标签吧!

ec2_tag

ec2_addtag

查看EBS磁盘

我们先回忆一下整个过程:

  1. 每隔 5 分钟,对AutoBackup标签值为yes的ec2的磁盘做一次备份;

  2. 每隔 1 分钟,查看AutoBackup标签值为yes的ec2的磁盘snapshot,如果是 10 分钟前创建的,那就将其删除。

  3. 回到ec2控制界面,进入EBS下的Snapshots,可以看到每隔 5 分钟,系统就会自动对我指定的ec2进行打snapshot的操作。

ebs_check

CloudWatch Log查看日志

CWL_list

CWL_list

抛砖引玉

各位客官请扪心自问:哪个备份周期最适合我呢???

温馨提示,涉及修改的地方有:

  1. PurgeSnapshot代码里面的timedelta(minutes=10)

  2. CloudWatch Event的两条Rule中的 Fixed rate of xxx

  3. 为你的ec2打上标签AutoBackup,需要定期备份的为yes,不需要的为no

PS: lambda调用的成本灰常灰常低,每 100 万个请求 ¥1.36, 可忽略不计!

成功,建立在人的社会属性之上。