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

5
我正在尝试使用脚本自动备份一个卷。
我遵循这个在github上找到的EBS-Snapshot.sh脚本:github
#!/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: 参数volumeId的值(([ec2-describe-volumes]))无效。期望值:'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
7个回答

9

上面的解决方案对我来说并没有完全起作用。在与亚马逊支持团队进行了一小时的交谈后,我现在拥有了这个可行的脚本,它将始终创建当前实例附加的所有卷的快照:

#!/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 中设置了一个定时任务。

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

这对我来说非常有效... :-)

希望对你有帮助, Sebastian


4

好的,

  1. 他运行的第一行(源代码)相当于“/etc/environment”,他只是加载一个文件,其中包含亚马逊所需的环境变量列表。至少我是这么认为的。
  2. 他让这个脚本比它需要的更加复杂了。他不需要运行“ec2-describe-instances”命令并将输出保存到文件中,然后再grep等操作。
  3. 你可以在DESC中放置任何你想要的内容。只需将等号右侧的所有文本替换为所需文本,并确保用引号括起来即可。

我会对这个脚本做两个修改。

  1. Get the InstanceId at runtime in the script. Don't hard code it into the script. This line will work no matter where the script is running.

    MY_INSTANCE_ID=`curl http://169.254.169.254/1.0/meta-data/instance-id`
    
  2. Instead of calling ec2-describe-volumes and saving the output to a temp file etc... Just use a filter on the command and tell it which instance id you want.

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

非常感谢您的解释,我整天都在搜索并自问关于“全局”变量的问题。感谢您对实例ID和卷列表的小改进,卷列表给我带来了一些麻烦。我将修改描述并修复仍然存在的“Client.InvalidParameterValue:参数volumeId的值(([ec2-describe-volumes]))无效。期望:'vol-...'。”错误。 :-) - clement
更改描述时要小心。确保在其周围添加引号以保持谨慎。如果出现“Client.InvalidParameterValue”错误,则可能是因为volume-id为空或您用于描述的文本具有空格,并且正在读取volume-id的一部分描述。 - bwight
我又遇到了那个问题。这是在屏幕上打印的整个过程:正在为卷创建快照:([ec2-describe-volumes]),并带有说明:-03-13-2012 以下是快照信息: Client.InvalidParameterValue: 参数volumeId的值(( [ec2-describe-volumes]))无效。期望值:'vol-...'。进程结束于03-13-2012-08:11:35 - clement
$volume "worth" (([ec2-describe-volumes])) in the "for"... 如何正确获取卷以使快照生效? - clement
你能否更新你的答案并附上你正在尝试运行的脚本?如果你这样做,我可以尝试帮助你。 - bwight
export EC2_URL=https://eu-west-1.ec2.amazonaws.com 解决了我的脚本问题......感谢阅读! - clement

1
我遇到了很多人正在寻找一种管理EBS快照的工具。我在互联网上找到了几个工具,但它们只是脚本和不完整的解决方案。最终,我决定创建一个更灵活、集中化和易于管理的程序。
这个想法是拥有一个集中化的程序来管理所有的EBS快照(本地或远程)。
我创建了一个小型的Perl程序, https://github.com/sciclon/EBS_Snapshots 一些特点: * 程序可以在守护进程模式或脚本模式(crontab)下运行
  • 您可以选择本地附加卷或远程卷

  • 您可以定义日志文件

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

  • 您可以为每个卷定义它们之间的频率

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

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

  • 您可以定义“预处理”执行,您可以添加代码以在执行快照之前执行,例如,您想尝试卸载卷或停止某些服务,或者检查实例负载。

  • 父进程将等待退出代码,“0”表示成功,您可以根据退出代码定义是否继续执行。

  • 您可以定义“后处理”执行以在拍摄快照后执行任何脚本(例如发送电子邮件告诉您)

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

  • 您可以在守护进程模式下“即时”重新配置脚本,脚本接受信号和IPC。

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


0

创建一个定时快照规则。您可以使用速率表达式或 cron 表达式来指定计划。有关更多信息,请参阅以下内容:

更多信息 要创建规则,请执行以下操作:

  1. CloudWatch 控制台中打开 CloudWatch 控制台。

  2. 在导航窗格中,选择“事件”,然后选择“创建规则”。

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

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).
  1. 选择目标,选择添加目标,然后选择 EC2 创建快照 API 调用。

  2. 对于卷 ID,请输入目标 Amazon EBS 卷的卷 ID。

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

选择配置详细信息。

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

选择创建规则。


0

0

我不知道你怎么想,但我更喜欢制作AMI而不是快照。这个脚本来自于亚马逊员工Craig的一个想法。他们正在开发一个名为Arche的快照脚本。这个脚本很简单 - 你在EC2实例中标记一个标签,然后标记的EC2将被制作成AMI。我在我的环境中测试过了。你也可以更改这个脚本中的命令来备份快照。

在运行之前,请使用证书和私钥配置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

0
这是我用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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接