Quantcast
Channel: りんけーじ
Viewing all 62 articles
Browse latest View live

GlusterFSをESXiから使う(3) 書き込み速度測定

$
0
0

実運用を想定して、ESXiの仮想マシンを乗っけてddで計ってみた。
結果は大体20MB/sくらいは出ているのでセーフな範囲。もう少し速いとうれしい。

速度を気にするならstripeも測るべきだけど出てこないのは、またバグっぽいものを見つけたから。
こっちはまた追ってまとめる。

条件いろいろ。

  • ノードは10.0.0.1、10.0.0.2、10.0.0.3の3台。
  • アクセス元は上記の通りVMware ESXi上のVMで、8GBの仮想ハードディスクをNFSデータストア上に配置している。
    アクセス先には全ケースで10.0.0.1上のNFS(glusterfs組み込み)を使用。
  • 各ノードの/mnt/dataはiSCSI経由でそれぞれ別のNASに接続。
    ZFSのZIL(log)とL2ARC(cache)をノード上のHDDに指定して、ZVOL上にUFSを作っている。
  • 測定はdd if=/dev/zero of=/dev/da1 bs=65536による。10回測定。

ボリュームの構成は3種類試してみた。

Single
# gluster vol create gv0 10.0.0.1:/mnt/data/brick
Replica 2
# gluster vol create gv0 replica 2
  10.0.0.1:/mnt/data/brick
  10.0.0.2:/mnt/data/brick
Disperse 3
# gluster vol create gv0 disperse 3 redundancy 1
  10.0.0.1:/mnt/data/brick
  10.0.0.2:/mnt/data/brick
  10.0.0.3:/mnt/data/brick

中央値6個の平均は以下の通り。単位はbyte/sec。
別ノードと通信しないSingleがやや早い。

Single Replica 2 Disperse 3
28,670,396 20,138,774 21,131,990

ちなみに生データ。こちらも単位はbyte/sec。中央値処理の為にソート済み。
8GBも書いているからか、大きなバラつきはない模様。

Single Replica 2 Disperse 3
26,766,310 18,828,979 19,826,040
27,617,969 18,966,455 20,091,941
27,636,101 19,237,992 20,740,261
28,142,674 19,668,180 21,079,484
28,423,709 19,904,223 21,080,437
29,019,394 20,034,735 21,137,484
29,109,941 20,818,509 21,261,837
29,690,557 21,169,007 21,492,439
30,513,710 21,365,170 21,911,347
31,736,206 21,894,438 22,051,744

QNAPのファームウェアを焼きなおす

$
0
0

うっかりやらかしてQNAP NASのファームウェアが入ったFlashを焼き払っちゃった。

結論

  • ほぼ公式ガイドどおりでいける。
  • Damn Small LinuxじゃなくてCore OSを使おう。
  • cpじゃなくてcat+redirectで書く。

そもそも昔みたいにファームウェアは普通のコマンドで書けないところにあるものと思ってたら、普通に/dev以下に居たらしく、油断したのが始まり。何をしようとしてたのかは置いておいて。

さて、復旧用にどうやらFull Imageが配布されていて、Flashにそのまま書けばいいらしい。
「文鎮化」一歩手前のような壊れ方でも、公式にきちんと復旧用情報があってすばらしい。

http://wiki.qnap.com/wiki/Firmware_Recovery

しかしガイドで勧められている”Damn Small Linux”をUSB Stickに焼いたところ、起動にやたらと時間がかかった挙句、X Windowの立ち上げでブラックアウトしたままとなって失敗。
そもそもコマンド数個のためにX Windowの入ったDistroを勧めるのが間違ってる気がするので、Core OSに切り替える。
こいつはイメージ(10MB!)を拾ってきて、Unetbootinで焼けばいい。

あとはCore OSを起動して焼くだけ……なんだけど、ここでガイドに書かれている通りcpを使ってコピーしてもうまくいかなかった。直後はfdiskでちゃんと書き込んだパーティションテーブルは見えるし、hexdumpで中身も見える。けど、再起動するときれいさっぱり居なくなっている。
最終的にはきちんと確認せずに復旧させちゃったけど、なぜかcat image > /dev/sdaのようにするとうまくいく模様。
cpと何が違うんだろうね?

GlusterFSの構成ディスクを交換する

$
0
0

図らずも一台のデータを壊してしまったので嬉々として復旧実験。
ノード自体は生きているが、brickの中身を壊しちゃったという場合の話。

参考にするのはGlusterFSの公式資料。

http://www.gluster.org/community/documentation/index.php/Gluster_3.4:_Brick_Restoration_-_Replace_Crashed_Server

  1. とりあえずglusterfsを止める。
    現状、FreeBSD版のservice stopだと子プロセスが残るのでkillallしてくださいな。
    (そのうち直します。あとglusterfsdじゃなくてglusterdが正しいという話もね……。)
    # service glusterfsd stop
    # killall glusterfsd
  2. ディスクを入れ替えたりいろいろする。
    newfsとかmountまで済ませる。
  3. brickのディレクトリを手動で作る。
  4. setextattrbinを持ってきてビルドしておく。(→おまけ)
  5. brickのディレクトリにvolume-idを設定する。ちょっと長いone-linerだけどこんな感じ。
    # cat /var/db/glusterd/vols/<ボリューム名>/info |
        perl -ne 'm/volume-id=/ and s/^.*=// and s/-//g and print' |
        setextattrbin user trusted.glusterfs.volume-id -stdin 
  6. glusterfsを起動して、healを開始させる。
    replicatedなら、
    # service glusterfsd start
    # gluster vol heal <ボリューム名> full

    disperseならNFSでマウントしてから、

    # find <マウント先> -exec stat {}\;

    などで復旧を開始。

おわり。

おまけのバイナリ値なxattrの話

標準のsetextattrだと文字列しか設定できない。
一応バイナリ(表示不可文字)も引き数に設定できるものの、万が一”00″が入ったらダメ。
たとえば、こんな風に消えてしまう。(これだけだとperlの責任が否定できないけどね)

# echo -n "110022" | perl -e 'print pack("H*", );' > a
# hexdump -C a
00000000  11 00 22                                          |.."|
00000003
# perl -e 'print $ARGV[0]' `cat a` | hexdump -C
00000000  11                                                |.|
00000001

そんなわけでsetextattrbinを作ったのです。

少しだけ判断に困るスパムがきた

$
0
0

GlusterFSのdisperseを試す(その2) にこんなコメントがやってきた。
文章はマトモだし、アレな薬の販売とか、カネカネカネな文章でもない。

This adds latency, reducing performance when this happens. Some GlusterFS performance xlators can help to reduce or even eliminate this problem for some workloads, but it should be taken into account when using dispersed volumes for a specific use case.

さて、レイテンシがあがるような設定はしていない、というか件の記事ではvolume createしかしてない。
メールアドレスで検索してもこれといって引っかからないし、おかしいなと思って本文で引っ掛けたら、glusterfsのマニュアルの一部だった。

Setting up GlusterFS Server Volumes

ま、変なURLが付いてる時点で落とすべきだったかな。
スパム送信側もいろいろ考える。ちょっと楽しそうだなと思ってしまった。

iscsi initiator+gjournalが固まる(2)

$
0
0

iscsi initiator+gjournalが固まるというのを前に書いた。
しかしどうやら、負荷のかけ方によっては、

  • 複数のiscsi targetに接続したとき
  • geomg_gateを使ったzfsを作って書き込んだとき

にも同じように固まることが分かった。
この状態ではまると、gstatで問題のデバイスがキュー長が非零のままで止まり、いつまでたっても解消しない。
そして 、こっちのほうが困るのだが、再起動ができなくなる。panicですら自動再起動できずに止まる。カーネルのコアも吐けない。

マシン固有の問題か、それともほかのなにかか。同じ型番のマシン複数で起きてるから、個体のバグではなさそう。
とりあえずは環境を別のマシンに移して起きるか確認して、あとはシリアル経由でカーネルデバッグかな……。

カーネルデバッグに手を染めてみる(1)

$
0
0

もたもたしてたらFreeBSD 11.0-BETA2が出てしまった。
この前から続けて、最後に試したFreeBSD 11.0-BETA1なシステムでiSCSI+zfsがハマる原因を調べる。
(一応書いておくと、9.3-RELEASE, 10.1-RELEASE, 10.3-RELEASEのいずれでも発生している。)

参考資料

  1. カーネルをビルドする。
    # cd /usr/src
    # cp sys/amd64/conf/GENERIC sys/amd64/conf/DEBUG
    # emacs sys/amd64/conf/DEBUG
    <ここでoptions DDBを追加>
    # make kernel-toolchain
    # make buildkernel KERNCONF=DEBUG
    # make installkernel KERNCONF=DEBUG
    # reboot
    

    /usr/srcにソースがない人はftp://ftp.jp.freebsd.org/pub/FreeBSD/releases/amd64/11.0-BETA1/src.txzあたりから持ってくる。持ってくるときはカーネルのバージョンに気をつけないとひどい目に遭う。(遭った。)

  2. デバッガに入れるか確認する。sysctlでenterしてみる。
    # sysctl debug.kdb.enter=1

    ここでdebug.kdb.enter: 0 -> 0と出る場合はカーネルが正しくビルド、もしくはインストールできていない。
    無事にddbに入れたらcontで脱出。

  3. シリアルケーブルをつなぐ。
    テスト用機(デバッグされる側)と適当なマシン(デバッグ作業をする側)をシリアルケーブルでつなぐ。
    接続できたかはcuでチェックする。
    双方でcu -l /dev/cuau0を実行して、あとは適当にキーを叩いて他方に出ればOK。
  4. /boot.config/boot/loader.confを書く。後者はいらないかも。
    /boot.config:
    -h

    /boot/loader.conf:

    hint.uart.0.flags="0x90"
  5. これで、通常は画面に出るメッセージの類がすべてシリアルコンソールに向いた。

  6. デバッグ作業マシンでcuを叩いておいて、テスト用機を再起動する。
    無事に起動時のメッセージが見えればOK。出ないときは……知らない。
  7. デバッグ作業マシンからデバッガに入る。cu越しに叩いてみる。
    # sysctl debug.kdb.enter=1

    無事にローカル上での実行と同じようにddbのコンソールに移ればOK。途中で途切れたりキー入力を受け付けない場合は、きっと/boot/loader.confの設定あたりが怪しい。うまくいったらcontで脱出。

  8. 長くなったので次に続く。

カーネルデバッグに手を染めてみる(2)

$
0
0

前回からの続き。

VMを使えばシリアルポートなんて簡単に接続できることに、いまさら気づいた。(始めてから2週間くらい)
機材そろえちゃったよ……。

気を取り直して、ハマっているbio(I/O)を探してみる。(そしてこれもうまくいかなかった。)

sys/geom/geom_io.cによれば、g_bio_run_(down|up|task)の3つのキューがあるらしい。

キューはstruct g_bioqで、宣言はsys/geom/geom.hにある。

struct g_bioq {
        TAILQ_HEAD(, bio)       bio_queue;
        struct mtx              bio_queue_lock;
        int                     bio_queue_length;
};

はsys/sys/queue.hにある。

#define TAILQ_HEAD(name, type)                                          \
struct name {                                                           \
        struct type *tqh_first; /* first element */                     \
        struct type **tqh_last; /* addr of last next element */         \
        TRACEBUF                                                        \
}

とりあえず1つ追ってみる。

db> print g_bio_run_up
ffffffff81c208d0
db> x/gx g_bio_run_up
g_bio_run_up: 0

と思ったらそもそもキューが空だった。down/taskもからっぽ。
そもそも当てずっぽうだったから、原因にすぐたどり着くとは思ってなかったけど、ちょっと残念。

QNAP NAS+iscsi+zfsが固まる

$
0
0

iscsi initiator+gjournalが固まるからの続き。

カーネルデバッグは敷居が高すぎて早々に諦めつつ、iSCSI+ZFSは使いたいので調査継続。
どうやらiSCSI TargetであるQNAP NAS、中身はLinux LIOが怪しい気がする。

まずは問題点を整理しておく。
手順と現象は以下の通り。

  1. FreeBSDのiSCSI InitiatorでQNAP NASのiSCSI Targetに接続する。
  2. 接続したiSCSI Target上にzpoolを作る。gnopでセクタサイズを4096にしてもしなくてもいい。
  3. 作成したzpool(zfs)にsync=alwaysを指定する。
  4. ddでがりがり書き込む。
    元がアクセス速度調査なので、dd if=/dev/zero of=/dev/da1 bs=65536 count=4096とか。
  5. gstatで監視する。そんなに待たずにL(q)が1になって固まる。

詳しい現象は以下。

  • ddはCtrl-Cで止められない。I/Oのsyscall中なので当たり前。
    ちなみに下手なI/Oを発生させるとどんどん巻き添えになる。
  • ハマったデバイスに読み込み要求を出すと(つぎにまたハマるまでの数秒から数十秒)復活する。
    たとえばdd if=/dev/da1 of=/dev/null bs=512 count=1とか。
  • iscsictl(引数なし)が固まる。これはFreeBSDのバグであろう。(興味が無いのでとりあえずスルー)
  • rebootしようとするとどこかで固まる。(ディスプレイをつないでいないので分からないが、iscsidの停止か、Syncing Disksとかその辺であろう)
  • QNAP NASのWeb管理コンソールから再起動させようとすると応答が無くなる。電源OFF→ONしかない。

最後の項目があるのでQNAP NASがダメになっているのは想像に難くない。
が、OpenIndiana(illumos)から同じ構成・パターンでテストすると起きないから困る。

そして、ついに (ぶちきれて)パケットキャプチャを取ってみたところ、はっきりとQNAP側が応答を返していないことが見えた。

まずは現象発生時のThroughput Graphから。
これはハマった状態から初めて、ちょこっと読み込みをさせて復活させて、少ししてやっぱりハマって、という流れ。

20160806_iscsistuck_throughput

ここで解析するに当たっての事前知識も整理しておく。
iSCSIは要求-応答ペアを識別するために32-bitの数値を使う。RFC 3720では3.2.2.1節でCommand Sequence Numberと呼んでいるが、WiresharkはInitiator Task Tagと呼んでいる模様。
表示でEndianがひっくり返っているようだが、誰が悪いのかは知らない。とりあえずペアが識別できればよいので放っておこう。

20160806_iscsistuck_wireshark1

各パケットのTask Tagを見たいので、Column Configurationで追加しておく。
Customを選んで、Filterに入力するような式を投げ込めばいい。今回だとiscsi.initatortasktagになる。

20160806_iscsistuck_wireshark2

これで見えるようになった。
さて、2つ目のThroughput Graphの復活しているところをクリックして、大体近くまで飛び、あとは少しずつ戻ってデータ転送が復活しているところを探す。(1つ目だと元の要求がキャプチャされてないから2つ目を選ぶ)
時間を見ると、どうやら13403フレームがたたき起こした読み込み要求で、13404フレームが今更な書き込み応答だ。

20160806_iscsistuck_wireshark3

絞り込んでみると、いかにひどいことが起きているかがわかる。

20160806_iscsistuck_wireshark4

これだけを見るとFreeBSDのInitiatorに非はないが、どうなんだろうか。

とりあえず、gnopでセクタサイズを8192にすると発生頻度が低くなる(というか今のところ起きていない)ので、それで凌ぐつもり。
またハマったり、気になったらどうにかしよう。


ReadyNASのRAID-5障害復旧

$
0
0

遠隔地に配置していたNETGEARのReadyNASで障害が発生、RAID-5構成の4台中2台で障害が起きてお亡くなりに。
でも良く見ると片方はなんとか認識できそうだったのでがんばってみた。

起きたことはServerFaultの質問 What steps should I take to best attempt to recover a failed software raid5 setup?とほぼ同じ。

うちの場合は1台が故障したのち、復旧(rebuild)”後”になにかが起きてこの現象に陥った。
残念ながらうっかりSSHのウィンドウを閉じてしまったので詳しいログは残していない。(運用者失格)

SSHでログインしてdmesgするとこんなメッセージが見える。

kicking non-fresh sde1 from array!
not enough operational devices (2/4 failed)

どうやらLinuxのmdでRAIDを実現しているらしいことをここで知り、mdadmでいろいろできることもわかる。
そしてmdadm --examine /dev/md127の結果から以下にたどり着く。
mdadm – re-added disk treated as spare
生きているハズの3台を使ってmdadm --assembleしようとすると、なぜかspare扱いされるというもの。

mdadm: /dev/md127 assembled from 2 drives and 1 spare - not enough to start the array.

最終的にどうしたかというと、まさに上記にあるとおり、mdadm --createした。
ここでやっているのは「パーティションテーブルを消して、同じ形でパーティションテーブルを切ればアクセスできる」というのと同じで、間違った形で定義しようものならデータが吹き飛ぶ危険な操作。それでも復旧できたのでよかった。

# mdadm --stop /dev/md127
# mdadm --create /dev/md2 --level=5 --raid-devices=4 --chunk=64 --name=RackStation:2 /dev/sdd3 /dev/sdc3 missing /dev/sda3 --assume-clean

ちなみに壊れたのは緑のWD 1.5TB(WD15EADS)の2台。
rebuild中にiostat -xで見ているとawaitが10000(ms)を超えていた。
テストマシンにつないでddを叩いても似たような感じだったので廃棄コースへ。2010年購入なので約6年稼動。

QNAP NAS+iscsi+zfsが固まる(2)

$
0
0

前回の続き。

結局FreeBSD 9.3-RELEASEにしたら直った。
FreeBSD 10.0以降のiSCSI Initiatorがおかしいか、相性が悪いかのどちらか。
パケットキャプチャの結果があるから後者もあるとは思うが、余計なバグを踏まされたので前者も疑わしい。

iscsi fails to reconnect and does not release devices

iscsiのカーネルプロセスが”simfree”の状態で固まるというもの。
接続を切断して再接続しようとしたりするとハマってしまい、かなりの曲者。
報告者によれば、
> I tried 11-RC1 and was not able to reproduce the issue.
とのことなので、11-RC1にすればいいのかもしれないが。
11-BETA1でも発生していたし、そもそもこれ以外の問題(もともとの件)があるので、今回は今更ながら9.3-RELEASEで構築を継続するつもり。

Windows+Pythonにmatplotlibをインストール

$
0
0

諸般の都合でWindows+Pythonにmatplotlibをインストールしようとしたらコケたのでメモ。

結論: pipをアップグレードすればよろしい。

C:\>C:\Python27\Scripts\pip install matplotlib
You are using pip version 7.0.1, however version 8.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting matplotlib
  Using cached matplotlib-1.5.3.tar.gz

(中略)

Command "python setup.py egg_info" failed with error code 1 in c:\users\2510\appdata\local\temp\pip-build-bxarh2\matplot
lib

C:\>C:\Python27\Scripts\pip list
You are using pip version 7.0.1, however version 8.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
numpy (1.11.1)
pip (7.0.1)
setuptools (16.0)

首をかしげながらいろいろ調べた挙句、pipがちゃんと動いていない気がして良く見たら、「You are using pip version 7.0.1, however version 8.1.2 is available.」といわれている。(しかも2度も)

C:\>C:\Python27\Scripts\pip install --upgrade pip
You are using pip version 7.0.1, however version 8.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting pip
  Downloading pip-8.1.2-py2.py3-none-any.whl (1.2MB)
    100% |################################| 1.2MB 327kB/s
Installing collected packages: pip
  Found existing installation: pip 7.0.1
    Uninstalling pip-7.0.1:
      Successfully uninstalled pip-7.0.1
Exception:
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\pip\basecommand.py", line 223, in main

  File "C:\Python27\lib\site-packages\pip\commands\install.py", line 297, in run
    # wheels, and don't try to build wheels when wheel is
  File "C:\Python27\lib\site-packages\pip\req\req_set.py", line 633, in install

  File "C:\Python27\lib\site-packages\pip\req\req_install.py", line 734, in commit_uninstall
    )
  File "C:\Python27\lib\site-packages\pip\req\req_uninstall.py", line 153, in commit
    self.file = pth_file
  File "C:\Python27\lib\site-packages\pip\_vendor\retrying.py", line 49, in wrapped_f
    return Retrying(*dargs, **dkw).call(f, *args, **kw)
  File "C:\Python27\lib\site-packages\pip\_vendor\retrying.py", line 212, in call
    raise attempt.get()
  File "C:\Python27\lib\site-packages\pip\_vendor\retrying.py", line 247, in get
    six.reraise(self.value[0], self.value[1], self.value[2])
  File "C:\Python27\lib\site-packages\pip\_vendor\retrying.py", line 200, in call
    attempt = Attempt(fn(*args, **kwargs), attempt_number, False)
  File "C:\Python27\lib\site-packages\pip\utils\__init__.py", line 89, in rmtree
    def get_prog():
  File "C:\Python27\lib\shutil.py", line 247, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 247, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Python27\lib\shutil.py", line 252, in rmtree
    onerror(os.remove, fullname, sys.exc_info())
  File "C:\Python27\lib\site-packages\pip\utils\__init__.py", line 101, in rmtree_errorhandler
    shutil.rmtree(dir, ignore_errors=ignore_errors,
WindowsError: [Error 5] アクセスが拒否されました。: 'c:\\users\\2510\\appdata\\local\\temp\\pip-usbfat-uninstall\\python
27\\scripts\\pip.exe'

……ちょっと、大丈夫なのこれ?と思いつつ続ける。

C:\>C:\Python27\Scripts\pip --version
pip 8.1.2 from C:\Python27\lib\site-packages (python 2.7)

OK、エラーのことは忘れよう。

C:\>C:\Python27\Scripts\pip install --upgrade pip
Requirement already up-to-date: pip in c:\python27\lib\site-packages

C:\>C:\Python27\Scripts\pip install matplotlib
Collecting matplotlib
  Downloading matplotlib-1.5.3-cp27-cp27m-win_amd64.whl (6.1MB)
    100% |################################| 6.1MB 125kB/s
Collecting python-dateutil (from matplotlib)
  Downloading python_dateutil-2.5.3-py2.py3-none-any.whl (201kB)
    100% |################################| 204kB 380kB/s
Requirement already satisfied (use --upgrade to upgrade): numpy>=1.6 in c:\python27\lib\site-packages (from matplotlib)
Collecting pytz (from matplotlib)
  Downloading pytz-2016.6.1-py2.py3-none-any.whl (481kB)
    100% |################################| 481kB 469kB/s
Collecting pyparsing!=2.0.4,!=2.1.2,>=1.5.6 (from matplotlib)
  Downloading pyparsing-2.1.8-py2.py3-none-any.whl (54kB)
    100% |################################| 61kB 787kB/s
Collecting cycler (from matplotlib)
  Downloading cycler-0.10.0-py2.py3-none-any.whl
Collecting six>=1.5 (from python-dateutil->matplotlib)
  Downloading six-1.10.0-py2.py3-none-any.whl
Installing collected packages: six, python-dateutil, pytz, pyparsing, cycler, matplotlib
Successfully installed cycler-0.10.0 matplotlib-1.5.3 pyparsing-2.1.8 python-dateutil-2.5.3 pytz-2016.6.1 six-1.10.0

QNAP TS-451にFreeBSDをインストールする

$
0
0

iSCSIが応答しなくなったりして困った挙句、FreeBSDをインストールしちゃった。

TS-451の中身はただのIntel CPUなPCなので、特に問題なくインストールできる。
怖いので内蔵Flashにはインストールせず、HDDにインストールした。

試したのはFreeBSD 10.3-RELEASEと、Release Announcementの出ていないFreeBSD 11-0-RELEASE。(10/10/ 9:30JST現在)
どちらも手順は変わらず。

  1. NASにキーボードとディスプレイ、”-memstick.img”を焼いたインストール用USBメモリ、インストール先HDD(or SSD)をつないで(再)起動する。
  2. “Starting…”が出ている間にDELキーを叩いてBIOS設定に入る。
  3. BOOTの設定で、インストール用USBメモリを最優先に設定する。ついでにインストール先のHDDもその下くらいに設定しておく。逆に、QNAP USBナントカは内蔵Flashぽいので下げておく。
  4. いつも通りにFreeBSDをインストールする。
    挿したディスクはada*で見える。(TS-451の場合)
    インストール用USBメモリはda0、内蔵Flashはどうやらda1になった。(以下、gpartの出力より)
    =>      1  1007615  da1  MBR  (492M)
            1        7       - free -  (3.5K)
            8    10488    1  linux-data  (5.1M)
        10496   481536    2  linux-data  [active]  (235M)
       492032   481536    3  linux-data  (235M)
       973568    34048    4  ebr  (17M)
    
    =>    0  34048  da1s4  EBR  (17M)
          0  16640      1  linux-data  (8.1M)
      16640  17408    521  linux-data  (8.5M)
  5. 拍子抜けするくらい簡単で、しかも普通に動く。ちなみにEthernetはigb0/1で認識される。
    あとはCAM Targetを設定してiSCSI Targetを作ればiSCSI箱のできあがり。

    メモリに余裕があるならZFS on Rootしてもいいし、ディスクは全部CAM Targetにまわしたい!なら外付けUSB HDDにインストールするのもいい。
    我が家では全ディスクに8GBの領域を作って、zpool mirror createしてインストールした。(GPTZFSBootを参照)

    さて、最初はVM(QNAP Virtualization Station)でFreeBSDを動かして……というのも試したけ.
    しかしFreeBSDのvirtioドライバがまだまだなせいか、iSCSI Targetを動かしてると割り込み(intr)処理でCPU使用率が飽和して転送速度が残念なことに。
    この辺がもっと改善すれば、今以上に仮想マシン主導の構成ができるんだけどなー。

Shuttle DS57Uがディスプレイなしで起動できない

$
0
0

タイトルどおり。
ShuttleのスリムでシンプルなDS57Uを愛用していたけど、FreeBSD 10以降でディスプレイなしだと起動できない。
今のところ解決法は無さそう。起動時だけディスプレイをつなぐか、HDMIのダミーアダプタをつなぐかしないといけない。

  • FreeBSD 9.3-RELEASEは特に何もしなくても起動できる。
  • FreeBSD 10.3-RELEASEはカーネルの読み込み中?かどこかで止まっている。(電源ボタンを一度押すだけで切れる)
  • FreeBSD 11.0-RELEASEは10.3-RELEASEと同じ。

9系列はiscsi initiatorがものすごくポンコツなので使いたくない。EOLも近い。

10.3-RELEASEではさらに以下を調べたが改善せず。

  • /boot/loader.confにkern.vty=scを書くとカーネルの読み込みは通過する。が、ifconfigが走るあたりで突然フリーズしてそのまま。(panicにすらならず、電源ボタン5秒押しでしか切れない)
  • コンソールをシリアルに切り替えても変わらず。(上の件がどこで止まったのかが分かるのはシリアルで見たから)
  • BIOSの設定に内蔵グラフィックのON/OFFはない。RAMをどのくらい共有するかの設定はあるが、デフォルト(64MB)から増加(256MB)させても変わらず。

ディスプレイ有無やsyscons/vtの設定の影響を受けるあたり、チップセットやディスプレイドライバ周りが原因と思うのだが、panicにすらならないと素人としては調べづらい。

zfs sync=disabledはどのくらい危ないのか

$
0
0

VMware ESXi用ストレージをZFS+NFSで運用していると必ず出てくる “sync=disabled” の件。
できればZIL(ZFS intent log)にSSDを使うなどして、安全にレイテンシを削るのが望ましいが、そうは言っていられないこともある。
仕方なく”zfs set sync=disabled”するとどれくらい危険かを少しだけ計ってみた。本当に少しだけ。

わざわざ調査用にシステムを組むのは面倒だったので、実験中のストレージをそのまま使った。
実験用のシステムはVMware ESXi→NFS+ZFS→iSCSIというやや面倒な構成をしている。
ESXi上のVMからは、常時NFS上のデータストア(の上のディスク)にddでzeroを書き続けさせて、電源を抜いたり電源ボタンを長押ししたりしていじめている。

結果は以下の通り。

  • NFS+ZFSなマシンの強制リブート
    10回実施して、特にこれといった異常は発生せず。zfs scrubでも異常は検知されなかった。
  • iSCSIストレージのリブート
    10回すべてでzpool scrubでチェックサムエラーを検知。mirrorだったのでそのまま回復。
    2台あるiSCSIストレージを両方ほぼ同時に停止した場合はmirrorでも修復できないケースが発生した。

metadataが壊れてアクセスすら不能になる、というようなケースは発生しなかったが、データ側の破損は(当然ながら)発生するようだ。
ちなみに、上の確認では”ESXiから見た整合性”は検証していない。つまりNFS/ZFS/iSCSIの異常時に”ESXi上のVMが安全に稼動を継続できるか”は怪しく、”一度VMを停止したのちに無事に起動できるか”を確認しただけであることに注意したい。

unionfsのバグを直そう

$
0
0

FreeBSDのunionfsがバグっててひどいという話。

元々、jailをunionfsを使って管理したいと思ってはじめたもの。Dockerがaufsを使っているのと同じイメージ。
同じようにハマる人はたくさんいるようで。

Thin jail woes
https://forums.freebsd.org/threads/54530/

> As krawall states, unionfs are dangerous. They will panic your kernel, at some point, guaranteed. I would stay waaay clear if I were you.

(意訳) unionfsはポンコツだから使わないほうがいいよ。

そんなこと言わないでみんなで使って直そうよ……。
というわけで、休日やら週末やらを使って調査&修正してみた。FreeBSDのVFSも少し理解できた(気がする)。

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=214326

これを機に、manページから以下の素敵な記述が消える日が来るといいんだけど。

THIS FILE SYSTEM TYPE IS NOT YET FULLY SUPPORTED (READ: IT DOESN'T WORK)
AND USING IT MAY, IN FACT, DESTROY DATA ON YOUR SYSTEM.  USE AT YOUR OWN
RISK.  BEWARE OF DOG.  SLIPPERY WHEN WET.  BATTERIES NOT INCLUDED.

余談:
なぜezjailやiocageを使わないかというと、こいつらがZFSを使うから。
ZFSが嫌いなのではなくて、中央ストレージにNFSで接続してるから使えないのだ。
file-backedなZFSも作れるけど、そうすると中央ストレージ(+ほかのシステム)から中身が見えない。(clustered-FSではないので、複数マシンから同時にマウントはできない)
それにfile-backedは仮想マシンのHDDイメージと同じで事前に容量を決めなきゃいけないし、zfs上でファイルを消しても縮んだりしない。
そんなわけで、今回の構成ではイマイチなのだ。


panic: ufs_direnter: compact2

$
0
0

この前から続けてunionfsをいじってたらpanicにやられた。
panicの中身からは分かりづらかったけど、VOP_CREATEに先んじてVOP_LOOKUPを呼んでいなかったことが問題らしい。

1ヶ月以上はまっていたので記録を残しておくことにした。
きっと誰の役にも立たないけど。

panic時のbacktraceはこんな感じ。

kdb_backtrace+0x8d
vpanic+0x1df
kproc_shutdown+0
ufs_direnter+0xbb2
ufs_makeinode+0x786
ufs_create+0x4a
VOP_CREATE_APV+0x16b
VOP_CREATE+0x51
(以下略)

ufs_direnterはsys/ufs/ufs/ufs_lookup.cで定義されていて、panicの条件はこうなっている。

if (spacefree < newentrysize)     
  panic("ufs_direnter: compact2");

ファイルを作る場合は、新しいファイルそのものに対応するエントリを生成するほか、それを配置するディレクトリも更新する。
ディレクトリの更新を行っているのがufs_direnter。そしてspacefreeはinode(?)の空き領域、newentrysizeは更新後の書き込みたいディレクトリ情報のサイズを表す。

さて、普通のメモリの管理(mallocとか)を考えると、newentrysizeを格納できる空き領域を探す処理があって、続けてその領域を使う(使用中フラグを立てるとか)処理があるはずだ。
しかし、ufsの場合この2つは遠く離れていて、前者がufs_lookup_ino(ufs_lookup)をCREATEモードで呼んだ場合、後者がufs_direnterにいる。

ufsのコードはまだあまり読んでないので、正直なところ理由は良く分からない。
とにかく、正しくVOP_LOOKUPを呼ばないでVOP_CREATEすると、楽しくないことが起きるということだ。

ちなみに、過去にunionfsで似たようなバグがあった模様。(FreeBSD unionfsの改善提案および修正状況のpatch13)
unionfsはrename時にファイルを生成する場合がある。
が、その後再度VOP_LOOKUPをせずにVOP_RENAMEしていたのが問題らしいように見える。LOOKUPし忘れたという意味では完全に同じ事象といえる。

バグレポート初め

$
0
0

正月という儀式を無視して年末からずっとunionfsを改造してたら、kern側のバグっぽいものを見つけたのでレポートした。

215705 – VOP_REMOVE call with invalid cn_nameptr

個人的にはバグだと確信してるけど、実はVOP_REMOVEのときはcn_nameptrは壊れててもいいとかあるのかな……ないよね……。

RedZone/memguardでカーネルデバッグ

$
0
0

モジュールをいじってたらkernel: Fatal double faultでpanicするようになってしまったので調査。
とはいってもdouble faultの原因リストなんて知らないので、ここはメモリ破壊系バグによる誤動作に賭けて調査開始。

……といっても、これまた調査方法を知らない。ユーザランドならvalgrindなどの強力なツールがあるけど、kernelだとどうなのか。
まずたどり着いたのはRedZone。

redzone (FreeBSD Man Pages)

カーネルのビルド設定に、options DEBUG_REDZONEを加えてあげればよい模様。
あとは動作としてsysctlでvm.redzone.panicvm.redzone.extra_memが設定可能。前者は見たまま(default: off)、後者は検出用の領域サイズであろうか。(※1)

※1 vm.redzone.extra_memはデフォルトが記されていないが、テスト環境では7206336(7.2MBくらい)だった。当初想定した”mallocした領域の前後につける緩衝領域”とは少し違うのかもしれない。
まあ、ページサイズより大きい分には空の仮想メモリを割り当てればいいから、MB単位だとどうでもいいのかもしれないが。

さて、これでダメだったので、次はmemguardを使ってみる。

memguard(9) (FreeBSD Man Pages)

同じくoptions DEBUG_MEMGUARDを入れてやる。
こっちはuma_zallocで確保した領域もチェックしてくれるらしい。今回はnamei_zoneが怪しいので対象にしてみる。
namei zoneは使うときにnamei_zoneと指定するので、その初期化を探して、
/usr/src/sys/kern/vfs_lookup.c:

namei_zone = uma_zcreate("NAMEI", MAXPATHLEN, 

から、名前は”NAMEI”と分かるので、sysctl -w vm.memguard.desc=NAMEIと指定する。
いきなり起動時に指定してbootできなくなると困るけど、後から指定するとチェックしてくれない領域が生じるので、一回sysctlで書き換えてテストしてから、/boot/loader.confに書いてテストする。

最終的にこっちでも引っかからず、原因不明。
困った。

WITNESSとdouble fault

$
0
0

昨日散々悩まされた件、もしやと思ってWITNESSを切ったら起きなくなった。
これはWITNESSによる負荷やタイミングのずれが原因と見るべきか、それともWITNESSがバグっているのか……。
検証してみたいけど、今その元気は無い。

SAN付きSSL証明書を作る

$
0
0

サーバが複数の名前を持つときに使いたい、SSL証明書のSAN(Subject Alternative Name)。
どこを見ても微妙に気に入らなかったので自分流に。

まずはCSRを作る用のopenssl.conf。
req_extensionsの指すセクションで、subjectAltNameを定義する。
環境変数で、OPENSSL_SAN=DNS:ldap.local,DNS:server1.ldap.local とか指定して使う。
違うSANで発行するためにconfigをいじらなくて良いのが重要。

openssl-req.conf:

prompt = no
string_mask = nombstr

[req]
policy = req_policy
distinguished_name = req_distinguished_name
req_extensions = v3_req

[req_policy]
localityName = optional
organizationalUnitName = optional
emailAddress = optional

[req_distinguished_name]
countryName = "JP"
stateOrProvinceName = "N/A"
#localityName = ""
0.organizationName = "my organization"
#organizationalUnitName = ""
commonName = $ENV::OPENSSL_CN
emailAddress = $ENV::OPENSSL_EMAIL

[v3_req]
subjectAltName = $ENV::OPENSSL_SAN

これでCSRにSANが組み込まれた。
あとはCA側で、CSRに書かれているSANを使うようにする。

CA側で同じようにsubjectAltNameを環境変数から取らせる(同じ値を与える)ことでもできるが、非常に気に食わないので採用しない。

さて、非常に悲しいことに、CSRに書かれたSANだけを証明書に写すという設定は無く、CSRのextensionsを丸ごと信用してくっつける設定しかない。
自分が発行者(CA)かつ依頼者(CSR作成者)ならよいが、少しでも “ちゃんとした” CAを運用するならこれまで以上にきちんとチェックせねばならない。(元々CNも含めてチェックしないといけないが。)

こちらは長いので要点だけ。

openssl-ca.conf:

[ca]
default_ca = CA_default

[CA_default]
# ... snip ...

# Extension copying option: use with caution.
copy_extensions = copy
Viewing all 62 articles
Browse latest View live