2012年7月31日火曜日

ftp を使ってディスク丸ごとバックアップ

最近、カーネルやOSSソース, ISO イメージの収集蓄積を行うのに、ZFS on Linux を利用しています。 メイン PC のディスクを丸ごとバックアップすることも利用目的の1つです。

しかし、ネット上にいくつも情報があるように、ZFS on Linux + NFS アクセスする場合、どうにも性能が出ないようです。
わたしの環境では、書き込みスループットが 1 MB/s を下回るくらいです。とても実用にはなりません。GigaBit Ether で接続しており、ftp ならば 50MB/s くらいは出る環境なのに、NFS だと全然遅くなってしまうのです。残念。バックアップ対象の PC のディスクは 180GB であり、圧縮して 100GB になったとしても、1 MB/s ですから、100000 秒もかかる計算です。どうにかできないものか・・・

ディスク丸ごとバックアップするというと、次のように dd で NFS 領域へ書き込みというのが、わたしのお決まりのパターンなのですが。。。
# dd if=/dev/sda bs=1M | lzop -c > /mnt_nfs/sda.dd.lzo

ftp ならスループット 50MB/s 出るのだし、なんとかして ftp に dd + lzop の出力を渡して転送できないの?・・・とサーチしてみると、なんと超簡単ではありませんか!無知でした。
ftp> bin
200 Type set to I
ftp> put |"dd if=/dev/sda1 bs=1M | lzop -c" sda1.dd.lzo
local: |dd if=/dev/sda1 bs=1M | lzop -c remote: sda1.dd.lzo
227 Entering Passive Mode (192,168,xxx,xxx,128,22).
150 Opening BINARY mode data connection for sda1.dd.lzo
196+1 records in
196+1 records out
205599744 bytes (206 MB) copied, 11.0407 seconds, 18.6 MB/s
226 Transfer complete.
90549924 bytes sent in 11 seconds (8e+03 Kbytes/s)
なんと、Linux (に限らずかな?) の ftp コマンドでは、put の第一引数の先頭に | を指定すれば、パイプラインからデータを読み取ってくれるのですね。作った人に感謝。

2012-08-01追記
上のコンソールは、VMware 上での実験結果ですが、実際 180GB のディスクバックアップを実行してみました。
[root@livedvd Desktop]# ftp mypc
Connected to mypc (10.xx.yyy.zzz).
220 (vsFTPd 2.2.2)
Name (mypc:centoslive): user01
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> bin
200 Switching to Binary mode.
ftp> put |"dd if=/dev/sda bs=1M | lzop -c" user01.sda.backup-2012-08-01.lzo
local: |dd if=/dev/sda bs=1M | lzop -c remote: user01.sda.backup-2012-08-01.lzo
227 Entering Passive Mode (10,xx,yyy,zzz,uuu,vvv).
150 Ok to send data.
171705+1 records in
171705+1 records out
180045766656 bytes (180 GB) copied, 3891.19 s, 46.3 MB/s
226 Transfer complete.
127003147717 bytes sent in 3.89e+03 secs (32638.60 Kbytes/sec)
対象の PC は、普段は Windows XP が動いているマシンなのですが、CentOS 6.3 LiveDVD を利用してバックアップを行いました。Live 状態では、ftp と lzop が未導入なので、yum でインストールする必要がありました。
LiveDVD は初めて使いましたが、こういったケースでは便利なものですね。

結果として、圧縮後の転送レートは 32MB/s で、約1時間でバックアップが完了しました。
これは、わたしとしては十分に満足できる結果です。

2012-08-03追記
1時間でバックアップできるなら十分かと思いましたが、多少工夫の余地がありましたので、追試を行いました。
まず、圧縮率が低い (180G:127G) のは、ファイルシステム (NTFS) の空き領域に過去に書き込んだデータの痕跡があるためと考えられるので、空き領域にオールゼロデータを書き込んでからバックアップを実行すれば、もっと時間短縮できそうでしたので、次のような Ruby スクリプトを使って、ゼロ書き込みを行いました。Linux なら dd if=/dev/zero of=zerofile とすればいいわけですが、Windows XP なので、一筆。
#!/usr/bin/env ruby
#
# Name: zerofill.rb
#

f = open("zerofile", "wb")

z = [0].pack("N")

@z4 = []

for i in 0...1024
        @z4.push(z)
end

z4096 = @z4.join('')

begin
        while true
                f.write(z4096)
        end
end
なお、Windows XP 上の Ruby スクリプト実行には、Rumix を利用しています。

加えて、前回の実験の際に top で挙動を見ていたら、dd でディスクデータ読み出しを行うと、buffers の値が搭載物理メモリサイズの限界まで上昇し、メモリ回収のため kswapd カーネルスレッドが頻繁に動いていました。
でも、この場合は無駄な動きと思えますので、dd に iflag=direct オプションをつけて実行してみました。結果は次の通り。
ftp> put |"dd if=/dev/sda iflag=direct bs=1M | lzop -1 -c" user01.sda.backup-2012-08-02.lzo
local: |dd if=/dev/sda iflag=direct bs=1M | lzop -1 -c remote: user01.sda.backup-2012-08-02.lzo
227 Entering Passive Mode (10,xx,yyy,zzz,uuu,vvv).
150 Ok to send data.
171705+1 records in
171705+1 records out
180045766656 bytes (180 GB) copied, 2297.55 s, 78.4 MB/s
226 Transfer complete.
40910990817 bytes sent in 2.3e+03 secs (17806.37 Kbytes/sec)
期待どおり、約38分で完了しましたし、バックアップファイルのサイズもコンパクトになりました。

2012年7月1日日曜日

2012年7月1日の うるう秒 調整時の ntpd の挙動観測データ

日本時間の 2012年7月1日午前9時 うるう秒 調整が実施されましたが、ntpd の補正がどのように振舞うのか、ntpq -np の出力を観測してみました。
CentOS 5 x86_64 + ntp-4.2.2p1-9.el5_3.2 (slew モード -x オプション) です。
                         remote           refid      st t when poll reach   delay   offset  jitter
                    ==============================================================================
2012-07-01 04:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  613 1024  377   12.831   -0.952  21.164
2012-07-01 04:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  363 1024  377   12.187   -1.422   0.422
2012-07-01 05:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  113 1024  377   11.911   -1.562   0.984
2012-07-01 05:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  887 1024  377   11.911   -1.562   0.485
2012-07-01 06:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  636 1024  377   13.371   -1.439   3.338
2012-07-01 06:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  389 1024  377   13.422   -1.389   2.102
2012-07-01 07:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  139 1024  377   10.875   -3.526   0.334
2012-07-01 07:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  916 1024  377   10.537   -4.184   0.992
2012-07-01 08:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  667 1024  377   11.885   -3.829   0.914
2012-07-01 08:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  419 1024  377   12.479   -2.801   0.037
2012-07-01 09:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  168 1024  377   11.131   -3.257  11.100
2012-07-01 09:32:18  219.xxx.yy.zz   192.168.u.vvv    2 u  942 1024  377   14.296  -1001.0 986.659
2012-07-01 10:02:18 +219.xxx.yy.zz   192.168.u.vvv    2 u  691 1024  377   11.954  -900.19 118.193
2012-07-01 10:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  443 1024  377   11.681  -795.11 100.385
2012-07-01 11:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  193 1024  377   16.832  -519.76  96.828
2012-07-01 11:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  969 1024  377   16.832  -519.76  83.788
2012-07-01 12:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  721 1024  377   12.516  -373.72  66.502
2012-07-01 12:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  474 1024  377   17.056  -246.34  51.731
2012-07-01 13:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  225 1024  377   15.727  -97.721  45.772
2012-07-01 13:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u 1000 1024  377   15.727  -97.721  30.503
2012-07-01 14:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  748 1024  377   12.229  -23.726  31.822
2012-07-01 14:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  501 1024  377   14.533   60.172   1.022
2012-07-01 15:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  251 1024  377   14.231   84.031  18.929
2012-07-01 15:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u    2 1024  377   13.800  124.631  17.261
2012-07-01 16:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  776 1024  377   13.407  156.855  14.962
2012-07-01 16:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  529 1024  377   10.603  166.262   7.274
2012-07-01 17:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  277 1024  377   12.336  185.132   9.301
2012-07-01 17:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u   28 1024  377   13.053  202.397   0.055
2012-07-01 18:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  805 1024  377   13.053  202.397  28.663
2012-07-01 18:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  555 1024  377   13.432  209.414   2.174
2012-07-01 19:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  308 1024  377   14.631  212.225   4.011
2012-07-01 19:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u   56 1024  377   13.349  214.017   0.057
2012-07-01 20:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  832 1024  377   14.411  213.960   1.213
2012-07-01 20:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  583 1024  377   13.615  203.817   6.336
2012-07-01 21:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  334 1024  377   17.122  197.009   2.029
2012-07-01 21:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u   88 1024  377   18.445  198.370  18.541
2012-07-01 22:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  862 1024  377   16.281  194.083  14.255
2012-07-01 22:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  613 1024  377   13.269  187.763  14.045
2012-07-01 23:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  365 1024  377   14.249  180.813   2.089
このデータを見ると、ずれが収まるまでには思いのほか時間がかかるようで、うるう秒調整が実施されてから14時間後の現在でも、上位 NTP サーバと180ミリ秒ほど開きがあります。
offset の値のプラス/マイナスについて、明確に記憶していませんでしたが、上記データから、その NTP サーバが提示する時刻が、サーバのシステム時刻より前である場合、マイナスということですね。
なので、今 +180 ミリってことは、上位 NTP サーバから 180 ミリ秒遅れているわけか。
この続きのデータは、また明日見てみます。

2012-07-02追記
昨晩の続きのデータは、次のようになってました。
                         remote           refid      st t when poll reach   delay   offset  jitter
                    ==============================================================================
2012-07-01 23:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  113 1024  377   16.669  175.530  42.274
2012-07-02 00:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  890 1024  377   27.000  167.411  50.393
2012-07-02 00:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  640 1024  377   10.899  164.112   2.428
2012-07-02 01:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  392 1024  377   17.415  154.429  12.125
2012-07-02 01:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  143 1024  377   13.487  144.749   3.697
2012-07-02 02:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  917 1024  377   12.823  135.426   5.625
2012-07-02 02:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  668 1024  377   12.132  131.629   5.259
2012-07-02 03:02:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  420 1024  377   11.726  120.271   3.557
2012-07-02 03:32:18 *219.xxx.yy.zz   192.168.u.vvv    2 u  170 1024  377   11.441  115.966   3.173
2012-07-02 04:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  944 1024  377   11.231  107.834   4.959
2012-07-02 04:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  184  512  377   13.227   90.511   6.811
2012-07-02 05:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  448  512  377   11.007   85.097   6.125
2012-07-02 05:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  199  512  377   10.028   65.927   4.114
2012-07-02 06:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  463  512  377   11.529   57.629   5.778
2012-07-02 06:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  726 1024  377   11.231   50.067   3.147
2012-07-02 07:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  479 1024  377   12.781   49.581   0.441
2012-07-02 07:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  227 1024  377   12.351   47.561   1.351
2012-07-02 08:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u 1002 1024  377   11.107   46.045   1.515
2012-07-02 08:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  751 1024  377   11.073   44.120  15.058
2012-07-02 09:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  505 1024  377   12.946   41.379   1.681
2012-07-02 09:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  256 1024  377   11.038   37.101   6.429
2012-07-02 10:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u    5 1024  377   12.444   37.810   0.185
2012-07-02 10:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  267  512  377   14.939   36.484  25.669
2012-07-02 11:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   12  128  377   10.509   21.750   6.330
2012-07-02 11:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   11  128  377   10.696   10.668   3.874
2012-07-02 12:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   15  256  377   13.222    5.393   5.583
2012-07-02 12:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  275  512  377   11.597    2.826   2.155
2012-07-02 13:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   24  512  377   11.602    4.860   0.627
2012-07-02 13:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  285 1024  377   12.522    4.768   3.272
2012-07-02 14:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   34 1024  377   12.450    6.383   1.396
2012-07-02 14:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  809 1024  377   12.383    7.734   0.046
2012-07-02 15:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  561 1024  377   13.710    6.254   2.814
2012-07-02 15:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  312 1024  377   13.091    9.562   0.215
2012-07-02 16:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   62 1024  377   12.187    8.944   1.301
2012-07-02 16:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u  838 1024  377   12.651   10.245   3.777
2012-07-02 17:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   80  512  377   11.899   10.865   0.806
2012-07-02 17:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   82  256  377   11.432    9.104   1.885
2012-07-02 18:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   87  128  377   10.328    6.771   0.873
2012-07-02 18:32:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   89  128  377   11.186    4.603   0.883
2012-07-02 19:02:16 *219.xxx.yy.zz   192.168.u.vvv    2 u   94  256  377   11.876    4.625   1.519
まだ、細かい波があるやうな感じですが、10 ミリ秒未満となった 12:00 あたりが収束だとすると、27時間要したことになります。
この結果をふまえると、step モードで正しく推移(時刻の逆行が1秒発生する)させたい気分になりますが、1秒戻りがどんな作用を及ぼすか、事前に完璧に調べあげることなど不可能であり、予期しないトラブルを避けるため、商用で使っているようなサーバでは、やはり slew モード (-x オプション) にしておいたほうが無難なのではないでしょうかね。くわばら、くわばら。



2015-02-01追記
前回の実施から2年半経過した今年1月はじめ、次回の うるう秒(閏秒)が 2015年7月1日(水) AM 9:00:00(日本時間)に実施されることが発表されました。
記憶されている方も多いものと思いますが、上記の記事を書いたまさしくその頃に、Linux カーネル内の うるう秒対応処理に新たな不具合が発見され、世界中の多数の Linux サーバでトラブルが発生しました。
知らずに、またしてもその罠にハマるのも残念ですので、微力ですが、その不具合について、情報追加しておきたいと思います。

まず、レッドハット社の公開情報は、次のとおりです。

https://bugzilla.redhat.com/show_bug.cgi?id=836803
https://rhn.redhat.com/errata/RHSA-2013-0496.html

読んでもらうとわかりますが、RHEL6/CentOS6 のカーネルに内在していた不具合であり、2.6.32-358.el6 で修正されています。ですので、もしも今現在も、古いカーネルを利用し続けているなら、単純には前記したバージョンより新しいカーネルにアップデートすれば良いことになります。

とは言うものの、世間には様々な事情により、カーネルアップデートが実施できない(許可してもらえない)ということも、ままあるものと思います。その場合はどうしたら良いのか?

まず、うるう秒の実施指示(Leap Indicator)は、NTP プロトコルによってもたらされる(通知される)わけですから、NTP クライアント(ntpd など)を動かしていないなら、うるう秒を知る由もないということが言えます。
勿論のこと、大部分のサーバでは ntpd を動かしていることでしょう。ですから、選択肢の1つとしては、うるう秒実施の前後だけ、一時的に ntpd を止めておくという運用方法が考えられます。ここで注意しなければならないのが、うるう秒の実施を通知する Leap Indicator のフラグは、うるう秒実施の 24 時間前からオンになるという点です。ntpd は、受信した Leap Indicator を Linux カーネルに伝達し、カーネルはうるう秒の実施準備を行ってしまいます。カーネルまで Leap Indicator が伝達されてしまうと、キャンセルするには再起動するしかなくなります。
したがって、もし ntpd を一時的に止める運用を行うのであれば、6月30日 AM 9:00(日本時間)より前に停止する必要があります。実際には、余裕を見て、例えば AM 8:00 に止めるなどというスケジュールになるものと思います。
上位 NTP サーバから通知される Leap Indicator の値は、次のコマンドで確認できます。
[root@hoge ~]# ntpq -c readvar
...
processor="x86_64", system="Linux/2.6.32-220.el6", leap=00,
...
leap=00 は通常状態であり、leap=01 だったらば、うるう秒挿入指示を受信済みであることを示します。
さて、当然ですが ntpd を止めたら時刻が少しは狂う(ずれる)ことになります。どれだけずれてしまうかは、マシン毎に個体差があるはずですが、まる1日 ntpd を止める程度なら、プラスマイナス数秒程度ではないかと思います。#これは、後日実験してみたいと思います。

プラスマイナス数秒の時刻ずれも許容できない場合はどうしたら良いのか?

ntpd を動かしたまま、Linux カーネルによる うるう秒調整動作を行わないようにするには、ntpd が、カーネルに Leap Indicator を伝達しないようにできれば良いです。そのパラメータは次のとおりです。/etc/ntp.conf の末尾に指定します。
...
server xxx.yyy.zzz.uuu  iburst
...
disable kernel
この設定を施してから、service ntpd restart を実行すればよいです。本当に disable になったかどうかは、次のコマンドで確認できます。
[root@hoge ~]# ntpdc -c sysinfo
...
system flags:         auth ntp kernel stats      ※正しく設定できれば、kernel が消えます
...
もっとも、slew モード(ntpd -xオプション付き)で動作している場合には、disable kernel がデフォルトになっているはずなので、設定を変更する前に、現在の動作状態を ntpdc コマンドで確認するとよいです。バージョンの古い ntpd は、slew モードでも enable kernel がデフォルトだったものがありますので、やはり、ntpdc コマンドで確認しておいたほうがよいと思います。
disable kernel に対応する処理部分は、次の箇所です。ntp-4.2.6p5-2.el6 より抜粋です。
...
    502         if (pll_control && kern_enable) {
...
    557                         if (sys_leap == LEAP_ADDSECOND)
    558                                 ntv.status |= STA_INS;
    559                         else if (sys_leap == LEAP_DELSECOND)
    560                                 ntv.status |= STA_DEL;
    561                 }
    562 
    563                 /*
    564                  * Pass the stuff to the kernel. If it squeals, turn off
    565                  * the pps. In any case, fetch the kernel offset,
    566                  * frequency and jitter.
    567                  */
    568                 if (ntp_adjtime(&ntv) == TIME_ERROR) {
    569                         if (!(ntv.status & STA_PPSSIGNAL))
    570                                 report_event(EVNT_KERN, NULL,
    571                                     "PPS no signal");
    572                 }
...
"ntpd/ntp_loopfilter.c"
disable kernel を設定すると、kern_enable の値がゼロになり、うるう秒の実施をカーネルに伝達しなくなります。
また、slew モードなら disable kernel になるという処理は、次の部分です。
...
    163         if (HAVE_OPT( SLEW )) {
    164                 clock_max = 600;
    165                 kern_enable = 0;
    166         }
...
"ntpd/cmd_args.c"

2016-12-11追記
次回の うるう秒挿入(日本時間2017年1月1日8時59分59秒)が迫ってますが、RHEL7 のカーネル不具合情報と修正版カーネルが公開されたので、追記しておきます。

http://rhn.redhat.com/errata/RHBA-2016-2862.html
https://access.redhat.com/solutions/2766351

カーネル 3.10.0-514.2.2.el7 で修正されたようですが、すぐにアップデートできないなら、ntpd の slew モードを使っておけばよいです。または、ntpd を一時的に止めておく方法も可能。ちなみに、今回のRHEL7のカーネル不具合(発症するとCPU100%)は、発生確率がけっこう低い (500回試して1回程度と記載されてます) ようです。

■関連記事
ntpd を1日止めた場合のズレはどの程度か?
うるう秒(閏秒)の際にcronが二重に実行されるかも?という都市伝説(?)について
2015年7月1日の うるう秒 調整時の ntpd の挙動観測データ
2017年1月1日の うるう秒 調整時の ntpd の挙動観測データ (記載予定)
人気ブログランキングへ にほんブログ村 IT技術ブログへ