Подстрахуй братуху, подстрахуй…
В ZFS 0.8 появилась возможность отправлять инкрементные снимки зашифрованных данных не расшифровывая. То есть имея зашифрованный массив можно организовать его зеркальную копию на удалённой машине не доверяя владельцу удалённого помещения. Ключ и расшифрованные данные не покидают доверенное помещение.
Никто из моих клиентов (микроконтор) не имеет более одного серверного помещения, если туда придёт к примеру пожар — всему звезда. Договорившись со своим коллегой по опасному админскому бизнесу вы можете взаимно страховать друг друга не опасаясь, что данными могут воспользоваться.
Любой сервис в виде виртуальной машины ставится на Proxmox, где данные размещены на ZFS, и у вас всегда будет возможность хранить удалённую копию виртуальной машины. Есть шанс, что в один прекрасный день вместо впадания в уныние вы съездите в удалённое помещение, заберёте железяку и запустите все службы в полном здравии. Я уже перевёл почти все свои сервисы на Proxmox около 2 лет назад и ни капли не жалею, всё отлично работает. На ZFS у меня работает терминальный сервер на 30 человек, на который завязаны тонкие клиенты (то есть 30 полноценных рабочих мест). Помимо актуальной копии у вас будут ещё и снапшоты за последние x дней и локально и удалённо.
Да, вы потеряете производительность от самого использования zfs и от шифрования, но для себя я пришёл к выводу, что готов заплатить эту цену за такой функционал.
Ложка дёгтя
В подкате сразу вам ложечка дёгтя. Да ZFS работает медленее. Существенно. Но использовать её как обычную фс нельзя. Она должна работать в массиве дисков, где увеличение количества дисков только приветствуется, диски желательно должны быть SAS, контроллер должен работать в режиме HBA (а не raid0 в качестве одиночных дисков), должна быть ОЗУ ECC и её должно быть много, обязательно должен быть один SSD (лучше PCI-E) в качестве кэша на чтение второго уровня (небольшой, гигов от 64) и один SSD для ZIL можно совсем небольшой, но желательно MLC.
Касательно SSD я положил на эти рекомендации и купил 2 PCI-E SSD по 128 и поделил каждый на 16 гигов и остальную часть. Два 16 гиговых раздела запустил в ZIL как mirror и а оставшиеся части запустил под кэш второго уровня как stripe. На растерзание zfs отдал 16 гигов оперы. (Один слот на купленной с ebay мамке оказался нерабочим, если бы работал — отдал бы 32)
zfskeeper.sh
От скрипта мне нужны были автоматические уведомления о неполадках, контроль количества снапов на обоих концах и контроль скорости. Из попавших мне в руки аналогов удовлетворивших меня скриптов не нашлось. Ниже я приведу часть скриптов, с которыми я ознакомился перед тем как делать этот. Для получения уведомлений по электронной почте замените в функции send_error_to_mail () мои данные на свои
zfskeeper.sh help покажет вам примеры использования
zfskeeper.sh prepare подскажет вам порядок подготовительных действий (рекомендуемых)
zfskeeper.sh bank/encrypted/subvol-100-disk-0 10 сделает текущий снимок и оставит 10 последних снимков
zfskeeper.sh bank/encrypted/subvol-100-disk-0 10 Remotehost 22 10m replicator bank/rtl/subvol-100-disk-0 20 Отправит незашифрованные данные на remotehost:22 под пользователем replicator со скоростью до 10MB/s оставит 10 снимков на источнике и 20 на удалённом хосте
zfskeeper.sh bank/encrypted/subvol-100-disk-0 10 Remotehost 22 10m replicator bank/rtl/subvol-100-disk-0 20 -w тоже самое, но данные будут зашифрованы
#!/bin/bash zpool=$1 lsnaps=$2 ip=$3 port=$4 speedl=$5 remoteuser=$6 backpool=$7 rsnaps=$8 sendargs=$9 ZFSLOGDIR=~/zfskeeplogs if [ ! -d "$ZFSLOGDIR" ]; then mkdir -p $ZFSLOGDIR fi NAMESNAP=`date "+%Y_%m_%d_%T"|sed s/:/_/g` logfile=$ZFSLOGDIR/$NAMESNAP.log write_to_log () { echo `date +"%T"`" $1" >> $logfile } log_last_command () { if [ $? -ne 0 ]; then write_to_log "$1 FAILED." if [ $2 = true ]; then write_to_log "Script execution stops" send_error_to_mail "$1" "$?" "$*" exit 1 fi else write_to_log "$1 COMPLETED." fi } send_error_to_mail () { Subject=`hostname`" ZFS backup $zpool missing" swaks --header "Subject: $Subject" --to admin@mydomain.ru --from "alertbot@mydomain.ru" -a LOGIN -au alertbot@mydomain.ru -ap МailPass --server mail.mydomain.ru -tls --body \ "$Subject command: zfskeeper.sh $3 $1 $2" \ --attach $logfile # --attach-type "$(get_mimetype $logfile)" --attach $logfile } case "$#" in 1) case "$1" in prepare) echo " Sender mashine: apt install swaks mbuffer useradd -s /bin/bash replicator mkdir -p /home/replicator chown replicator:replicator /home/replicator zfs allow -u replicator send,snapshot,destroy,mount bank/encrypted su replicator ssh-keygen Receiver machine: ln -s /usr/sbin/zfs /usr/local/bin/zfs useradd -s /bin/bash replicator mkdir -p /home/replicator chown replicator:replicator /home/replicator passwd replicator Sender mashine: ssh-copy-id -i .ssh/id_rsa.pub Remotehost zfs allow -u replicator compression,create,receive,destroy,mount bank/companyname " ;; *) echo " Usage: To show the prepare instrutions: zfskeeper.sh prepare localkeeping: keep last 10 snapshots of bank/encrypted/subvol-100-disk-0 zfskeeper.sh bank/encrypted/subvol-100-disk-0 10 remotekeeping: keep last 10 snapshots bank/encrypted/subvol-100-disk-0 and send it by ssh to Remotehost:22 bank/rtl/subvol-100-disk-0 and keep last 20 copies by replicator user and limit transferspeed 10Mb/s zfskeeper.sh bank/encrypted/subvol-100-disk-0 10 Remotehost 22 10m replicator bank/rtl/subvol-100-disk-0 20 If you need to send encrypted data, then you need add -w to the end of the line zfskeeper bank/encrypted/subvol-100-disk-0 10 Remotehost 22 10m replicator bank/rtl/subvol-100-disk-0 20 -w " ;; esac exit 0 ;; 2) echo `date +"%T"`" Local keeping of $NAMESNAP being started" > $logfile ;; 8|9) echo `date +"%T"`" Remote keeping of $NAMESNAP being started" > $logfile ;; *) echo "illegal number of parameters" >&2 exit 1 ;; esac ####################################### Local part ####################################################### # Remove waste local snaps numsnap=`zfs list -H -o name -t snapshot -s creation|grep "${zpool}@"|wc|awk '{ print $1 }'` let MAXSNAP=numsnap-lsnaps+1 >/dev/null if [ $MAXSNAP -gt 0 ] ; then for d in `zfs list -H -o name -t snapshot -s creation| grep "${zpool}@"|/usr/bin/head -n"$MAXSNAP"`; do zfs destroy ${d} log_last_command "Remove local snapshot $d" done fi # Create fresh local snap zfs snapshot $zpool@backup_$NAMESNAP log_last_command "Create local $zpool@backup_$NAMESNAP" true ####################################### Local part ####################################################### if [ -z "$backpool" ]; then write_to_log "Local keeping is complete" exit 0 fi ####################################### Remote part ####################################################### # Check remote address if [ -n "$ip" ]; then if ping -c 1 $ip > null ; then sship="ssh -c aes128-ctr -p"$port" -l"$remoteuser" "$ip else echo "URL $ip is not accesiible, abort" send_error_to_mail "Try to ping remote host" "URL $ip is not accesiible, abort" "$*" exit 1 fi else # Remote backup is unnecessary exit 0 fi # Remove waste local snaps numsnap=`$sship zfs list -H -o name -t snapshot -s creation|grep "${backpool}@"|wc|awk '{ print $1 }'` let MAXSNAP=numsnap-rsnaps+1 >/dev/null if [ $MAXSNAP -gt 0 ] ; then for d in `$sship zfs list -H -o name -t snapshot -s creation| grep "${backpool}@"|/usr/bin/head -n"$MAXSNAP"`; do $sship zfs destroy ${d} log_last_command "Remove local snapshot $d" done fi # Receive last remote snap MOST_SLAVE_SNAP_NAME=`$sship zfs list -H -o name -t snapshot -s creation|grep "$backpool@backup"|tail -n1|awk -F "@" '{print $2}'` # If localbackup has same snap then send incremental copy. If has't then send full if [ -n "`zfs list -H -o name -t snapshot -s creation|grep -w "$zpool@$MOST_SLAVE_SNAP_NAME"`" ]; then #zfs send $sendargs -i $MOST_SLAVE_SNAP_NAME $zpool@backup_$NAMESNAP | pv -L $speedl | $sship zfs receive -vF $backpool@backup_$NAMESNAP &>> $logfile zfs send $sendargs -i $MOST_SLAVE_SNAP_NAME $zpool@backup_$NAMESNAP | mbuffer -q -v 0 -s 128k -m 1G | pv -L $speedl | $sship "mbuffer -q -v 0 -s 128k -m 1G | zfs receive -vF $backpool@backup_$NAMESNAP" &>> $logfile log_last_command "Sending incremental backup to the remote machine" true else #If backpool exist we remove it. You can rename it if [ -n "`$sship zfs list -H -o name -s creation|grep -w "$backpool"`" ]; then #$sship zfs rename -p $backpool `$sship zfs list -H -o name|grep -w "$backpool"|awk -F "/" '{print $1}'`/old_$NAMESNAP $sship zfs destroy -r $backpool 2>> $logfile log_last_command "Need to destroy remotepool for full sending $backpool" true fi #zfs send $sendargs $zpool@backup_$NAMESNAP | pv -L $speedl | $sship zfs receive -vF $backpool &>> $logfile zfs send $sendargs $zpool@backup_$NAMESNAP | mbuffer -q -v 0 -s 128k -m 1G | pv -L $speedl | $sship "mbuffer -q -v 0 -s 128k -m 1G | zfs receive -vF $backpool" &>> $logfile log_last_command "Sending full backup to the remote machine" true fi ####################################### Remote part ####################################################### write_to_log "Remote keeping is complete" exit 0
zfskeepall.sh
Для того, чтобы держать в тонусе несколько разделов, нужен управляющий скрипт. Его уже каждый может сделать на свой вкус и цвет, в зависимости от конфигурации. Мой тестовый выглядит вот так:
#!/bin/bash scriptpath=/home/replicator/zfskeeper.sh $scriptpath bank/encrypted/subvol-100-disk-0 5 RemoteHost 22 30m replicator bank/rtl/subvol-100-disk-0 5 -w
Существующие решения
zfsbackup.sh — тоже аккуратный, но малофункциональный
P.S. Разгрыз zfs я с третьего раза, каждый раз грыз где-то по месяцу. Мне не удавалось заставить её работать быстро, да и в полной мере не удалось. В целом ситуация изменилась после установки SAS дисков (хотя бы 7200, хотя бы HL).
Всем мир! Спасибо, что дочитали!
ссылка на оригинал статьи https://habr.com/ru/post/491456/
Добавить комментарий