delphij's Chaos

选择chaos这个词是因为~~实在很难找到一个更合适的词来形容这儿了……

01 Jan 2011

ZFS的自动化备份

主任说:冗余不做,日子甭过;备份不做,十恶不赦。

以前一直是每天手动给自己的新服务器做备份,最近找时间写了一套脚本来自动完成这个事情。

脚本没啥复杂的,大体的思路是这样:

  1. 在源上根据日期命名生成一份新的快照;
  2. 将上次备份机器收到的快照和新快照之间的差异 pipe 给 xz,然后再把结果pipe给ssh(使用key验证),传到备份机上;
  3. 备份机解压缩、zfs receive之后,如果成功,ssh到源系统上记录自己拿到的那个新的快照日期;

由于是通过 Internet (从AS6939送到AS33651)传递快照,所以使用了压缩。用ssh来完成传输的考虑主要是因为它能够做到互相验证身份。

目前这个设计过于"精密"—-双方互相配合的地方比较多,未来版本打算改掉。

目前版本的实现中的一些要点

首先在两边用ssh-keygen生成用于令root远程登录的密钥对,并传到对端。

在插入到授权文件,通常是 /root/.ssh/authorized_key 时,在公钥前缀上:command=“exec /root/bin/receivefs”,其中receivefs是接收端的脚本。【注意:这样做仍然不能完全确保安全性,但能限制攻击者获得root key并使用这个跳板毁掉远程备份的能力,receivefs脚本可以检查命令的格式,只给攻击者一次尝试机会,等等】

send方面,保存一个配置文件到 /root/config/文件系统名字,其内容为远端已有的快照。

send方面的发送命令大致如:zfs send -R -i ${ZFS_TO_SEND}@${PREVIOUS_SNAPDATE} ${ZFS_TO_SEND}@${TODAY} | cpuset -c -l ${RANDOM_CPUID} nice -4 xz | ssh -4 ${TARGET_HOST} /root/bin/receivefs ${TODAY} ${PARENT_FILESYSTEM}

其中cpuset命令将xz进程(CPU密集、单线程计算任务)绑在一颗CPU上以改善性能。

测试成功之后,将其配入crontab即可。