如何自动对 Amazon EC2 实例的卷进行快照?

Posted

技术标签:

【中文标题】如何自动对 Amazon EC2 实例的卷进行快照?【英文标题】:How to automatically snapshot a volume of an Amazon EC2 instance? 【发布时间】:2012-03-28 20:54:57 【问题描述】:

我正在尝试使用脚本自动备份卷。

我遵循 github 上的 EBS-Snapshot.sh 脚本:

#!/bin/bash

# export EC2_HOME='/etc/ec2'  # Make sure you use the API tools, not the AMI tools
# export EC2_BIN=$EC2_HOME/bin
# export PATH=$PATH:$EC2_BIN
# I know all of the above is good to have solution, but not re-usable
# I have captured all of the above in a particular file and lemme execute it
source /etc/environment

PURGE_SNAPSHOT_IN_DAYS=10

EC2_BIN=$EC2_HOME/bin

# store the certificates and private key to your amazon account
MY_CERT='/path/to/certificate-file'
MY_KEY='/path/to/private-file'
# fetching the instance-id from the metadata repository
MY_INSTANCE_ID='your ec2-instance-id'

# temproary file
TMP_FILE='/tmp/rock-ebs-info.txt'

# get list of locally attached volumes via EC2 API:
$EC2_BIN/ec2-describe-volumes -C $MY_CERT -K $MY_KEY > $TMP_FILE
VOLUME_LIST=$(cat $TMP_FILE | grep $MY_INSTANCE_ID | awk ' print $2 ')

sync

#create the snapshots
echo "Create EBS Volume Snapshot - Process started at $(date +%m-%d-%Y-%T)"
echo ""
echo $VOLUME_LIST
for volume in $(echo $VOLUME_LIST); do
   NAME=$(cat $TMP_FILE | grep Name | grep $volume | awk ' print $5 ')
   DESC=$NAME-$(date +%m-%d-%Y)
   echo "Creating Snapshot for the volume: $volume with description: $DESC"
   echo "Snapshot info below:"
   $EC2_BIN/ec2-create-snapshot -C $MY_CERT -K $MY_KEY -d $DESC $volume
   echo ""
done

echo "Process ended at $(date +%m-%d-%Y-%T)"
echo ""

rm -f $TMP_FILE

#remove those snapshot which are $PURGE_SNAPSHOT_IN_DAYS old

我有两个用于 X509 身份验证的文件,即实例 ID,但我不了解脚本以及如何参数化要备份的卷。

我不明白第一行(来源)和 EC2_BIN。 使用该配置,它会列出所有卷并制作所有这些卷的快照...

对于快照的注释,如何更改此行以添加文本?​​

DESC=$NAME-$(date +%m-%d-%Y)

对不起,我是初学者,但我不明白整个脚本

编辑:

我收到这个新代码的错误:

为卷创建快照:([ec2-describe-volumes]) 描述:-03-13-2012 快照信息如下: Client.InvalidParameterValue: 值 (([ec2-describe-volumes])) 参数volumeId 无效。预期:'vol-...'。流程结束于 03-13-2012-08:11:35 –

这是代码:

#!/bin/bash

#Java home for debian default install path:
export JAVA_HOME=/usr
#add ec2 tools to default path
#export PATH=~/.ec2/bin:$PATH


#export EC2_HOME='/etc/ec2'  # Make sure you use the API tools, not the AMI tools
export EC2_BIN=/usr/bin/
#export PATH=$PATH:$EC2_BIN
# I know all of the above is good to have solution, but not re-usable
# I have captured all of the above in a particular file and lemme execute it
source /etc/environment

PURGE_SNAPSHOT_IN_DAYS=60

#EC2_BIN=$EC2_HOME/bin

# store the certificates and private key to your amazon account
MY_CERT='cert-xx.pem'
MY_KEY='pk-xx.pem'
# fetching the instance-id from the metadata repository

MY_INSTANCE_ID=`curl http://169.254.169.254/1.0/meta-data/instance-id`

# temproary file
TMP_FILE='/tmp/rock-ebs-info.txt'

# get list of locally attached volumes via EC2 API:
$EC2_BIN/ec2-describe-volumes -C $MY_CERT -K $MY_KEY > $TMP_FILE

#VOLUME_LIST=$(cat $TMP_FILE | grep $MY_INSTANCE_ID | awk ' print $2 ')
VOLUME_LIST=(`ec2-describe-volumes --filter attachment.instance-id=$MY_INSTANCE_ID | awk ' print $2 '`)

sync

#create the snapshots
echo "Create EBS Volume Snapshot - Process started at $(date +%m-%d-%Y-%T)"
echo ""
echo $VOLUME_LIST
echo "-------------"
for volume in $(echo $VOLUME_LIST); do
   NAME=$(cat $TMP_FILE | grep Name | grep $volume | awk ' print $5 ')
   DESC=$NAME-$(date +%m-%d-%Y)
   echo "Creating Snapshot for the volume: $volume with description: $DESC"
   echo "Snapshot info below:"
   $EC2_BIN/ec2-create-snapshot -C $MY_CERT -K $MY_KEY -d $DESC $volume
   echo ""
done

echo "Process ended at $(date +%m-%d-%Y-%T)"
echo ""

rm -f $TMP_FILE

#remove those snapshot which are $PURGE_SNAPSHOT_IN_DAYS old

【问题讨论】:

【参考方案1】:

上述解决方案对我来说并不完全有效。在与亚马逊支持人员聊天一小时后,我现在有了这个工作脚本,它将始终创建附加到当前实例的所有卷的快照:

#!/bin/bash

# Set Environment Variables as cron doesn't load them
export JAVA_HOME=/usr/lib/jvm/java-6-sun
export EC2_HOME=/usr
export EC2_BIN=/usr/bin/
export PATH=$PATH:$EC2_HOME/bin
export EC2_CERT=/home/ubuntu/.ec2/cert-SDFRTWFASDFQFEF.pem
export EC2_PRIVATE_KEY=/home/ubuntu/.ec2/pk-SDFRTWFASDFQFEF.pem
export EC2_URL=https://eu-west-1.ec2.amazonaws.com # Setup your availability zone here

# Get instance id of the current server instance
MY_INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
# get list of locally attached volumes 
VOLUMES=$(ec2-describe-volumes | grep $MY_INSTANCE_ID | awk ' print $2 ')
echo "Instance-Id: $MY_INSTANCE_ID" 

    # Create a snapshot for all locally attached volumes
    LOG_FILE=/home/ubuntu/ebsbackup/ebsbackup.log
    echo "********** Starting backup for instance $MY_INSTANCE_ID" >> $LOG_FILE
    for VOLUME in $(echo $VOLUMES); do
        echo "Backup Volume:   $VOLUME" >> $LOG_FILE
        ec2-consistent-snapshot --aws-access-key-id ASDASDASDASD --aws-secret-access-key asdfdsfasdfasdfasdfasdf --mysql --mysql-host localhost --mysql-username root --mysql-password asdfasdfasdfasdfd --description "Backup ($MY_INSTANCE_ID) $(date +'%Y-%m-%d %H:%M:%S')" --region eu-west-1 $VOLUME
done
echo "********** Ran backup: $(date)" >> $LOG_FILE
echo "Completed"

我在 /etc/cron.d/ebsbackup 中设置了一个 cronjob

01 * * * * ubuntu /home/ubuntu/.ec2/myscriptname

这对我来说很好用... :-)

希望这对你有帮助, 塞巴斯蒂安

【讨论】:

【参考方案2】:

好吧,

    他运行的第一行(来源)。那是一样的。 /等/环境。无论如何,他所做的只是加载一个文件,其中包含亚马逊所需的环境变量列表。至少这是我的假设。 他让这个脚本变得比它需要的复杂得多。他不需要运行 ec2-describe-instances 命令并将输出保存到文件然后 grep 输出等...... 您可以为 DESC 放置任何您想要的内容。您可以将 = 右侧的所有内容替换为您想要的任何文本。只需确保在其周围加上引号即可。

我会改变这个脚本的两点。

    在运行时在脚本中获取 InstanceId。不要将其硬编码到脚本中。无论脚本在哪里运行,此行都将起作用。

    MY_INSTANCE_ID=`curl http://169.254.169.254/1.0/meta-data/instance-id`
    

    而不是调用 ec2-describe-volumes 并将输出保存到临时文件等...只需在命令上使用过滤器并告诉它您想要哪个实例 ID。

    VOLUME_LIST=(`ec2-describe-volumes --filter attachment.instance-id=$MY_INSTANCE_ID | awk ' print $2 '`)
    

【讨论】:

好的,非常感谢您的解释,我搜索了一整天,我问自己有关“全局”变量的问题 :-) 感谢对实例 ID 和卷列表、卷的小改进清单给我带来了一些麻烦。我将修改描述并修复“Client.InvalidParameterValue: Value (([ec2-describe-volumes])) for parameter volumeId is invalid. Expected: 'vol-...'.'仍然存在的错误:-) 小心更改描述。确保在其周围添加引号以小心。如果您收到错误 Client.InvalidParameterValue ,那是因为卷 ID 为空,或者您用于描述的文本有空格,并且它读取卷 ID 描述的部分 我又遇到了这个问题。这是屏幕上打印的整个过程:为卷创建快照:([ec2-describe-volumes]),描述:-03-13-2012 快照信息如下:Client.InvalidParameterValue:值(([ec2-describe- volumes])) 的参数 volumeId 无效。预期:'vol-...'。流程于 03-13-2012-08:11:35 结束 $volume "worth" (([ec2-describe-volumes])) 在“for”... 如何正确获取卷以使快照生效? 您能否使用您尝试运行的脚本更新您的答案。如果你愿意,我可以试试。【参考方案3】:

我遇到很多人在寻找管理 EBS 快照的工具。我在互联网上找到了几个工具,但它们只是脚本和不完整的解决方案。最后我决定创建一个更灵活、更集中、更易于管理的程序。

这个想法是有一个集中的程序来管理所有 EBS 快照(本地的实例或远程)

我创建了一个小的 Perl 程序, https://github.com/sciclon/EBS_Snapshots

一些特点: * 程序以守护模式或脚本模式(crontab)运行

您也可以只选择本地附加卷或远程卷

您可以定义日志文件

您可以为每个卷定义快照数量

您可以为每个卷定义其中的频率

当达到删除最旧快照的限制时,频率和数量将像“循环”一样工作。

您可以一步调整数量,我的意思是如果您有 6 个快照,并且您在 3 中修改数量,该过程将自动重新调整。

您可以定义“prescript”执行,您可以在执行快照之前添加要执行的代码,例如您想尝试卸载卷或停止某些服务,或者检查实例负载. 父进程会等待退出码,“0”表示成功,你可以根据退出码定义是否继续。

您可以定义“后记”执行以在拍摄快照后执行任何脚本(例如告诉您有关它的电子邮件)

您可以添加“受保护的快照”以跳过您定义的快照,我的意思是它们将处于“只读”状态并且永远不会被删除。

当脚本以守护程序模式运行时,您可以“即时”重新配置脚本,脚本接受信号和 IPC。

它有一个“本地缓存”以避免多次请求 API。 您可以在配置文件中添加或修改任何配置并重新加载而不终止进程。

【讨论】:

【参考方案4】:

这是我在 Ruby 中编写的一个函数,用于对所有区域的所有实例上的所有卷进行快照。

require 'aws-sdk'

def snapshot_all_attached_volumes(region)
  # For every instance in this region
  AWS::EC2.new(:region => region).instances.each do |instance|
    # get all the attached volumes
    instance.attachments.each do |mountpoint, attachment|
      # and create snapshots
      attachment.volume.create_snapshot(description = "Automated snapshot #HOSTNAME:#$0")
    end
  end
end

regions = AWS::EC2.regions.map(&:name)
regions.each do |region| 
  begin
    snapshot_all_attached_volumes(region)
    # delete_all_old_snapshots(region) 
  rescue
    puts "#$!"
  end 
end

【讨论】:

【参考方案5】:

我不了解你,但我更喜欢制作 AMI 而不是快照。这个脚本来自亚马逊员工克雷格的一个想法。他们正在开发一个名为 Arche 的快照脚本。此脚本很简单 - 您在 EC2 实例中标记一个标签,并且标签 Ec2 是 AMIed。我在我的环境中对其进行了测试。您也可以更改此脚本中的命令来备份快照。

在运行之前,请使用 cert 和 pk 密钥配置 linux 环境变量。

#!/bin/bash
echo "AMI Backup is starting..."
echo "taking AMI Backup..."

day_of_year=$(date +%j)
week_of_year=$(date +%U)
week_of_year=$( printf "%.0f" $week_of_year )
year=$(date +%Y)

for INST in $(ec2-describe-instances --region=sa-east-1 --filter "tag:Backup=On" | awk '/^INSTANCE/ print $2')
do
        start_time=$(date +%R)
        ami=$(ec2-create-image $INST --name $INST$week_of_year --no-reboot | awk 'print $2')
        ec2-create-tags $ami --tag Day_Year=$day_of_year > /dev/null
        ec2-create-tags $ami --tag Week_Year=$week_of_year > /dev/null
        ec2-create-tags $ami --tag Src_Instance=$INST > /dev/null
        ec2-create-tags $ami --tag Start_Time=$start_time > /dev/null
        end_time=$(date +%R)
        ec2-create-tags $ami --tag End_Time=$end_time > /dev/null
        echo "Created AMI $ami for volume $INST"
done

year=$(date +%Y)
expire_day=`expr $day_of_year  -  2`
expire_week=`expr $week_of_year  -  2`


echo "identifying AMI to be deleted"
for delete in $(ec2-describe-images --filter "tag:Week_Year=$expire_week" | awk ' print $2;exit;')
do
        ec2dereg $delete
        echo "deleted $delete"
done

【讨论】:

【参考方案6】:

我认为现在最好的方法是使用 AWS Lambda 为您的 EC2 实例拍摄快照。您可以从此链接找到更多详细信息

http://www.iwss.co.uk/ec2-instance-snapshot-through-aws-lambda-function-using-phyton-2-7/

【讨论】:

【参考方案7】:

创建按计划拍摄快照的规则。您可以使用速率表达式或 cron 表达式来指定计划。对于more information

更多信息 创建规则

    在https://console.aws.amazon.com/cloudwatch/ 打开 CloudWatch 控制台。

    在导航窗格中,选择事件、创建规则。

对于事件源,请执行以下操作:

a. Choose Schedule.

b. Choose Fixed rate of and specify the schedule interval (for example, 5 minutes). Alternatively, choose Cron expression and specify a cron expression (for example, every 15 minutes Monday through Friday, starting at the current time).

    对于 Targets,选择 Add target,然后选择 EC2 Create Snapshot API call。

    对于卷 ID,键入目标 Amazon EBS 卷的卷 ID。

    对于 AWS 权限,选择创建新角色的选项。新角色授予内置目标权限以代表您访问资源。

选择配置详细信息。

对于规则定义,键入规则的名称和描述。

选择创建规则

【讨论】:

以上是关于如何自动对 Amazon EC2 实例的卷进行快照?的主要内容,如果未能解决你的问题,请参考以下文章

启动 Amazon EC2 实例时如何自动启动 Web 服务?

自动关闭和启动 Amazon EC2 实例

如何在 Amazon Auto-scaling 组中的多个 ec2 实例上部署和更新应用程序?

给aws ec2 所有ebs做自动快照

创建新实例时如何保护来自 Amazon EC2 实例的数据?

Amazon AMI 和 EBS 快照有啥区别?