2014年9月13日土曜日

SoftLayerに冗長化NFSサーバを(その7)

前回予告していた、コマンド1つでシステムバックアップの方法を説明します。

コマンドを発行するとシステムを再起動し、anaconda のキックスタートモードでバックアップを NFS サーバに格納し、再起動します。コマンド発行から再ログインできるまでの時間は、Bare Metal Instance の場合、実測で3分半を切りました。十分満足できる結果となったので、これ以上のチューニングは行いません。普通に再起動する時間よりも短い時間でシステムバックアップができるようになりました。これで気軽にシステムバックアップを取得することができます。リポジトリやキックスタートファイルは NFS サーバに配置する必要があるので無理ですが、それ以外の部分は プロビジョニングスクリプトに仕込んでおきました。

そもそも、システムを停止せずにシステムバックアップが取れれば、バックアップ時間はそれほど気にしなくてもよいのでは、という意見があると思います。例えば、/、/boot パーティションしかない場合、/boot パーティションはカーネルアップデート時を除き読み取り専用として扱うのであれば、残りの / パーティションを LVM で構成し、スナップショットを取得し、スナップショットからバックアップを作成する、という方法もあると思います。LVM ではなくても、スナップショットを取得できるファイルシステムで / パーティションを作成しておく、でもよいです。一貫性のあるバックアップとなっているはずです。クラッシュリカバリに対応したファイルシステムであれば動くはずです。このような状況になっているのであれば、やり方としてはありだと思います。ただし、どのようにリカバリしたらよいのか、という点で悩むことになると思います。
このような方法は、一貫性があり確実にリストアに使えるバックアップをいつも同じやり方で取得する、という観点からはお勧めできません。システムを正常に停止し、停止した状態でシステムバックアップを取得するのでなければ、システムバックアップと呼ぶべきではないくらいに考えています。システムバックアップを再取得しなければならない状況は設定変更やパッチ適用の前後くらい、ということであればなおさらです。
今回はバックアップを tar コマンドで取得していますが、Rescue モードでマウントできないファイルシステムの場合、dd コマンドで取得するように変更すればよいだけなので、応用範囲はかなり広いです。パーティションが増えても、マウントおよび tar コマンド行 (もしくは dd コマンド行) を増やすだけです。確実に一貫性のある状態のバックアップが取得できます。リストアもほぼ同様の方式で行えます。パーティション作成、フォーマット、ブートローダのインストールが増えるくらいです。MACアドレス、ホスト名、IPアドレスが入っているファイルをリストア後に書き換える前提であればテンプレートとしても利用可能です。カーネルやドライバ、ブートローダーに気を付ければ、P2V や V2V にも利用可能です。
Red Hat 社の方が、多様な環境を前にして環境ごとの違いをどう吸収したらよいのか一概に言えないがキックスタートで構築するのが一番確実だと思われます、と言われていたのが今でも印象に残っています。

まず、NFS サーバ上にリポジトリを用意します。リポジトリと言っても、anaconda のイメージファイルを配置するだけです。Active 機で操作します。


sudo mkdir -p /backup/ks
sudo mkdir -p /backup/co6.5/images
sudo wget http://mirrors.service.networklayer.com/centos/6.5/isos/x86_64/CentOS-6.5-x86_64-minimal.iso -O /backup/co6.5/CentOS-6.5-x86_64-minimal.iso
sudo mount -o loop /backup/co6.5/CentOS-6.5-x86_64-minimal.iso /mnt
sudo cp /mnt/images/{install.img,updates.img} /backup/co6.5/images/
sudo umount /mnt
sudo rm /backup/co6.5/CentOS-6.5-x86_64-minimal.iso


バックアップコマンドを用意します。

パラメータとしてバックアップ先の NFS サーバの IP アドレスが必要となります。指定ミスがあるかどうかの判定として、キックスタート中で NFS マウント後に NFSSERVER:/backup/system ディレクトリが存在していることを確認しています。バックアップは、NFSSERVER:/backup/system/ホスト名/年月日時分/ ディレクトリに作成します。バックアップの上書きや削除は行っていません。再起動後、「cat /proc/cmdline」を実行すると「backup=201409072322」ように、先ほどの「年月日時分」がわかるようにしています。こちらが含まれていない場合は、バックアップを完了できていません。含まれている場合は、バックアップを実行完了しています。実行完了したからと言って正しくバックアップが取得できているかどうかは、リストアしてみないと分かりません。バックアップの宿命です。リストアが成功したバックアップは貴重です。リストアが成功した実績のあるバックアップを必ず残すようにしましょう。

使い方は、引数に NFS サーバの IP アドレスを指定するだけです。


cat << 'EOF' | sudo tee /rescue/backup
#!/bin/bash
if [ "$1" = "" ]; then
  echo Usage: $0  nfsserver_ip
  exit 1
fi
if [ -e /proc/xen ]; then
  sed -i -e 's/^\(default=.*\)$/##rescue##\1\ndefault='"$(($(cat /boot/grub/grub.conf | grep -v ^# | tr '\n' ',' | sed -e 's/title/\ntitle/g' | grep ^title | awk '/ rescue / {print NR}')-1))/" -e '/vmlinuz / s%^.*$%\tkernel /vmlinuz lang=en_US keymap=jp106 selinux=0 ksdevice=eth0 ip='"$(ifconfig eth0 | grep inet | awk '{print $2}' | awk -F: '{print $2}') netmask=255.255.255.192 gateway=$(if route -n | grep -q '^10\.0\.0\.0'; then route -n | grep '^10\.0\.0\.0'; else route -n | grep '^0\.0\.0\.0'; fi | awk '{print $2}') dns=$(grep ^nameserver /etc/resolv.conf | head -1 | awk '{print $2}') ks=nfs:$1:/backup/ks/$(uname -n).cfg%" /boot/grub/grub.conf && reboot
else
  kexec -l /boot/vmlinuz --initrd=/boot/initrd.img --command-line="lang=en_US keymap=jp106 selinux=0 ksdevice=eth0 ip=$(ifconfig $(ifconfig bond0 > /dev/null 2>&1 && echo bond0 || echo eth0) | grep inet | awk '{print $2}' | awk -F: '{print $2}') netmask=255.255.255.192 gateway=$(if route -n | grep -q '^10\.0\.0\.0'; then route -n | grep '^10\.0\.0\.0'; else route -n | grep '^0\.0\.0\.0'; fi | awk '{print $2}') dns=$(grep ^nameserver /etc/resolv.conf | head -1 | awk '{print $2}') mtu=9000 ks=nfs:$1:/backup/ks/$(uname -n).cfg" && reboot
fi
EOF
sudo chmod 755 /rescue/backup


バックアップスクリプト本体にあたるキックスタート・ファイルを用意します。
システムバックアップ対象となるサーバ上で実行します。出来上がったファイルを NFS サーバ Active 機の /backup/ks/ にコピーします。パーミッションが 755、オーナーを root に変更します。

※ 2014/09/27 追記
network オプションは指定しなくても動きました。
bootloader オプションは --driveorder オプションなしでも動きました。
part オプションは --recommended オプションだけで動きました。
そうするとパラメータは NFS サーバの IP アドレスのみとなります。
つまり、クライアントごとにバックアップ用のキックスタートファイルを用意する必要がなくなります。
GitHub 上のプロビジョニングスクリプトでは、このファイル作成は自動化されています。


NFSSERVER=10.110.88.62

[ -e /proc/xen ] && DEV=xvda || DEV=sda
cat << EOF > $(uname -n).cfg
install
text
reboot
nfs --server=$NFSSERVER --dir=/backup/co6.5
lang en_US.UTF-8
keyboard jp106
timezone --utc Asia/Tokyo
network --device eth0 --onboot yes --mtu=$(ifconfig bond0 > /dev/null 2>%1 && echo 9000 || echo 1500) --noipv6 --bootproto static --ip=$(ifconfig $(ifconfig bond0 > /dev/null 2>&1 && echo bond0 || echo eth0) | grep inet | awk '{print $2}' | awk -F: '{print $2}') --netmask=255.255.255.192 --gateway=$(if route -n | grep -q '^10\.0\.0\.0'; then route -n | grep '^10\.0\.0\.0'; else route -n | grep '^0\.0\.0\.0'; fi | awk '{print $2}') --nameserver=$(grep ^nameserver /etc/resolv.conf | head -1 | awk '{print $2}')
authconfig --enableshadow --passalgo=sha512
rootpw password
bootloader --location=none --driveorder=$DEV
part /boot --noformat --onpart ${DEV}1
part /     --noformat --onpart ${DEV}2
%packages
@Core
%end
EOF
cat << 'EOF' >> $(uname -n).cfg
%pre
[ -e /proc/xen ] || exec < /dev/tty3 > /dev/tty3 2>&1
[ -e /proc/xen ] || /usr/bin/chvt 3
[ -e /proc/xen ] || set -x
[ -e /proc/xen ] && DEV=xvda || DEV=sda
ifconfig eth1 down
[ -e /proc/xen ] || ifconfig eth3 down
for i in $(cat /proc/cmdline)
do
  echo $i | grep -q = || continue
  echo $i | grep -q -v ^= || continue
  eval $i
  echo $i
done
mkdir /mnt/sysimage
mount /dev/${DEV}2 /mnt/sysimage
mount /dev/${DEV}1 /mnt/sysimage/boot
[ -e /proc/xen ] && sed -i -e '/^default=/d' -e 's/^##rescue##default=/default=/' -e '/vmlinuz / s%^.*$%\tkernel /vmlinuz rescue repo=http://mirrors.service.networklayer.com/centos/6/os/x86_64/ lang=en_US keymap=jp106 selinux=0 sshd=1 nomount ksdevice=eth0 ip='"$(ifconfig eth0 | grep inet | awk '{print $2}' | awk -F: '{print $2}') netmask=255.255.255.192 gateway=$(if route -n | grep -q '^10\.0\.0\.0'; then route -n | grep '^10\.0\.0\.0'; else route -n | grep '^0\.0\.0\.0'; fi | awk '{print $2}') dns=10.0.80.11%" /mnt/sysimage/boot/grub/grub.conf
mkdir /backup
mount -t nfs $(echo $ks | awk -F: '{print $2}'):/backup /backup
if [ ! -d /backup/system ]; then
  umount /backup
  mount -o ro,remount /dev/${DEV}2 /mnt/sysimage
  mount -o ro,remount /dev/${DEV}1 /mnt/sysimage/boot
  reboot
fi
. /mnt/sysimage/etc/sysconfig/network
DATETIME=$(TZ=JST-9 date +%Y%m%d%H%M)
mkdir -p /backup/system/$HOSTNAME/$DATETIME
cd /mnt/sysimage
tar czf /backup/system/$HOSTNAME/$DATETIME/boot.tgz boot > /dev/null 2>&1
umount /mnt/sysimage/boot
tar czf /backup/system/$HOSTNAME/$DATETIME/root.tgz . > /dev/null 2>&1
## other partition ##
mount /dev/${DEV}1 /mnt/sysimage/boot
[ -e /proc/xen ] && sed -i -e "s/backup=[0-9]* /backup=$DATETIME /" /boot/grub/grub.conf
[ -e /proc/xen ] && reboot
umount /backup
mount -t proc /proc /mnt/sysimage/proc
chroot /mnt/sysimage /usr/local/sbin/reboot_quick noreboot backup=$DATETIME
mount -o ro,remount /dev/${DEV}2 /mnt/sysimage
mount -o ro,remount /dev/${DEV}1 /mnt/sysimage/boot
chroot /mnt/sysimage /sbin/kexec -e
[ -e /proc/xen ] || /usr/bin/chvt 1
reboot
%end
%post
%end
EOF


これで、コマンドひとつでシステムバックアップが取れる状態となります。

バックアップ対象となるパーティションが増えた場合は 「## other partition ##」 というコメント部分にマウント処理、バックアップ処理、アンマウント処理を追加します。仮想マシンの場合は、画面出力を増やすと途中で処理が止まるようなので、その点に気を付けてください。
また、仮想マシンの場合は、/boot/grub/grub.conf を書き換えてから再起動し、キックスタート処理で元に戻していますが、元に戻す前にエラーとなってしまうと、通常起動できなくなってしまうという弱点があります。その場合は、SoftLayer の Rescue を立ち上げて、書き戻してください。物理マシンの場合はこのような弱点はありません。


先週末のうちにここまで書いて、この週末に動作確認をしてからアップしようと思っていたのですが、Bare Metal Instance が発注できなくなってしまっていました。時間精算可能な Bare Metal Server が登場した関係で、Bare Metal Instance はどうなるのか気にはなっていたのですが、まさかなくなるとは... orz。
一番安いもので、$0.465/hour なので、検証目的では大幅な値上げです。ワンコインで Oracle RAC も、構築するだけで遊ぶ時間が無くなってしまいます。
Bare Metal Instance の弱点は、HDD が1台しかないこと、RAID になっていないことに尽きます。
その意味で、本番機として利用されることはほとんどなかったのではないか、とは思われます。

急遽、予定を変更して、時間課金 Bare Metal Server の検証を割り込ませることとします。
本稿は、テストがいつもより出来ていない点ご了承ください。

0 件のコメント:

コメントを投稿