Chienomi

ReadyNASのトラブルと、その中身に踏み込む

Live With Linux::server

本記事はもとは、NetGearのNAS、ReadyNASのトラブルシューティング記事であった。 Btrfsのスナップショット転送中にiSCSIが切れてしまうという問題が発生し、その問題に対処したことを記録しようと思ったのだが、後述するように同じ問題を過去に記事にしていた。 そのため、記述に価値が成り立っていなかったため、従来より踏み込んだReadyNAS(部分的にLinuxサーバー)の扱いに関する話をする。

既にNetGearはNASから撤退しているため有用ではないかもしれないが、誰かの役に立つことを信じて。

ReadyNASとは

ReadyNASはNetGearが展開していたNAS製品である。

なぜかGoogleからはReadyNASの情報が除外されており、1400000件のヒットがあったとしながら、50ページしか表示されない。 探せば、まだある程度製品を買うことができる。だが、もう現実的な選択とは言えないだろう。

ReadyNASはBtrfsを採用する。 SynologyがBtrfs, QNAPがExt4であるということは参考になる情報だろう。

OSはLinuxであり、DebianをベースにNASシステムに仕上げている。

NTT-X StoreがNetGear製品を推しており、ReadyNASも積極的に取り扱っていた。 このためある程度人気はあったが、Synologyと比べると「落ちる」イメージがついて回ったようだ。

前提状況

ReadyNAS1には8台のディスクがあり、別のストレージサーバーにそのバックアップとして4台のディスクがある。 全体のストレージ構成はそれ以上に存在するが、完全に切り離せるようにしているためこれだけにフォーカスすれば良い。

今回、ReadyNASのディスクの更新と、ストレージサーバーの拡大を行う。これによって

  • ReadyNAS上のデータにはアクセスできない
  • ストレージサーバーは起動できないが、ディスクは利用できる

という状態になる。

そこで、ReadyNASの現在のディスクは予備として保管し、ReadyNASには新しいディスクを装填する。 一方、新しいサーバーに従来のストレージサーバーのディスクを接続し、このバックアップからReadyNASにデータを転送する。

新しいサーバーがReadyNASのディスクをiSCSIでマウントし、btrfs sendならびにbtrfs receiveを実行して転送を実施する。

問題を認識する

btrfs send並びにbtrfs receiveはひとつのジョブとして実行しているが、これが書き込み失敗となってステータス1で終了している。 画面上にはファイルが書き込めなかったこと、そして書き込めなかった理由はread only filesystemであることが示されている。

Btrfsは書き込みに失敗する状況が続くとデフォルトでリードオンリーでremountする。

journalctl --boot 0によって状況を確認すると、どうもiSCSIが切断された状況であることが分かる。

ただし、切断されたままになっているわけではないことは、リードオンリーでアクセスできていることから分かる。

とりあえず再試行してみたが、やはり2日ほど経った後に失敗した。

そのため、発生する必然性があるのだと判断した。この状態ではサーバーとReadyNASどちらに問題があるのかはっきりしない。 そこで、ReadyNASについても調査することにした。

NASは一般的にLinuxまたはFreeBSDが使われているが、ReadyNASはLinuxを採用している。 これはファイルシステムがBtrfsであることから簡単に判別できるだろう。 このため、Linuxの操作が効く。

だがLinuxとして操作するためにはシェルが必要だ。 ReadyNASはオフィシャルにSSHアクセスを可能にしているが、SSHアクセスを行うと保証しない旨告げられる。 このSSHアクセスはrsyncやSFTP向けに開放しているというのが主なところであるようだが、シェルアクセスも行うことができる。

まずはSSHを有効にする。

SSHの有効化

次にユーザーアカウントを追加する。 adminアカウントでもアクセスできるが、避けたほうが良いだろう。 注意点として、ユーザーアカウントの設定を更新するとき、パスワードをそのままにしているとパスワードが短縮されてしまうため、パスワードは毎回入力する必要がある。

また、なぜかパスワードに記号を入れると単純すぎると警告される。 記号を入れなければ警告されないが、記号を入れてもちゃんと問題なく動作する。

記号を入れると警告が出る

アカウントの追加ができたらSSHアクセス、そしてシェルアクセスを有効にする。 パスワードは入れておく必要があるが、パスワード認証は許容しないようにする。

ユーザーSSHの設定

ここで公開鍵の登録が可能だ。ReadyNAS OS 6.10.7のOpenSSHは〜で、ECDSA鍵の利用が可能である。

登録が終わったら例えば次のようにしてSSHログインを行う。

$ ssh -i ~/.ssh/readynas_ecdsa foouser@192.168.10.2

ReadyNASはシェル環境が整備されておらず、メンテナンスしづらい。

ReadyNAS OSはSystemdを導入している環境であるため、journalctl --boot 0としてログの確認が可能。 前回起動時のログであればjournalctl --boot -1になる。

ReadyNAS側にエラーが確認できるため、問題の原因はReadyNAS側にあるとみなすことができる。 サーバー(クライアント)側が接続を失ったといった問題であれば、ReadyNAS側に大きな問題として記録されることはないからだ。ReadyNAS側にこうして問題が記録されるということは、ReadyNASに問題が生じたために処理がエラーとなったと見るのが妥当ということになる。

実際の問題

どうもopen-iscsiとLinuxカーネルの間の問題らしく、Linux 3.19から問題が発生していたらしい。 検索するとQNAPSynologyでも報告されている。

結論としてはecho 4092 > /sys/block/$disk/queue/max_sectors_kbとすることで安定しそうだという話で、そういえばすごく前にそんな感じの処理を入れていた記憶がある。 と思って調べたら同じ問題を過去に記録していた。

完全に忘れていた… 覚えていれば今回の手間はかからなかったと思うのだが。

swap

ReadyNAS 528は4GBのメモリを搭載するが、Btrfsの処理を行う上でちょっと苦しい面があるようだ。 BtrfsはZFSほどではないが多くのメモリを必要とするファイルシステムで、可能ならばメモリはもっと多いほうが良い。 (特に有効性はないとは思うが。)

ReadyNAS自身のディスクは4GBしかないようだ。 かといってストレージ上に色々と置いているわけでもないが。

例えばGlobalVolというボリュームを作成し、LUNとしてiGlobalLUNを作成したとする。 すると、ボリュームは/GlobalVolにマウントされ、ファイルシステムはBtrfsでフォーマットされる。 LUNはthickかthinかは作成時にどうしたかによるが、/GlobalVol/iGlobalLUNの形でファイルとして確保されている。

Btrfs上に巨大なループバックデバイス用のファイルを確保する。 …ちょっと抵抗のある形だ。パフォーマンス的にも褒められたものではないだろう。 私の場合Btrfsを使っているから、Btrfs上の巨大なファイルにBtrfsが組まれている状態ということになる。

Btrfs上に直接スワップファイルを置くことはできない。 そのため、まずはファイルを作る。

# dd if=/dev/zero of=/GlobalVol/swapfile.img bs=4M count=4096

これをループバックデバイスにする。

# losetup /dev/loop2 /GlobalVol/swapfile.img

スワップとしてファーマットし

# mkswap /dev/loop2

有効化する

# swapon /dev/loop2

もっと思い切った方法

Btrfsを使う前提でBtrfsのドライブをReadyNASに任せるのであれば、そもそもiSCSIを使わない方法が通用する。 SSHアクセスができる仕組みであるため、SSHFSでマウントすればよく、snapshotやsend/receiveなどはReadyNAS自身が取り扱うようにすれば良い。

この場合のメリット

  • Btrfsをネストさせたり、巨大なファイルを設置する必要がない
  • 何かしらのマシンでiSCSIマウントした上で利用することなく、直接SSHFSで扱える
  • ボリュームサイズ90%の制限にひっかからないため、ディスクをフルに使える

デメリット

  • BtrfsボリュームがNAS 1台に完結してしまう
  • Btrfsの重い処理もRaedyNASが行うことになる
  • ユーザー管理がReadyNASで独立したものになり、アンマッチになりやすい
  • Btrfsの細かいオプション設定などができない
  • 使えるBtrfsが古い

ReadyNASクラッシュ時にBtrfsボリュームを救出可能かどうか? という点にも疑問が残る。 ReadyNASがクラッシュするとNASがブートできなくなる。ディスクを取り出してデータにアクセスできなければ救出できない。

メリット、デメリットともに大きい印象だ。

判断の分かれ目は、NAS 1台で完結するかどうかにあるだろう。 balanceなどの重い処理をReadyNASにやらせるのは躊躇われるが、ReadyNASはそもそもrebalanceするような構成変更ができない。

その方法は非常にシンプルで、NASに何らかの方法でファイルを配置していくだけだ。

ReadyNASがマスター側である場合、スナップショットはReadyNASの設定によってスケジュール設定可能だ。

ReadyNASがバックアップ側である場合、ReadyNASにSSHログインし、

btrfs send foosnapshot | socat -u STDIN TCP-LISTEN:20000

のように待機したホストに対して、ReadyNASのrootユーザーで

btrfs receive /FooVolume < /dev/tcp/foohost/20000

のようにして受け取る。 なお、逆にReadyNASのスナップショットを転送する場合も同じ方法が使える。

ReadyNAS同士であれば、別のサーバーで

socat -u TCP-LISTEN:20000 TCP-LISTEN:20001

のようにして中継することもできる。 ReadyNASにはsocatやnetcatがないため、中継なしに行うのは少し難しい。

なお、これとは別の方法として、ReadyNASにログインした上でiSCSIの設定を行えば、md-raidブロックデバイスそのものをiSCSIで提供することもできる。 ReadyNASの保証対象外になってしまうが、そうした方法まで含めるなら、ReadyNASのメニューからiSCSIを設定するよりも良いだろう。

HDD書き込みをシーケンシャルライトに限る

概念と手法

HDDは物理的にデータは連続性が保たれるのが望ましい。言い換えると、できる限り書き込みをシーケンシャルに行いたい。

複数の書き込みを並列で行わなければできそうに思えるが、実際は意図せず書かれる状況があるため、思ったほどうまくいかない。

HDDに置きたいデータを並列に処理する状況は普通に考えられる。 例えばビデオエンコーディングは最終的に大きなデータを生成するが、並列処理を縛られるのは処理効率に関わってくる。 また、ダウンロードなどで同様の問題がある。

そこで、まずSSDキャッシュを用意し、HDDに書くデータをSSD上に構成し、これをコピーすることでシーケンシャルにできる。 SSDは連続性のない記録の影響が少なく、大きなデータを繰り返し書くことでSSDの寿命に関する問題はあるが、実際の問題の度合いとしてはメリットが上回る。

だが、普通にマウントするとランダムにかかれてしまうことがあるだろう。 例えばサムネイルを同一ディレクトリ上に書いてしまうアプリなどが考えられる。

これを厳密に制御するため、HDD上のデータをroot:root持ちにする。 これにより、通常データを利用する一般ユーザーはそもそもHDD上にデータを書くことが許されないため、HDDに書かれる状況が一気に限定的になる。 rootによるデスクトップログインをするようなケースを除けば、rootによるHDDアクセスさせないのは難しいことではない。 TrackerやBalooのようなインデクサを無効にする、あるいは除外するだけでも十分だろう。

こうすれば意図しないwriteを避けることができるが、今度は意図したwriteができなくなってしまう。 同一マシン上での話であれば問題ないが、ReadyNASで直接Btrfsを扱っている場合、ReadyNASのrootアカウントでwriteを行う必要があり、rootログインを許さないままだとなかなか難しい。

場合によってはinternal-sftpを許すことで限定的に利用できそうに見えるが、実際はrootでストレージのルートに対してSFTPアクセスを許すのはやりすぎである。そこで比較的使いやすい方法がrrsyncだ。

rrsyncはrsyncのラッパースクリプトであり、SSH key commandとして使われることを想定している。 rrynsc自体はrsyncに同梱されており、Arch Linux (Manjaro Linux)の場合、/usr/lib/rsync/rrsyncとして存在している。

例えば

command="/usr/lib/rsync/rrsync -wo /mnt" ssh-ed25519 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA haruka@chienomi

というエントリを作ったとする。対応するエントリを~/.ssh/configに記載し

Host NAS
  HostName nas.local
  User root
  IdentityFile ~/.ssh/nas-rrsync_ed25519

次のようにコマンドを実行したとする

rsync foofile NAS:.

するとfoofileはNAS上の/mnt/foofileとしてコピーされる。 また、

rsync foofile NAS:/

とした場合でも同様に/mnt/foofileとしてコピーされる。つまり、Chrootしているかのような動作になる。 rrsyncを使う場合、パスに..を使うことはできなくなる。本当にChrootしているわけではなく、パスを書き換えることによって実現しているのだが、SSH Key commandを迂回して他のことを実行することはできないため、(rrsyncにバグがない限りは)rrsyncで指定されたサブディレクトリの下に対してしか書くことができない。

基本的なやり方としては、SSD上でHDDに書き込みたいデータをアッセンブルし、これをrsync -rvuなどの形でまとめて転送し、転送後rm -rfなどで削除する。 rmコマンドを打つ頻度が高くなるため注意が必要。場合によっては関数にしておくなどして間違いのないようにする必要があるだろう。

CLIで辛い部分のカバー

rsyncに限定されるため、Nemoでドラッグアンドドロップといったことはできなくなる。 不便だが、繰り返し行うディレクトリはNemo Actionsなどでできるようにしておくと気にならないだろう。 コピー先を間違えないようにタイピングするには、予めsshで入っておき、destinationディレクトリに移動した上でpwdしてコピペするのが確実だ。

この運用は私の中でも経験が浅いが、使っていて気になる問題を軽減するためのものをNAS Utilsとして公開している。

nas-renameシリーズはNemo上で行いたいような手作業リネームのためのユーティリティである。 ゲームプレイ動画はタグ付け(例えば「XXXクリア」)をファイル名に付加しているのだが、これは処理前に必ずしもできるとは限らないため、変換後に行いたかったりする。 nas-rename-gen.rbはファイル名のリストをYAMLで出力する。このリストを編集し、nas-rename-do.rbに食わせるとリネームしてくれる。 かなり狭い目的のために作ったものだが、使いどころは割とありそう。バルクリネーマーと違うのはタグ付けは手動で行わなくてはならないので、それをできるだけ簡略化していることだ。

encfs-filename-shoten.rbはEncFSに適合するようにファイルネームを短縮するものだ。 基本的にfindのパイプで使う。

現実的な手法か

「使いにくいのではないか?」と思うかもしれないが、「現状」を考えれば利益が上回る。

私がこのシステムを組んだとき、まだSSDはSLCかMLCかと言っているような時期で、容量は大きくて256GB、それで2万円くらいはした。 HDDのほうは3TBや4TBが普通だったので、容量の差が非常に大きかった。

当時でも256GBというのはデータを保存するには小さすぎるので、システムにSSD、データにHDDという使い方しかやりようがなかった。 検討の余地もなく、HDD上のデータを直接編集するしかないので、このような手法を取るのはあまりに現実的でなかった。

現在、SSDは8TBまで存在する。だいたい10万円くらいで、容量単価は¥12.5/GBである。 1TB, 2TBあたりの容量単価は¥10/GBくらいで、4TBだと¥11/GBくらいなので、めちゃくちゃ高いというわけでもない。 そして、少なくとも2TBあたりまでは割高ではない(純粋に高くはあるが)。

経験的に言えば、データアクセスには強い局所性があり、データ容量が増えるほどに局所性は強まる。総データ量48TBに対して2TBのストレージはホットなデータに対して十分とは言わないまでも運用可能な容量である。 つまり、よく使うデータを手元に置けば普段NASを起動しないような運用が現実的にできるということだち。

さらに頻繁に書き換えられるホットなデータに限るとすれば、2TBは十分すぎるほどに大きいと言える。 これによってSSDを

  • 書き換え頻度の高いライブなデータ
  • アクセス頻度が非常に高いホットなデータ
  • HDDへ書き込む前の一時的な書き込みバッファ

として使えば2TBのSSDでカバーできる。 ホットなデータは読み出しであるからこの運用でも特に問題なくNASで扱うこともでき、ライブなデータとバッファとして考えればSSDは余裕をもった容量を確保できる。

この運用においてそもそもライブなデータはNASに書き込まない。複数のPCがそれぞれにライブなデータを共有すれば良い。 それは、GitやMercurialを使ってもいいし、クラウドドライブを使ってもいい。 そのため、ライブなデータの扱いづらさについて悩む必要はない。

問題はダウンロードしてファイル名を調整してディレクトリ構成を整えて、といった作業だが、これはそもそもランダムライトになってしまうものであり、こうした作業はSSD上でやってしまえば良い。そして、最終的な形に仕上がったらNASにまとめて転送すれば良いのだ。

こうしたやり方が現実的にできるようになったのは、(それなりにコストはかかるが)1TB, 2TBのSSDを各PCに搭載するようなことが現実的に可能になったからだ。 また、ファイルの模様替えを行う場合はなかなか大変になってしまうので、8年やって構成や運用がだいぶ枯れているというのも大きい。3年前にDegraded Storageを組んだときに従来の反省点を踏まえてディレクトリ構成を再編しており、この再編作業自体もその前から2年ほどかけている。

こうした事情があって、「私の環境では」メリットが先行する手法となっており、今回採用となった。

難しいのはEncFSである。 EncFSへのアクセスはEncFSをマウントしたユーザーに限られる。つまり、EncFSへ書き込むためにはrootでアクセスする必要がある。

つまりrootでのSFTPアクセスを許可する必要があるということになるのだが、まぁそこは厳密な鍵管理のもと許可したとしよう。これによってEncFSでマウントしアクセスすることができるし、実際これで書けるのだが、いきなりI/Oを発行せず権限チェックを実施する場合、root所有の(書き込み権限のない)ファイルに書こうとしているように見えるため、止められてしまう。 例えばNemoによるドラッグアンドドロップなどはできない。

これが問題なのは、ReadyNASでEncFSが使えないため、rrsyncなどで書き込むことができないからだ。

このため、EncFS上の編集操作に関しては、rootでReadyNASのrootとしてSSHFSでマウントする必要がある。 なお、rsyncはこのようなチェックを行わないため、単にバルクで書きたいだけであれば一般ユーザーにReadyNASのrootの鍵をもたせておけば良い。

もっとも、LUKSデバイス上のファイルシステムにEncFSを構築する暗号化ネストを必要とする人はごく少数であろう。

inside of ReadyNAS

ReadyNASはDebianベースのLinuxシステムである。 Debianよりも保守はいい加減である。

既に販売は終了しているが、2022年3月現在、まだ保守されている。

ReadyNASの中核システムはreadynasdというプログラムである。ELFバイナリであり、中身はわからない。 SSHでログインできる場合、起動後にreadynasdを終了させても問題ない。

readynasdreadynasd -v 3 -tというオプションで起動される。 -vがログレベルであり、journalに書き出すログがコントロールされる。ただし、/usr/lib/systemd/system/readynasd.serviceを編集してreadynasd -v 0 -tに変更したとしても、ReadyNAS上でのログ出力を抑制することはできない。

ReadyNASのウェブインターフェイスを提供するウェブサーバーはApacheである。

ReadyNAS自体のディスクは4GBほどで、これがシステム領域になっている。 それとは別にすべてのディスクに3つのパーティションを切り、3つのdm-raid(md)デバイスを形成する。 1つ目がReadyNASのシステム用、2つ目がswap、3つ目がデータ用である。

ボリュームの暗号化した場合、3つ目のdm-raidデバイスに対してLUKS暗号化を行う。

1つ目と3つ目のdm-raidデバイス(あるいは、3つ目のdm-raidデバイス上のdm-cryptデバイス)はBtrfsでフォーマットされる。単一のdm-raidデバイスとして構成されているため、meta single/data singleである。

ReadyNASのメニューで作成したボリュームは/<VolumeName>としてマウントされる。これはルートボリュームである。 ルートボリュームには

  • .apps
  • .purge
  • .timemachine
  • .vault
  • ._share
  • home

の6つのサブボリュームが作られる。さらなるサブボリュームを作ることは可能である。 ルートボリュームのマウントは/etc/fstabで処理されており、この後であればfstabへの記載でサブボリュームのマウントも可能である。 それぞれのサブボリュームもマウントされる

/dev/mapper/HyMaster-0 on /HyMaster type btrfs (rw,noatime,nodiratime,nospace_cache,subvolid=5,subvol=/)
/dev/mapper/HyMaster-0 on /apps type btrfs (rw,noatime,nodiratime,nospace_cache,subvolid=259,subvol=/.apps)
/dev/mapper/HyMaster-0 on /home type btrfs (rw,noatime,nodiratime,nospace_cache,subvolid=260,subvol=/home)
/dev/mapper/HyMaster-0 on /run/nfs4/home type btrfs (rw,noatime,nodiratime,nospace_cache,subvolid=260,subvol=/home)

が、これらはfstabにエントリがない。少なくともhomeappsに関しては.mountユニットになっている。 マウントオプションは見ての通りrw,noatime,nodiratime,nospace_cacheである。

ReadyNASのOpenSSHのバージョンはOpenSSH_6.7p1-hpn14v5 Debian-5+deb8u7.netgear1, OpenSSL 1.0.1t 3 May 2016であり、ED25519鍵を受け入れる(ED25519鍵のサポートはOpenSSG 6.5から)。ホスト鍵はECDSAである。 ユニットはsshd.serviceではなくssh.serviceとなっている。

何らかのタイミングで

Mar 06 04:28:46 serruria readynasd[4588]: Volume HyMaster health changed from Redundant to Inactive.
Mar 06 04:28:56 serruria readynasd[4588]: Volume HyMaster health changed from Inactive to Redundant.

というようなログがあふれる。 メールがあふれる問題はメールを送る閾値を警告以上にすることで抑制でき、journalに関してはreadynasd -v 2 -tで起動するようにすれば抑制できるが、前述の通りreadynasdそのものが吐くことは止められない。妥当なのは起動後readynasdを止めてしまうことだが、そうすると今度はアラート制御はできなくなる。 なお、このように大量に出力されていても特に動作に問題があるわけではない。

Vimとlessがないのでメンテナンスはかなりやりづらい。 Zshと併せてこれらはapt-getによってインストール可能である。これだけでも相当楽になる。journalをmoreで見るのは結構きつい。 なお、Vim-tinyとBusybox lessであるためフル機能ではない。

アンチウィルスはclamAVである。

ReadyDLNAの中身はminidlnaである。

adminというユーザーはウェブインターフェイス提示の通り98のユーザーとして存在する。 rootのパスフレーズはadminに揃えられるようになっている。