2016年3月24日木曜日

システムバックアップその8

お次は、バックアップ対象の領域のうち、LVMのlvolで構成されている領域に対して、スナップショットを作成する部分だ。
スナップショット、って何か?
簡単に書くと、「その瞬間のコピーイメージ」だ。(実際には、完全なコピーが作られるわけではない)
ある特定の領域に対して、バックアップ中にファイルの更新が入ると、バックアップデータが不整合を起こすことになる。そのため、スナップショット(その瞬間のコピーイメージ)を作成し、スナップショットからバックアップを取得するようにしたい。そのためのスナップショットだ。
まずはスクリプト。
例によって、sudo su - してからね。
# cd
# cd backup/bin
# vi 0040_create_snapshot
中身はこんな感じ
--中身ココから--
#!/bin/sh

BINDIR=`/usr/bin/dirname $0`
BINDIR=`/usr/bin/realpath ${BINDIR}`
ETCDIR=`/usr/bin/realpath ${BINDIR}/../etc`

. ${ETCDIR}/config

# Create Snapshot
for FSCONFIG in ${ETCDIR}/fsconfig/*
do
  USELVM=""
  VOLNAME=""
  SNAPSIZE=""

  . ${FSCONFIG}

  . ${BACKUPPOINT}/current/config/blkid/${VOLNAME}

  if [ x${USELVM} = "xYes" -a x${TYPE} != "xswap" ]
  then
    /bin/sync;/bin/sync;/bin/sync
    /sbin/lvcreate -L ${SNAPSIZE}  \
                   -n ${VOLNAME}.snap \
                   --snapshot ${ROOTVG}/${VOLNAME}
  fi
done

--中身ココまで--
前半は、いつも通りの変数定義。
for ループの内部で、${FSCONFIG} と blkid/${VOLNAME} を取り込んでいる。
${FSCONFIG} は事前に定義しておくファイルで、${VOLNAME}は前回までの 0030_create_config で作成したファイルだ。
そして if文 を使って「LVM領域か?」と「swap領域以外か?」という確認をしている。
LVM領域でかつswap領域じゃなかった場合に、if文が成立して、syncコマンドとlvcreateコマンドが実行される。(まぁぶっちゃけ、swap領域を排除する必要は無いんだが…)
ここの lvcreate コマンドが、LVMスナップショットを作成しているコマンドだ。
lvcreate の前までに使用している変数は以下の2つ。
  • ${USELVM}
  • ${TYPE}
一つ目の${USELVM}は前回までに説明してある。${FSCONFIG}の内部で定義しておく変数だ。
次の${TYPE}は、前回作成するようにした、blkid/${VOLNAME}の中で定義されている。
念のため、確認してみるといい。
# blkid -o export /dev/sda1
# blkid -o export /dev/vg-root/lv-root

TYPE=vfat や TYPE=ext4 という出力結果があるはずだ。
0030_create_config で出力するようにしておいたファイルシステム構成情報を、こちらの 0040_create_snapshot で早速利用している。
で、LVM領域&swap以外、という条件が成立した領域に対して、lvcreate を実行しているわけだが、その文がコレ
    /sbin/lvcreate -L ${SNAPSIZE}  \
                   -n ${VOLNAME}.snap \
                   --snapshot ${ROOTVG}/${VOLNAME}

引数として3つ出ている。
1つ目を飛ばして、2つ目、-n ${VOLNAME}.snap
これは、スナップショットボリューム(lvol)につけるlvol名だ。
既に存在する lvol からスナップショットを生成するので、名前を付けておく必要が有る。
ここではベースとなる(スナップショット元になる)lvolの名前に、.snap を付与した名称にしている。
次の --snapshot ${ROOTVG}/${VOLNAME} は、ベースとなる lvol の指定だ。
つまり、${ROOTVG}/${VOLNAME} で示される lvol から、スナップショット ${VOLNAME}.snap を作成する、というコマンドになる。
戻って1つ目の引数。
-L ${SNAPSIZE} は、スナップショットの差分保持領域サイズだ。
スナップショットの仕組みが分からないと、何言ってるのかサッパリ分からないだろう。
ざっくり書くと、スナップショットを作成してからも、ベースのlvolには書き込みが出来る。その間、スナップショットは「作成直後」の中身を保持している。当然、ベースlvolとスナップショットの中身は差異が生じる。
この差異を持っているのがスナップショットだ。
つまり、ベースlvolの中身を丸っとコピーしているわけではなく、差分だけ保持しておいて、あたかも新旧2面持っているかのように見せかけているわけだ。
この「差分を保持できる領域はどれぐらいの量にしますか?」っていうのを指定するオプションが -L ${SNAPSIZE} だ。
スナップショットを作成してから、スナップショットを削除するまで(今回はバックアップ目的でスナップショットを作成するので、バックアップ完了まで)の間に、どれぐらいの書き込みが発生するのか?というのを予想して指定する必要が有る。
が、はっきり言って正確にサイズを予想するのは無理だ。
だいたい指標としては、「元のlvolのサイズの10~20%」とか言われているが、それだって正確じゃない。
/usr のように、通常運用時はほとんど書き込みが発生しない領域もあれば、/var のように頻繁に書き込み・書き換えが発生する領域もある。
なので、必要となるサイズは「えいやっ!」で決めてしまい、運用していく中で変更していく、という形を取ることになるだろう。
ちなみに、スナップショットサイズは、同VGの空き領域(Free PE)から確保されるため、その分だけ VG に空き領域が必要だ。(今ならまだ40GB以上余っているはずだ)
さて、スナップショットとlvcreateコマンドがなんとなく分かってきたところで、使用している変数を確認してみよう。
使っているのは3つ。
  • ${SNAPSIZE}
  • ${VOLNAME}
  • ${ROOTVG}
だ。
${ROOTVG}は、既に ${ETCDIR}/config の内部で定義している。
また、${VOLNAME} も、${ETCDIR}/fsconfig の中の設定ファイルで定義済みだ。(前回定義しているはず。)
残りは ${SNAPSIZE} だ。
これをドコに定義するか?だけど、先ほども書いたように、領域の特性によって、スナップショットサイズは変わって来る。そのため、領域ごとに作成している設定ファイル(${ETCDIR}/fsconfig の中のファイル)に定義するのがスジというものだろう。
なお、sda1 と sda2 はLVM制御下には無いため、${SNAPSIZE}を定義する必要は無いが、他の設定ファイルを合わせるために、敢えて記述している。
これまでで、${ETCDIR}/fsconfig の下には、3つのファイルが存在しているはずだ。それぞれにファイルに以下の内容を追記しよう。
# vi ../etc/fsconfig/0010_sda1
--追記ココから--
#
# SNAPSIZE:
# If the area of interest was the LVM region, we want to create
# a LVM Snapshot.
# It will specify the capacity of the Snapshot area.
# ex.
#   SNAPSIZE=32M
#   SNAPSIZE=320M
# If you specify a larger size than the capacity of the backup target,
# it will be the same capacity as the size of the backup target.
#
SNAPSIZE=

--追記ココまで--
# vi ../etc/fsconfig/0020_sda2
--追記ココから--
#
# SNAPSIZE:
# If the area of interest was the LVM region, we want to create
# a LVM Snapshot.
# It will specify the capacity of the Snapshot area.
# ex.
#   SNAPSIZE=32M
#   SNAPSIZE=320M
# If you specify a larger size than the capacity of the backup target,
# it will be the same capacity as the size of the backup target.
#
SNAPSIZE=

--追記ココまで--
# vi ../etc/fsconfig/0030_lv-root
--追記ココから--
#
# SNAPSIZE:
# If the area of interest was the LVM region, we want to create
# a LVM Snapshot.
# It will specify the capacity of the Snapshot area.
# ex.
#   SNAPSIZE=32M
#   SNAPSIZE=320M
# If you specify a larger size than the capacity of the backup target,
# it will be the same capacity as the size of the backup target.
#
SNAPSIZE=320M

--追記ココまで--
lv-root はLVM領域でかつswap以外の領域のため、SNAPSIZE を指定しておいた。320MByteにしているが、この数字が多いのか少ないのかははっきり言って不明だ。運用していく中で調整していくしか無い。
さて、ココまで出来たらテスト実行だ。
今まで通り、0010から順番に実行してみよう。
いつも忘れるんだけど、ココでも実行パーミッションを付与しておくのを忘れないように。
# chmod +x 0040_create_snapshot
# ./0010_mount
# ./0020_mkdir
# ./0030_create_config
# ./0040_create_snapshot
0040_create_snapshot を実行した時に、「Logical volume "lv-root.snap" created.」と表示されてたら、スナップショットの作成に成功だ。
ちなみに、スナップショットを作成している状態で、同じ名称のスナップショットを作成しようとするとエラーになる。(このまま、もう一度 0040 を実行したらエラーになるはずだ。)
2度連続して実行しないように注意しよう。(次の実行前には、スナップショットは削除しておこう。)
とりあえず、本当にスナップショットが作成されたか確認。
# lvs
  LV                  VG      Attr       LSize   Pool Origin         Data%  Meta%  Move Log Cpy%Sync Convert
  lv-root             vg-root owi-aos---   7.63g                                
  lv-root.snap        vg-root swi-a-s--- 320.00m      lv-root        0.83       
(一部省略している)

lv-root と lv-root.snap は表示されていて、lv-root.snap の Pool Origin が lv-root になっているはずだ。また、lv-root.snap の Attr の先頭の文字が  s になっていると思う。
これによって、lv-root.snap は、「lv-root から作成されたスナップショット」ということが分かる。
気になるようなら、一度マウントして、中身が lv-root と同じか見てみたらいい。
# mount -o ro /dev/vg-root/lv-root.snap /mnt
# ls / /mnt

どうだろうか。/(lv-root)と同じようなファイルシステムになっているのが確認できただろうか。
後は、/dev/vg-root/lv-root.snap からファイルを一式バックアップすれば、lv-root のバックアップが完了する。
ファイルのバックアップ処理は次回以降に記載することとして、とりあえずテスト・確認のためのマウントを外して、スナップショットは削除しておこう。
合わせて、作成されたcurrentディレクトリの削除と、/media/backup のアンマウントも忘れないように。
# umount /mnt
# lvremove /dev/vg-root/lv-root.snap
(本当に削除していいか?と聞かれるので、名前が間違っていないことを確認して、 y で削除しよう。)
# rm -rf /media/backup/current
# umount /media/backup

これでスナップショットを作成するスクリプトは完成だ。
この次は、ファイル一式をバックアップする処理になる。
ちなみにこの先、
  • スナップショットを削除する処理
  • ファイルシステムメタデータ取得処理(実は不要)
  • バックアップディレクトリ(current)を年月日時分秒にリネーム
  • 古い世代のバックアップの削除
と流れていって、バックアップが完了する。
そして、これらのバックアップ処理を順番に実行していく親スクリプトを用意する予定だ。
リストアの方は、以下の3つ+親スクリプトの計4本を予定している。
  • HDD構成情報の反映(パーティション等作り直し)
  • ファイルシステム作成
  • ディレクトリ、ファイル書き戻し
まだまだ先は長い…。
2016/03/28追記
/media/backup/current ディレクトリの削除を忘れていたので、そのコマンドを追記。
2016/03/30追記
リストアの予定スクリプト、一覧が漏れていたので記入。

0 件のコメント:

コメントを投稿