カテゴリー別アーカイブ: FreeNAS

zfsのプールを他のサーバに効率よく移設する

zfsのプールを他のサーバに効率よく移設してみた。

現在zfsで構築されているファイルサーバから、新規に作成されたzfsのファイルサーバへzpoolを転送してみた。

 

流れとしては元サーバでsnapshotを取り、その後にsshで転送して受け側で展開するというもの。

zfs snapshot tank/[email protected]`date +%Y%m%d`;

zfs send tank/[email protected]`date +%Y%m%d` | ssh -c arcfour256 [email protected]_to_transfer zfs recv tank/[email protected]`date +%Y%m%d`


気をつけるのはdateを使って転送しているのでスナップショット作成から転送開始までに日をまたぐと失敗する。(スナップショットの作成はだいたい早いので大丈夫なハズ…)

またsshは-cで軽い暗号化方式を選ぶことで転送速度が上がるらしい。

ちなみに今回のテストでは標準のもの(aes128-cbc)だと8.1MB/sでしたが、arcfour256では でした。

 

一瞬でのバックアップを実現するSolaris ZFS (3/4)

http://www.atmarkit.co.jp/ait/articles/0804/08/news138_3.html

大容量ファイルのSCP転送を高速にする方法

http://d.hatena.ne.jp/rx7/20101025/p1

 

NIS, LDAPを用いた複数の環境でログインシェルを変更する

NIS, LDAPを用いた複数の環境でログインシェルを変更したかった。

現在自分の環境ではLDAPを利用している。ログイン情報をLDAPサーバに集約できるので非常に便利。LDAPではログイン時にユーザ名、パスワード(ハッシュ)などの情報を各ホストに提供するのだけれど、その中にはログインシェルも含まれる。

ログインシェルといえばUNIX系でよく使われるcsh, tcsh、Linux系でよく使われるbash、また高機能シェルとして名高いksh, zshなどがある。自分はzshをメインのシェルとしているのだけれど、LDAPのログインシェルの情報をzshに変更するだけでは問題がある。

まず一つ目はフルパス表記での問題だ。
ログインシェルは通常フルパスで表記される。これはシェルの初回立ち上げ時に~/.cshrc, ~/zshrcといった環境ファイルを読み込ませ、その段階でパスがセットされるからだ。つまりログインシェルの情報を取得して起動させる段階ではパスが通っていないことが想定される。そしてこのフルパス表記がOS毎に違ってくる可能性がある、ということが問題の核だ。
このシェルの実体、バイナリの実体が配置される場所は大まかに以下のようになる。Linux系ではrpm, yum, aptなどのパッケージ管理ツールでインストールした場合の/usr/bin/、デフォルトで配置される/bin/、ソースからインストールされた/usr/local/binである。
対してFreeBSDの場合、tcshやcsh, shなどの元々インストールされているバイナリは/bin/sh, /bin/tcshなどに配置されるが、後から手動でインストールされたバイナリは/usr/local/binに配置される。zshやbash(FreeBSDではbashがデフォルトで入ってこない)は/usr/local/binに置かれている訳だ。
この問題に関して言えば、インストール時にバイナリの配置場所を/usr/bin, /bin, /usr/local/binのいずれかに統一してしまう、若しくはシンボリックリンクを統一された場所に配置する、という解決方法が考えられる。でもこれらの作業をそれぞれのホストでいちいち実行するのは億劫だ。

二つ目の問題はデフォルトでインストールされるシェルが少ないことだ。自分の環境では主にFreeBSD、またDebian系(Ubuntu)、RHEL系(CentOS)、さらにはMac OS Xと数種類のOSを利用している。その中でデフォルトでインストールされるシェル、となると実は結構少ない。FreeBSDではcsh若しくはtcshをデフォルトシェルにする事が多い。対してLinuxではbashがデフォルトシェルとなることがおおい。そして残念な事にはFreeBSD/Linuxに於いては(t)csh/bashがお互いにデフォルトでインストールされていない。
ということはbashならbashをLDAPのデフォルトシェルにしてしまって、bashの環境ファイルである.bashrcなどでzshを呼び出す、という事ができない。

以上の点を踏まえながら試行錯誤していった結果、「UNIX/Linuxの両方に入っているシェルを使ってログイン時にzshにしてしまう」という方法にたどり着いた。ちなみにそのUNIX/Linuxの各種OSの最大公約数と言うべきシェルはsh。
shとはThompson shellを意味し、bashの前身となったシェルだ。過去にはバックスペースすら無かった気もするけれど、カーソルキーで入力位置を変更できない、コマンド履歴が使えないというシェルの基本的な機能のみしか持っていない素朴なシェルだ。
(とは言え、過去のbashも同様でデフォルトではコマンド履歴なども使えなかった気がしてbashとshのデフォルト状態での違いがあまり無いような状態だったんだけれど、最近のbashは使いやすいシェルっぽくなってる)
さてLDAPではこのshをデフォルトシェルにし、shが立ち上がった後にzshを呼び出すようにしてみる。

shでログインされた際に呼ばれる環境ファイルは “.profile”ファイルである。”.login”かと思ったんだけれどこれはshだと実行されないしcsh系だった気がする。つまりsh系ではダメということ。
この.profileファイルには直接shに実行して欲しいことを記述する。以下に例を示す。

[ -x /usr/local/bin/zsh ] && exec /usr/local/bin/zsh
[ -x /bin/zsh ] && exec /bin/zsh

shらしい記述で条件式を書き、それぞれのバイナリが存在し実行可能であればexecしてやる。execでシェルを呼び出せばログインシェルが切り替わった動作になるのでCtrl+Dなどでシェルを抜けたときにzshを支えているshも一緒にexitしてくれる。つまりログインシェルがzshになったようにみえてshを意識することが無い。

以上で思っていたようなzshなどのパスが違う環境でログインシェルを統一する、ということが可能になった。

めでたしめでたし。

FreeBSDのNFSでファイルロックをとれるようにする

FreeBSDのNFSでファイルロックをとれるようにする。

OSのバージョンは、サーバ側がFreeBSD 7.3(FreeNAS 0.7.2)、クライアントがFreeBSD 8.2。6系列だと動かないとか。

ずっと、NFSではファイルのロックがとれないと聞いていた(思い込んでいた)けど、さっくり調べたらLinuxではとれるとか。 だったらFreeBSDでもいけるっしょ、と調べてみた。

結論から行くとロックはとれる様子。

まずはテストコードを書いてみた。

<?php
$fp = fopen("/mnt/nfs/hoge.txt", "r+");
if(flock($fp, LOCK_EX)){
 echo 'got exclusive file lock'."\n";
 flock($fp, LOCK_UN);
}else{
 echo 'cannot get file lock'."\n";
}
fclose($fp);
?>

shell> touch /mnt/nfs/hoge.txt
shell> php flock.php
cannot get file lock

ファイルのロックはとれていない。これが普通の(mountでnfsserver:/path/to/mount /mnt/nfsとかしたときの)nfsをマウントしたときの動作。いままではここであきらめていたけどここからちょっと突っ込んでみる。

さっくり調べてみるとrpc.lockd, rpc.statdを起動させるとロックが取得できるらしい。で、早速起動させてみる。rc.confに以下を追加して起動する。


shell> grep rpc /etc/rc.conf
rpc_lockd_enable="YES"
rpc_statd_enable="YES"

shell> sudo /etc/rc.d/statd start
shell> sudo /etc/rc.d/lockd start

shell> php flock.php
got exclusive file lock

サーバ側でもrpcを走らせる必要があるとか色々書いてあった。今回サーバはFreeNASのNFSを使っている。確認したらrpc.{statd, lockd}は動いていた。


shell> ssh freenas ps auxww | grep rpc

root         69671  0.0  0.0  6912  1452  ??  Ss   Mon10AM   0:00.37 /usr/sbin/rpcbind
root         69955  0.0  0.0 267976  1348  ??  Is   Mon10AM   0:00.03 /usr/sbin/rpc.statd
root         69992  0.0  0.0  6912  1300  ??  Is   Mon10AM   0:00.00 /usr/sbin/rpc.lockd

おかげでうまくいっているみたい。めでたしめでたし。

参考リンク

http://groups.google.com/group/mailing.freebsd.fs/browse_thread/thread/0cd34288efff29ec/d8202d636557a2ae

FreeNAS 0.72のftpに接続できない

FreeNAS 0.72のftpに接続できない。

shell> tail /var/log/ftp.log

Apr 12 16:09:53 blaster proftpd[40351]: 192.168.1.1 (::ffff:192.168.1.2[::ffff:192.168.1.2]) – USER yousan (Login failed): Limit access denies login
Apr 12 16:10:10 blaster proftpd[40351]: 192.168.1.1 (::ffff:192.168.1.2[::ffff:192.168.1.2]) – USER yousan (Login failed): Limit access denies login
Apr 12 16:11:01 blaster proftpd[40351]: 192.168.1.1 (::ffff:192.168.1.2[::ffff:192.168.1.2])- USER yousan (Login failed): Limit access denies login

Limit access denies loginでググってみると、proftpd.confの設定らしい。

It is due to a setting in /etc/proftpd.conf. This was a new Plesk 8.0.1 installation and the default setting :

<Limit LOGIN>
AllowGroup ftpusers
DenyAll
</Limit>

FTP Problem - limited access denies login - Parallels Forums

どうやらftpグループに属していないと接続できないような設定らしい。

デフォルトでこんな設定らしいけど、いままでおそらくこの設定は外して運用してきたんだろうね。知らなかった。

しょうが無いので接続させるユーザはftpグループに属するようにしてやる。

 

うまくつながった。

FreeNASで一つのNICに二つ以上のIP addressを付与する

FreeNASで一つのNICに二つ以上のIP addressを付与する。

現在あるホストに192.168.52.214というアドレスを割り振っているが、(物理的に)同じセグメントにおいてあるマシンとのやりとりは、デフォルトゲートウェイを介さなければならない。

これは、一つのスイッチングハブに複数のL2のセグメント、例えばあるホストは192.168.0.1のアドレスであり、あるホストは192.168.1.1、ということだ。

普通はこんなことにしない。L2スイッチでつながれるのはブロードキャストドメインであるはずであり、各ブロードキャストドメインをつなぐのがルータの役割だからだ。

でもなんかなんとなく、こんな構成にしている。

でもここで問題がある。先述のホスト、192.168.0.1(ホストA)と192.168.1.1(ホストB)が通信するときにすべてお互いのデフォルトゲートウェイとなっているルータを介して通信してしまっていることだ。

これは実はルータを介さず直接通信することができるはず、である。

そのための手段は、

  1. デフォルトゲートウェイがICMPリダイレクトを送信して、それぞれのホストが直接macアドレスをホストA、ホストB宛てにしてやりとりする
  2. ルータからルーティング情報を広告する、もしくは各ホストにスタティックルートを書く。これでデフォルトゲーウェイに投げることなくarp解決を各自のホストで行ってもらう。
  3. arpプロキシでもいけるのかも・・・、しれない。いややっぱり無理っぽい

でもそれぞれには問題がある

  1. デフォルトゲートウェイにあるルータ(RT58i)がICMPリダイレクトを投げてくれない。またデフォルトではICMPリダイレクトを受け取らない(拒否する)ホストがある。
  2. ルーティング情報を設定するのが面倒。ルータから管理セグメント宛ての広告にしても、各ホストでRIPなどの待ち受け(例えばwindowsならRIPリスナ)の設定がたくさんひつようで面倒。静的ルーティングは構成変更とかあると大変そう、というか絶対漏れて通信できなくなってましたっていうホストがでてくる。

といったところでいろいろと躊躇していた。

ところで最近いろいろとホストが増えてきて、セグメント間のネットワーク利用率も高まり、いよいよ通信はルータがボトルネックになってきた。でもこれらのセグメントにはちょっとした特性があった。それは帯域を利用するホストがごく少数に限られていること、だ。

それぞれのセグメントにはそれぞれのデフォルトゲートウェイをおいて、ネットワークを司るサーバ(DNSとかnisとかメールとかwebとか。 dhcpはl2だったので統合されてしまった)がいるんだけど、そいつらへのアクセスが多い。ココで言う多いとはもう一方のセグメントからの通信、すなわちルータの帯域を使う通信が多い、ってことだ。

でも実は、多いといえども帯域的にはそこまで使ってなかった。だから今までそこまで問題視してなかった。所詮はDNSの問い合わせとかypとか、キャッシュされやすい項目だしまぁ許容範囲内だった。でもあるときから状況が変わってしまった。それはNAS/SANの導入だ

NASを導入したんだけどこれって結構お金がかかる。HDDとかマシン代とか。ついでに運営コストも結構こまめに設定いれると面倒だ。だから一元化してしまいたい、してしまった。これによりこのホストには同じ(論理)セグメントからの通信はもちろん、もう一方のセグメントからの通信量も増えてしまった。さてさてここでルータがいよいよ本格的にボトルネックになってしまった。

いよいよ上述の三つのうち、そろそろどれかを解決して直接通信させる必要がでてきたんだけど、ここでyubirdたんからアドバイスが。

「NIC二枚さして別のIP持たせればいいんじゃない?」

なるほど、頭いいです。それをやれば確かに現在の問題は解決する。万事オッケー。でもこれこれには投資が必要だ。

そこで横着な案を思いついた。一つのNICに複数のIPアドレスを設定すればよいのではないか・・・、と。

ところでこのNASはFreeBSDをベースとしたFreeNASで構築されている。中身はまぁFreeBSDだ。ということはFreeBSDでNICへ複数のIPアドレスを持たせてやれ(どうやらこれはエイリアスと呼ばれるらしい)ばよい。FreeBSDとなると情報源も一挙に広がるので対処しやすい。

さてそこでさっくりググって情報を漁る。さっくり見つかる。

rc.conf

ifconfig_lnc0=”inet 192.168.140.129 netmask 255.255.255.0″
ifconfig_lnc0_alias0=”inet 192.168.254.100 netmask 255.255.255.0″
ifconfig_lnc0_alias1=”inet 172.17.10.100 netmask 255.255.0.0″

設定終了後サーバの再起動等を行って設定を反映させます。
FreeBSD-複数IPアドレス設定(alias) — server-memo.net

なるほど、これなら自分にもできそうだ、ということで早速試してみる。とここで問題が。

FreeNASのrc.confってどうやら再起動ごとに書き換わってしまうみたい。ということで手動で(ifconfigをたたいて)できないか試すことになった。

まずは実験前の状態


# ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
ether 00:50:xx:xx:xx:xx
inet 192.168.0.1netmask 0xffffff00 broadcast 192.168.52.255
media: Ethernet autoselect (1000baseT <full-duplex>)
status: active

# ping 192.168.1.1
PING 192.168.1.1 (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=63 time=0.822 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=63 time=0.568 ms

ここでTTLが63になっている。ちなみにICMPリダイレクトがくると二発目ぐらいから64とかになったりする。今回は見てても全然減らない。

tracerouteしてみると


# traceroute 192.168.1.1
traceroute to host002.l3tp.org (192.168.84.2), 64 hops max, 52 byte packets
1  192.168.0.254 (192.168.0.254)  0.703 ms  0.439 ms  0.407 ms
2  192.168.1.2 (192.168.1.2)  0.790 ms  0.470 ms  0.470 ms

やっぱりルータ経由みたい。

さてテキトウにmanみてaliasを与える。


# ifconfig em0 alias 192.168.1.1/24
# ifconfig
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
ether 00:50:xx:xx:xx
inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.52.255
inet 192.168.1.1 netmask 0xffffff00 broadcast 192.168.84.255
media: Ethernet autoselect (1000baseT <full-duplex>)
status: active

なんか二行になったwwwうぇっうぇっ。こんなの始めてww。

aliasの後はinetをつけずにIPアドレスを記述。サブネットマスクはnetmask 255.255.255.0でもいいしCIDRでもいいらしい。

pingしてみる


# ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=64 time=0.870 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.401 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.308 ms

ちゃんとTTLが64のままだ。


# traceroute 192.168.1.2
traceroute to 192.168.1.2 (192.168.84.2), 64 hops max, 52 byte packets
1 192.168.1.2 (192.168.1.2)  2.449 ms  2.087 ms  0.701 ms

ばっちり。

さてここでaliasの解除してみる。解除のためには-aliasをつけるらしい。


# ifconfig em0 -alias 192.168.1.1

後ろのIPアドレスを指定しないとすべての関連づけ?されているIPアドレスがなくなってしまうので注意。DHCPで配られたアドレスすらなくしてしまった。

ひとまずこれで一つのNICに複数のIPアドレスをつけることができた。

方法は二つ、

  • rc.confにifconfig_em0_alias0=”inet 192.168.1.1″の形で書くこと
  • ifconfigのaliasオプションで設定してやること

これを使ってFreeNASに複数のIPアドレスを付与してみる。

中略

手動で与えて、他のホストからnetperfをかけてみる。


freenas%./netserver
Starting netserver at port 12865
Starting netserver at hostname 0.0.0.0 port 12865 and family AF_UNSPEC

client% netperf -H 192.168.0.1
TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.0.1 (192.168.0.1) port 0 AF_INET
Recv   Send    Send
Socket Socket  Message  Elapsed
Size   Size    Size     Time     Throughput
bytes  bytes   bytes    secs.    10^6bits/sec

65536  32768  32768    9.93       91.26
client% netperf -H 192.168.1.1
TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.1.1(192.168.1.1) port 0 AF_INET
Recv   Send    Send
Socket Socket  Message  Elapsed
Size   Size    Size     Time     Throughput
bytes  bytes   bytes    secs.    10^6bits/sec

65536  32768  32768    9.90      847.86

別セグメントからはおよそ91Mbp、同じセグメントからは850Mbps出た。

別セグメントだとルータを通過するのでそこのスループットで頭打ちになっているけど、同じセグメント扱いのときはワイヤスピード?にちかい850Mbpsが出た。ばっちりだ!

FreeNAS 0.72で、sambaの設定で各ユーザのホームディレクトリを表示してやる

FreeNAS 0.72で、sambaの設定で各ユーザのホームディレクトリを表示してやる。

samba/cifsの設定だと一つ一つディレクトリをぽちぽち追加しないとダメ。

これだと複数人のユーザがいる場合、全部を追加してやるか、ホームディレクトリの親元を共有してやる必要がある。

なのでsmb.confに追加の設定を与えて自分のホームディレクトリだけをみれる(browsable)ようにしてやる。

[homes]
comment = Home Directories
browseable = no
writable = yes

これでユーザはsmbでfreenasのサーバにアクセスしたときにホームディレクトリが表示されるようになる。

でもユーザのホームディレクトリはデフォルトで/mntとかになっているのでこれを適宜変えてやる必要があるので注意。

FreeNASに接続できなかった

FreeNASに接続できなかった。

結論から言うとデフォルトゲートウェイが設定されてなかった。

まずインストール直後のFreeNASを起動して、IPアドレスはDHCPから取得するように端末から設定した。DHCPからうまくアドレスをもらっていたようだったのだけど、隣のセグメントからつながらない。


クライアント: 192.168.1.100
FreeNAS: 192.168.2.100

みたいな感じ。ファイアウォールのせいかと思って、FreeNASと同じセグメントのマシンからSSHトンネルを掘って作業してたんだけど、どうもおかしい。基本的にあいている設定で、隣のセグメントからつながらないような設定が見当たらない。

しょうがないのでsshでログインしてdhclientを再起動。したらdefaultrouteがちゃんと設定されてた。うーん、再起動でちゃんと設定されるか見ておく必要あり。だめならrc.confを書き換えるか、毎度それも書き換えられてしまうならパッチを送るか。