FreeNASのzfs環境でHDD交換したメモ

FreeNASで設定したzfs環境用のHDD交換方法のメモとなります。
なおCUIによる手順となっています。

# 環境
このメモは以下の環境を前提としています。

- FreeNAS 8.3.2利用
- USBメモリーにFreeNASのOSがインストールされており、そこから起動
- HDD4本を使ってraidz2(RAID6)構築済
- [GPT](http://e-words.jp/w/GPT.html)利用

# ことの始まり
HDDの1本でエラーが出始めた
　↓
ある日曜日、前回zpool scrabから35日以上経過していたので、zpool scrabが自動的に動いた
　↓
OS側で自動的にディスクが切り離された
　↓
zfsから該当HDDがUNAVAILとなった

```lang:問題部分を抜粋
# zpool status
  pool: tank
 state: DEGRADED
(略)
config:

	NAME                             STATE     READ WRITE CKSUM
	tank                             DEGRADED     0     0     0
	  raidz2-0                       DEGRADED     0     0     0
(略)
	    10284868363385756633         UNAVAIL      0     0     0  was /dev/gptid/46b7e268-9176-11e2-83a7-7054d244c94e

errors: No known data errors
#
```

# 交換準備
dmesgコマンドを実行して、交換するHDDとパーティション情報を確認しておきます。
コマンドの結果からada1というHDDがOSから切り離されているので、これが故障したHDDなことがわかります。

```lang:dmesgの結果
### あらかじめFreeNASサーバにSSHでログインしておく
% dmesg
(ada1:ahcich2:0:0:0): lost device
ahcich2: AHCI reset: device not ready after 31000ms (tfd = 00000080)
ahcich2: Poll timeout on slot 7 port 0
ahcich2: is 00000000 cs 00000080 ss 00000000 rs 00000080 tfd 80 serr 00000000 cmd 0004c717
ahcich2: Poll timeout on slot 7 port 0
ahcich2: is 00000000 cs 00000080 ss 00000000 rs 00000080 tfd 80 serr 00000000 cmd 0004c717
(ada1:ahcich2:0:0:0): removing device entry
Closed disk ada1 -> 6
```

## アクセスランプ点滅しているHDDを確認
今回の作業では、以下の赤枠のように1本だけHDDアクセスランプが点滅していないものがありました。これが今回交換するada1のHDDのようです。
![01.png](https://qiita-image-store.s3.amazonaws.com/0/77532/94055634-56c6-51a6-5460-5d52d18da2be.png)

## シリアル番号確認
上記の確認だけでなく、念のためHDDのシリアル番号も確認して、抜いたHDDが本当に故障しているものかを調べておきます。なおすでにHDDが見えなくなっているので、**どのHDDを交換してはいけないのか？**を確認します。

```lang:利用するコマンド
# camcontrol identify {HDD名}
```

```lang:正常なHDDの場合(例)
% su -
### 以下からrootで作業
# camcontrol identify ada0
(略)
firmware revision     CN01
serial number         ????????      # ←正常なディスクすべてでこの値をメモしておく
(以下略)
```

```lang:交換するHDD(以下のようなエラー出力)
### rootで作業
# camcontrol identify ada1
camcontrol: cam_lookup_pass: CAMGETPASSTHRU ioctl failed
cam_lookup_pass: No such file or directory
cam_lookup_pass: either the pass driver isn't in your kernel
cam_lookup_pass: or ada1 doesn't exist
(以下略)
```
##パーティション情報取得
念のため、電源OFF前に事前にパーティション情報を取得します。

```lang:利用するコマンド
# gpart show {HDD名}
```
```lang:パーティーション情報取得(例)
# gpart show ada0
=>        34  3907029101  ada0  GPT  (1.8T)
          34          94        - free -  (47k)
         128     4194304     1  freebsd-swap  (2.0G)
     4194432  3902834696     2  freebsd-zfs  (1.8T)
  3907029128           7        - free -  (3.5k)
#
```

# ディスク交換
## 本体シャットダウン

```lang:
### rootで作業
# shutdown -p now
```
## 故障したHDDを取り出してシリアル番号確認
壊れたHDDを取り出します。
その後、以下のシリアル番号がすべて異なることを確認します。

* あらかじめメモしておいたシリアル番号
* 取り出したHDDに記載されたシリアル番号

もし一致したら、見なかったことにしてそのまま元の位置にHDDを戻しましょう（笑）

# 本体起動
HDD交換後に本体の電源をONにして本体を起動します。正常に起動することをお祈りしましょう（笑）
なおzfsではHDD交換しただけでは自動的にRAID再構築が始まらないため、続けて以下の作業を行っていきます。

# 交換したHDDへのGPTスキーマ作成とパーティション作成
起動後にFreeNASサーバにログインして、パーティションを作成します。
なお元々GPTを利用していたため、GPTスキーマを作成してからパーティション作成します。

```lang:
### 以下からはrootで作業します
### GPTスキーマを作成する
# gpart create -s gpt ada1
ada1 created
### 確認
# gpart show ada1      # GPT化していることを確認
=>        34  3907029101  ada1  GPT  (1.8T)
          34  3907029101        - free -  (1.8T)
```

電源OFF前に取得したパーティション情報を利用してパーティションを作成します。

```lang:gpartでのパーティション作成方法
# gpart add -i {index番号} -t {ファイルシステムタイプ} -b {スタート位置} -s {サイズ} ada1
### -bオプションはfreebsd-swapのみで利用
```

```lang:パーティション作成方法
### 以下のようにパーティションを作る
# gpart show ada0
=>        34  3907029101  ada0  GPT  (1.8T)
          34          94        - free -  (47k)
         128     4194304     1  freebsd-swap  (2.0G)
     4194432  3902834696     2  freebsd-zfs  (1.8T)
  3907029128           7        - free -  (3.5k)
### swap領域作成
# gpart add -i 1 -t freebsd-swap -b 128 -s 4194304 ada1
ada1p1 added
### zfs領域作成
# gpart add -i 2 -t freebsd-zfs -s 3902834696 ada1
ada1p2 added

### 作成したパーティション確認
# gpart show ada1
=>        34  3907029101  ada1  GPT  (1.8T)
          34          94        - free -  (47k)
         128     4194304     1  freebsd-swap  (2.0G)
     4194432  3902834696     2  freebsd-zfs  (1.8T)
  3907029128           7        - free -  (3.5k)
### 他のディスクの情報
# gpart show ada0
=>        34  3907029101  ada0  GPT  (1.8T)
          34          94        - free -  (47k)
         128     4194304     1  freebsd-swap  (2.0G)
     4194432  3902834696     2  freebsd-zfs  (1.8T)
  3907029128           7        - free -  (3.5k)
#
### ada1とada0で値が一致している！（問題なし）
```

# rawuuid値の確認とディスク交換用コマンドの実行

```
# gpart list ada1
Geom name: ada1
modified: false
state: OK
fwheads: 16
fwsectors: 63
last: 3907029134
first: 34
entries: 128
scheme: GPT
Providers:
1. Name: ada1p1
(略)
   rawuuid: 58e6ad2b-5e8e-11e5-a197-7054d244c94e     # ←こっちはswapのなので無視
(略)
2. Name: ada1p2
(略)
   rawuuid: f5e5af6c-5e8e-11e5-a197-7054d244c94e     # ←こっちをメモ
(略)
#
```
先ほどメモしたrawuuid値を利用して、新しいHDDのzfs領域のキャラクタ・デバイスができているかを確認します。

```
# ls -la /dev/gptid/f5e5af6c-5e8e-11e5-a197-7054d244c94e
crw-r-----  1 root  operator    0, 140 Sep 19 14:26 /dev/gptid/f5e5af6c-5e8e-11e5-a197-7054d244c94e
###デバイスができているので問題なし
```

ディスク交換のコマンドを実行します。

```lang:使い方
zpool replaece {プール名} {zfs上の壊れたHDD} {zfs上の新しいHDD}
```

```lang:実行例
# zpool replaece tank 10284868363385756633 gptid/f5e5af6c-5e8e-11e5-a197-7054d244c94e
#
```
RAID再構成が行われていることを確認します。


```
# zpool status
  pool: tank
 state: DEGRADED
(略)
config:

	NAME                                              STATE     READ WRITE CKSUM
	  raidz2-0                                        DEGRADED     0     0     0
	    replacing-2                                   UNAVAIL      0     0     0
	      10284868363385756633                        UNAVAIL      0     0     0  was /dev/gptid/46b7e268-9176-11e2-83a7-7054d244c94e
	      gptid/f5e5af6c-5e8e-11e5-a197-7054d244c94e  ONLINE       0     0     0  (resilvering)    # ←"resilvering"と出ていればOK

errors: No known data errors
#
```
このまま待てば再構成は終わるので、作業完了となります。

# おまけ
　今回の作業を通じて初めて知ったのですが、FreeNASをUSBメモリーにインストールすると、2GBのswap領域をHDD上に取ります。swapだから自由に読み書きできるそれなりの広い領域が必要なのでHDD上に取るのは当たり前の話ですが、これも今回の学びでした。

　またWebGUIにアクセスしたら、/var/log/messagesに以下のようなログが出力されました。

```
swap_pager: I/O error - pagein failed; blkno 75,size 45056, error 6
vm_fault: pager read error, pid 2054 (python)
```

この内容を踏まえると、

* 今回のHDD障害はzfs領域ではなくてswap領域上で発生
* swap領域は冗長化されていない

ということが言えそうです。

USBメモリーにFreeNASのOSを入れていても、swap領域はHDDにあることと冗長化の対象外であることに気をつける必要がありそうです。

# たわ言
　このページに書いたお話は、専門の保守業者を頼れるなら業者に任せることで解決するため、そういう人はそもそもこの資料は読む必要がありません。

　また、AWSやSalesForceのようなパブリッククラウドしか知らない人は今後ますます増えてくるため、こうした話は程なく過去の話になるでしょう。

　その結果、HDDが壊れた時にこうした作業の存在を知るITエンジニアは今後ますます減るわけですが、ファイルサーバのHDDの交換は失敗すると最悪データがすべて消えてしまうという影響の大きいものです。そのため需要は少なくても、誰かのために役立てられるよう忘れないうちに作業記録をメモとしてまとめました。

#たわ言（その２）
　今回作業したNAS、HDDケースと本体に貼ってある番号は左から0,1,2,3なのに、adaの番号は左から3,2,1,0と逆なことがわかりました（笑）

　アクセスランプが消えていたから抜くHDDを間違える可能性は低いと思っていましたが、ちゃんとHDDのシリアル番号も確認しないと危険なようです。