はじめに
オンプレミスKubernetesで運用しているRook/Cephに接続しているHDDをsmartctlで確認したところ問題がありそうだったので、予防的にHDDを交換することにしました。
後日談として、突然にHDDがクラッシュしてしまった際の対応についてまとめています。
環境
次のようなバージョンで稼動している合計5ノードによるk8sクラスターを運用しています。
- Rook/Ceph v1.5.12
- Kubernetes v1.21.6
- Ubuntu 20.04.5
- OSDを構成しているHDD - /dev/sda, 4TB
- Host: Fujitsu TX1320 M4 (CPU: Xeon E-2234, Memory: 64GB)
今回のターゲットにしているHDDのもう少し詳しいデータは次のようになっています。
$ sudo smartctl -a /dev/sda
smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.4.0-126-generic] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF INFORMATION SECTION ===
Model Family: HGST Deskstar NAS
Device Model: HGST HDN726040ALE614
Serial Number:
LU WWN Device Id:
Firmware Version: APGNW7JH
User Capacity: 4,000,787,030,016 bytes [4.00 TB]
Sector Sizes: 512 bytes logical, 4096 bytes physical
Rotation Rate: 7200 rpm
Form Factor: 3.5 inches
Device is: In smartctl database [for details use: -P show]
ATA Version is: ACS-2, ATA8-ACS T13/1699-D revision 4
SATA Version is: SATA 3.1, 6.0 Gb/s (current: 6.0 Gb/s)
Local Time is: Wed Feb 15 06:31:50 2023 UTC
SMART support is: Available - device has SMART capability.
SMART support is: Enabled
いまとなっては、SeagateのExosや、Western Digital の WD Gold か HGST/Ultrastar にしておかなかったことを少し後悔しています。最近構築したノードのHDDはWD GoldやUltrastarを導入しています。
予算の都合があったとはいえ、それなりの負荷をかける用途ではどのメーカーであってもフラッグシップモデルにしておくべきでした。
概要
smartctlでshortテストをしてみたところ少し問題があったので、Rook/CephのOSDから外して smartctl で再度テストを実施していきます。
$ sudo smartctl -l selftest /dev/sda
smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.4.0-126-generic] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Short offline Completed: servo/seek failure 70% 20319 0
# 2 Short offline Completed: servo/seek failure 60% 20318 0
# 3 Short offline Completed without error 00% 2166 -
#2の結果がRook/Cephのクラスターに含まれている時の最初のエラーで、#1がOSDから外して負荷を与えないようにして実施した最新の結果になっています。
"Remaining"の意味は残りのテストの内容になっているので、30〜40%程度のテストが進行した時点でエラーが発生していることが分かります。
"-H"オプションによる出力では、テスト結果はPASSEDになっています。
$ sudo smartctl -H /dev/sda
smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.4.0-126-generic] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED
PASSEDの判定基準は、"failing NOW"を含む結果がなければ全部PASSEDになるようなので、即時に対応が必要でなければ全てPASSED扱いになるようです。
とはいえ、servo/seekのエラーは致命的にもみえるので、Rook/CephのOSDから削除して、負荷を与えない状態にしてからlongテストを実施してみます。これには30分ほどの時間が予告されていましたが、実際にはすぐにエラーになって停止しています。
$ sudo smartctl -l selftest /dev/sda
smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.4.0-126-generic] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Extended offline Completed: servo/seek failure 90% 20319 0
# 2 Short offline Completed: servo/seek failure 70% 20319 0
# 3 Short offline Completed: servo/seek failure 60% 20318 0
# 4 Short offline Completed without error 00% 2166 -
この状態で交換する必要があるかは微妙です。Raw_Read_Error_Rate値やSeek_Error_Rate値などの各値に問題は確認できません。今回は様子をみるところかもしれませんが、作業手順を確保したい事と、ちょうどメモリ交換のためにクラスターを停止させる予定だったため、このタイミングで確保しておいた交換用のHGST Ultratarと交換することにします。
取り出したHDDは別のバックアップ取得用のNASに移して様子をみる予定です。
SMART Attributes Data Structure revision number: 16
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
1 Raw_Read_Error_Rate 0x000b 100 100 016 Pre-fail Always - 0
2 Throughput_Performance 0x0005 124 124 054 Pre-fail Offline - 162
3 Spin_Up_Time 0x0007 100 100 024 Pre-fail Always - 0
4 Start_Stop_Count 0x0012 100 100 000 Old_age Always - 192
5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail Always - 0
7 Seek_Error_Rate 0x000b 100 100 067 Pre-fail Always - 0
8 Seek_Time_Performance 0x0005 044 044 020 Pre-fail Offline - 39
9 Power_On_Hours 0x0012 098 098 000 Old_age Always - 20321
Rook/Ceph側の作業概要
Rook/Cephでディスクを交換する際には、下記の手順に従って実施しています。
実際に稼動しているシステムは、v1.5.12なので osd-purge.yaml のファイルは、rook/cluster/examples/kubernetes/ceph/osd-purge.yaml からコピーして変更後、実施しています。
--- rook/cluster/examples/kubernetes/ceph/osd-purge.yaml 2022-08-25 07:11:21.591632585 +0000
+++ osd-purge.yaml 2023-02-15 05:45:52.752190600 +0000
@@ -28,7 +28,7 @@
image: rook/ceph:v1.5.12
# TODO: Insert the OSD ID in the last parameter that is to be removed
# The OSD IDs are a comma-separated list. For example: "0" or "0,2".
- args: ["ceph", "osd", "remove", "--osd-ids", "<OSD-IDs>"]
+ args: ["ceph", "osd", "remove", "--osd-ids", "1"]
env:
- name: POD_NAMESPACE
valueFrom:
この状態では、しばらくrebalancingのためにステータスが HEALTH_WARN になるので、完了するまで暫く待ちます。
cluster:
id: 51464e80-fbf5-44cd-b033-a2e1374526cf
health: HEALTH_WARN
Degraded data redundancy: 3405010/19885929 objects degraded (17.123%), 34 pgs degraded, 34 pgs und
ersized
services:
mon: 3 daemons, quorum k,l,m (age 7w)
mgr: a(active, since 7w)
mds: myfs:1 {0=myfs-a=up:active} 1 up:standby-replay
osd: 4 osds: 4 up (since 97m), 4 in (since 91m); 34 remapped pgs
task status:
data:
pools: 4 pools, 97 pgs
objects: 6.63M objects, 164 GiB
usage: 1.4 TiB used, 13 TiB / 15 TiB avail
pgs: 3405010/19885929 objects degraded (17.123%)
203008/19885929 objects misplaced (1.021%)
63 active+clean
31 active+undersized+degraded+remapped+backfill_wait
3 active+undersized+degraded+remapped+backfilling
io:
client: 1.2 KiB/s rd, 26 KiB/s wr, 2 op/s rd, 2 op/s wr
recovery: 27 KiB/s, 24 objects/s
これが完了するまでは、operatorは起動しないままになっています。
$ sudo kubectl -n rook-ceph get deploy -l operator=rook
NAME READY UP-TO-DATE AVAILABLE AGE
rook-ceph-operator 0/0 0 0 2y21d
今後予定している作業
これから HEALTH_OK になってから、Diskを交換し、その後で、operatorを起動することで交換した新しいデイスクを認識させることになります。
その部分は後から追記します。
いまのところ、3%程度のreblancingのために12時間前後を必要としていて、2日以上の時間が経過しています。
HDDの交換
全体の rebalancing が完了するのに、約3日(72時間)かかりましたが、HEALTH_OK を確認してから、全部のノードを落とし、メモリを増やつつ、問題のあった osd.1 のHDDを交換してから、全部のノードを起動します。
再び HEALTH_OK になるまで数分かかりましたが、この状態になってから operator の pod を起動します。
$ kubectl -n rook-ceph scale deployment rook-ceph-operator --replicas=1
しばらくすると、交換したHDDが認識され、再び rebalancing が始まりました。
cluster:
id: 51464e80-fbf5-44cd-b033-a2e1374526cf
health: HEALTH_OK
services:
mon: 3 daemons, quorum k,l,m (age 6m)
mgr: a(active, since 6m)
mds: myfs:1 {0=myfs-b=up:active} 1 up:standby-replay
osd: 5 osds: 5 up (since 19s), 5 in (since 19s); 54 remapped pgs
data:
pools: 4 pools, 97 pgs
objects: 6.67M objects, 164 GiB
usage: 1.7 TiB used, 17 TiB / 18 TiB avail
pgs: 3748057/19997190 objects misplaced (18.743%)
53 active+remapped+backfill_wait
43 active+clean
1 active+remapped+backfilling
io:
client: 8.2 KiB/s rd, 1.3 MiB/s wr, 2 op/s rd, 135 op/s wr
recovery: 0 B/s, 300 keys/s, 6 objects/s
progress:
Rebalancing after osd.1 marked in (16s)
[............................]
今回交換したHDDは別のNASの交換用にストックしておく予定です。
交換したHDDへの追加テスト
別のシステムに接続してもう少し詳しくテストしてみます。
$ sudo smartctl -t long /dev/sdb
smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.4.0-139-generic] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===
Sending command: "Execute SMART Extended self-test routine immediately in off-line mode".
Drive command "Execute SMART Extended self-test routine immediately in off-line mode" successful.
Testing has begun.
Please wait 571 minutes for test to complete.
Test will complete after Tue Feb 21 11:35:36 2023 UTC
Use smartctl -X to abort test.
10時間(600 minutes)ほど経過した段階で確認したextended (long)テストの結果は次のようになりました。
$ sudo smartctl -l selftest /dev/sdb
smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.4.0-139-generic] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Extended offline Completed without error 00% 20448 -
# 2 Extended offline Completed: servo/seek failure 90% 20319 0
# 3 Short offline Completed: servo/seek failure 70% 20319 0
# 4 Short offline Completed: servo/seek failure 60% 20318 0
# 5 Short offline Completed without error 00% 2166 -
3 of 3 failed self-tests are outdated by newer successful extended offline self-test # 1
検証用のシステムは次のような構成です。
- 本体: Fujitsu製 PRIMERGY MX130 S2
- CPU: AMD FX(tm)-6300 Six-Core Processor
- Memory: DDR3-677 22GB
- Primary Storage (/dev/sda): Intel SSD 535 120GB
- OS: Ubuntu 20.04.5 (LTS) 64bit版
このシステムに/dev/sdbとして接続した上で、smartctlコマンドからlongテストを実施しています。
今回の対応は適当だったのか?
一般的に servo/seek failure にはどのように対応するべきなのでしょうか。
最終的なSMARTの結果をみる限り、交換する必要はなさそうでした。
このシステムでの対応として
今回はCeph/Rookの障害対応の練習としてHDDを交換しました。
手元に同容量のHGSTのUltrastarがあったことと、メモリを増量するためにメンテナンス・ウィンドウを予定していたことから追加でHDD交換の作業実施を決定しました。
HDDが一つ壊れたところでサービスは継続できるので、このシステムについては交換する必要性はほぼなかったといえます。
一般的な対応として
SMARTのテスト中に "servo/seek failure" が発生してもテスト自体は終っているので、これだけで交換する必要はないと思います。少なくともRMAには該当しないでしょう。
商用OSが出力するSMARTの結果にはサーボの不調によって予防的な交換を勧めるものもあるので、あまり頻度が上がれば心配ではあるけれど、まずは Seek_Error_RateやSeek_Time_Performanceなどの値が正常であるかどうかを確認するべきだと思われます。
今回のケースでは、負荷がほとんどない検証用のシステムに接続してみると問題は再現しなかったということです。
予防的に交換する判断もあると思いますが、現段階では交換の必要性はほぼないと思いました。
後日談 - HDDが突然クラッシュした時の対応ログ
ここでは rook/ceph v1.9.13 を利用しています。
前回は計画的にOSDを停止しましたが、突然にHDDがクラッシュしたので、その際の対応についてログを残しておきます。
基本的には計画交換の際と同様に対応しています。
発見の経緯と障害発生ノードの状況
Kubernetesのクラスターを全てv1.27.5にアップグレードしたタイミングで、kube-prometheusを動作させています。
ここからのメール通知でHDDがダウンしたタイミングで状況を把握していました。
対象のノードにアクセスした時のdmesgは次のような状況でした。
$ sudo dmesg | grep sda
[ 3.843102] sd 0:0:0:0: [sda] 7814037168 512-byte logical blocks: (4.00 TB/3.64 TiB)
[ 3.843103] sd 0:0:0:0: [sda] 4096-byte physical blocks
[ 3.843107] sd 0:0:0:0: [sda] Write Protect is off
[ 3.843108] sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
[ 3.843114] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 3.962646] sd 0:0:0:0: [sda] Attached SCSI disk
[3712876.369100] blk_update_request: I/O error, dev sda, sector 2476925184 op 0x1:(WRITE) flags 0x8800 phys_seg 6 prio class 0
[3712876.372943] blk_update_request: I/O error, dev sda, sector 2563816832 op 0x1:(WRITE) flags 0x8800 phys_seg 16 prio class 0
[3712876.375629] blk_update_request: I/O error, dev sda, sector 2704265728 op 0x1:(WRITE) flags 0x8800 phys_seg 7 prio class 0
[3712876.378941] blk_update_request: I/O error, dev sda, sector 2758165248 op 0x1:(WRITE) flags 0x8800 phys_seg 16 prio class 0
[3712876.381839] blk_update_request: I/O error, dev sda, sector 2761019040 op 0x1:(WRITE) flags 0x8800 phys_seg 12 prio class 0
[3712876.383981] blk_update_request: I/O error, dev sda, sector 2765957968 op 0x1:(WRITE) flags 0x8800 phys_seg 5 prio class 0
[3712876.386381] blk_update_request: I/O error, dev sda, sector 2767521328 op 0x1:(WRITE) flags 0x8800 phys_seg 10 prio class 0
[3712876.388996] blk_update_request: I/O error, dev sda, sector 2782126720 op 0x1:(WRITE) flags 0x8800 phys_seg 16 prio class 0
[3712876.390800] blk_update_request: I/O error, dev sda, sector 2861393664 op 0x1:(WRITE) flags 0x8800 phys_seg 16 prio class 0
[3712876.392684] blk_update_request: I/O error, dev sda, sector 1969594448 op 0x1:(WRITE) flags 0x8800 phys_seg 6 prio class 0
[3712881.733781] sd 0:0:0:0: [sda] tag#10 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
[3712881.733787] sd 0:0:0:0: [sda] tag#10 Sense Key : Illegal Request [current]
[3712881.733793] sd 0:0:0:0: [sda] tag#10 Add. Sense: Unaligned write command
[3712881.733799] sd 0:0:0:0: [sda] tag#10 CDB: Synchronize Cache(10) 35 00 00 00 00 00 00 00 00 00
[3712881.733814] blk_update_request: I/O error, dev sda, sector 0 op 0x1:(WRITE) flags 0x800 phys_seg 0 prio class 0
[3712881.751068] sd 0:0:0:0: [sda] Synchronizing SCSI cache
[3712881.751123] sd 0:0:0:0: [sda] Synchronize Cache(10) failed: Result: hostbyte=DID_BAD_TARGET driverbyte=DRIVER_OK
[3712881.751127] sd 0:0:0:0: [sda] Stopping disk
[3712881.751141] sd 0:0:0:0: [sda] Start/Stop Unit failed: Result: hostbyte=DID_BAD_TARGET driverbyte=DRIVER_OK
この時点でOSから/dev/sdaは認識できない状況になっていました。
kubectlとcephコマンドから把握できた状況
kubectl上で他のPodに影響がないか確認しておきます。
$ sudo kubectl get --all-namespaces pod | grep -v Running | grep -v Completed
NAMESPACE NAME READY STATUS RESTARTS AGE
rook-ceph rook-ceph-osd-2-7db985d8b9-s24p2 0/1 CrashLoopBackOff 29 (4m33s ago) 43d
HDDがクラッシュしただけで、OSDが1つ停止している他には影響はない状態です。
Rook/CephからはOSDがクラッシュしていたので ceph status
の出力結果は次のようになっています。
cluster:
id: 51464e80-fbf5-44cd-b033-a2e1374526cf
health: HEALTH_WARN
Degraded data redundancy: 3381503/22240935 objects degraded (15.204%), 35 pgs degraded, 35 pgs undersized
1 daemons have recently crashed
services:
mon: 3 daemons, quorum l,p,q (age 4w)
mgr: a(active, since 6w)
mds: 1/1 daemons up, 1 hot standby
osd: 5 osds: 4 up (since 2h), 4 in (since 111m); 35 remapped pgs
data:
volumes: 1/1 healthy
pools: 4 pools, 97 pgs
objects: 7.41M objects, 177 GiB
usage: 1.5 TiB used, 13 TiB / 15 TiB avail
pgs: 3381503/22240935 objects degraded (15.204%)
62 active+clean
33 active+undersized+degraded+remapped+backfill_wait
2 active+undersized+degraded+remapped+backfilling
io:
client: 852 B/s rd, 748 KiB/s wr, 1 op/s rd, 58 op/s wr
recovery: 14 KiB/s, 11 objects/s
また ceph osd status
や ceph health detail
も確認しておきます。
ID HOST USED AVAIL WR OPS WR DATA RD OPS RD DATA STATE
0 node1 386G 3339G 31 343k 1 0 exists,up
1 node3 335G 3390G 8 74.3k 2 89 exists,up
2 node2 0 0 0 0 0 0 autoout,exists
3 node4 388G 3337G 16 190k 0 0 exists,up
4 node5 442G 3283G 26 284k 1 15 exists,up
HEALTH_WARN Degraded data redundancy: 3368048/22240995 objects degraded (15.143%), 35 pgs degraded, 35 pgs undersized; 1 daemons have recently crashed
[WRN] PG_DEGRADED: Degraded data redundancy: 3368048/22240995 objects degraded (15.143%), 35 pgs degraded, 35 pgs undersized
pg 1.0 is stuck undersized for 2h, current state active+undersized+degraded+remapped+backfill_wait, last acting [3,1]
pg 2.0 is stuck undersized for 2h, current state active+undersized+degraded+remapped+backfill_wait, last acting [1,0]
...
[WRN] RECENT_CRASH: 1 daemons have recently crashed
osd.2 crashed on host rook-ceph-osd-2-7db985d8b9-s26p2 at 2023-10-27T00:14:59.555441Z
復旧までの一時対応について
自動的にRook/CephではPGのリカバリが進行しています。
最終的にはOSD.2を削除し、ノードを停止した上でHDDを交換し、再度Rook/Cephのクラスターに加えていきますが、まずはceph status
でbackfilling処理が完了するまで待つことにしました。
そして概ね、交換用のHDDが到着してから次のような復旧手順を考えました。
- OSD.2の削除 (osd-purge.yamlの実行)、crash reportの削除
- Operatorの停止 (HDDの自動認識やOSDの自動復旧を停止)
- node2のcordon/drainの実行とノードの停止
- 同容量HDDとの交換と、ノードの起動
- uncordonの実行
- Operatorの起動
- 稼動確認
とりあえず手持ちの4TBのHDDは中古なので、新品のWD GOLD/Ultrastarを発注していて到着してから作業を進めます。
試しにbackfilling中にosd.2の削除を試してみます。
## もし以前に job.batch/rook-ceph-purge-osd を実行していればこれを先に停止する
# $ sudo kubectl -n rook-ceph delete job.batch/rook-ceph-purge-osd
## ./deploy/examples/osd-purge.yaml を編集し、<OSD-IDs>を2に変更してからapplyすること
$ sudo kubectl apply -f ./deploy/examples/osd-purge.yaml
osd-purge.yamlは起動状態のOSDは削除できないことになっていてbackfillingを待たないはずですが、正常状態からのOSD削除とは違うようです。現状では次のようなログを出力してOSDの削除ができません。
2023-10-27 03:10:36.599304 D | exec: Running command: ceph osd safe-to-destroy 2 --connect-timeout=15 --cluster=rook-ceph --conf=/var/lib/rook/rook-ceph/rook-ceph.config --name=client.admin --keyring=/var/lib/rook/rook-ceph/client.admin.keyring --format json
2023-10-27 03:10:36.869041 W | cephosd: osd.2 is NOT be ok to destroy, retrying in 1m until success
このため、一度 osd-purge.yaml の実行は諦めて、backfillingが終るまで待つことにします。
$ sudo kubectl -n rook-ceph delete job.batch/rook-ceph-purge-osd
他の健全なノードのOSD(HDD,/dev/sda)の状況チェック
backfillingが完了するまで、smartctlを使って他のノードの様子を確認しておきます。
$ ansible all -m command -b -a "smartctl -t short /dev/sda"
## wait more than 2 mins
$ ansible all -m command -b -a "smartctl -l selftest /dev/sda" | grep offline
# 1 Short offline Completed without error 00% 21719 -
# 1 Short offline Completed without error 00% 26350 -
# 1 Short offline Completed without error 00% 5913 -
# 1 Short offline Completed without error 00% 21719 -
とりあえず他のノードのHDDには以上はなさそうです。
1台だけ5913時間とLifeTime hoursが短かい出力は、この記事の先頭でUltrastarに交換したサーバーです。
作業1. osd.2の削除
72時間程度経過してからceph statusの出力を確認します。
cluster:
id: 51464e80-fbf5-44cd-b033-a2e1374526cf
health: HEALTH_WARN
1 daemons have recently crashed
services:
mon: 3 daemons, quorum l,p,q (age 5w)
mgr: a(active, since 6w)
mds: 1/1 daemons up, 1 hot standby
osd: 5 osds: 4 up (since 2d), 4 in (since 2d)
data:
volumes: 1/1 healthy
pools: 4 pools, 97 pgs
objects: 7.43M objects, 177 GiB
usage: 1.8 TiB used, 13 TiB / 15 TiB avail
pgs: 96 active+clean
1 active+clean+scrubbing+deep
io:
client: 8.5 KiB/s rd, 458 KiB/s wr, 3 op/s rd, 9 op/s wr
この状態でosd-purge.yamlを実行します。
## 編集済みのosd-purge.yamlを改めて実行
$ sudo kubectl apply -f ./deploy/examples/osd-purge.yaml
この時のログは次のようになりました。
2023-10-29 21:28:19.896058 I | rookcmd: starting Rook v1.9.13 with arguments '/usr/local/bin/rook ceph osd remove --preserve-pvc false --force-osd-removal false --osd-ids 2'
2023-10-29 21:28:19.896124 I | rookcmd: flag values: --force-osd-removal=false, --help=false, --log-level=DEBUG, --operator-image=, --osd-ids=2, --preserve-pvc=false, --service-account=
...
2023-10-29 21:28:24.828033 I | cephosd: no ceph crash to silence
2023-10-29 21:28:24.828046 I | cephosd: completed removal of OSD 2
この処理はすぐに完了し、ceph statusの出力は次のようになっています。
cluster:
id: 51464e80-fbf5-44cd-b033-a2e1374526cf
health: HEALTH_WARN
1 daemons have recently crashed
services:
mon: 3 daemons, quorum l,p,q (age 5w)
mgr: a(active, since 6w)
mds: 1/1 daemons up, 1 hot standby
osd: 4 osds: 4 up (since 2d), 4 in (since 2d); 18 remapped pgs
data:
volumes: 1/1 healthy
pools: 4 pools, 97 pgs
objects: 7.43M objects, 177 GiB
usage: 1.8 TiB used, 13 TiB / 15 TiB avail
pgs: 932805/22290660 objects misplaced (4.185%)
78 active+clean
15 active+remapped+backfill_wait
3 active+remapped+backfilling
1 active+clean+scrubbing+deep
io:
client: 852 B/s rd, 170 KiB/s wr, 1 op/s rd, 12 op/s wr
recovery: 18 MiB/s, 182 keys/s, 14 objects/s
crash reportが残っているので、これは削除しておきます。
$ sudo kubectl -n rook-ceph exec -it $(sudo kubectl -n rook-ceph get pod -l app=rook-ceph-tools -o jsonpath='{.items[*].metadata.name}') -- bash
## 以下はrook-ceph-tools内で実行
# ceph crash ls
ID ENTITY NEW
2023-10-27T00:14:59.555441Z_64635e62-9248-46e4-aa4b-005b421809a1 osd.2 *
# ceph crash info 2023-10-27T00:14:59.555441Z_64635e62-9248-46e4-aa4b-005b421809a1
# ceph crash archive-all
これを実行するとHEALTH_OKになりました。
51464e80-fbf5-44cd-b033-a2e1374526cf
health: HEALTH_OK
services:
mon: 3 daemons, quorum l,p,q (age 5w)
mgr: a(active, since 6w)
mds: 1/1 daemons up, 1 hot standby
osd: 4 osds: 4 up (since 3d), 4 in (since 3d); 6 remapped pgs
data:
volumes: 1/1 healthy
pools: 4 pools, 97 pgs
objects: 7.43M objects, 178 GiB
usage: 1.8 TiB used, 13 TiB / 15 TiB avail
pgs: 794646/22290831 objects misplaced (3.565%)
91 active+clean
4 active+remapped+backfill_wait
2 active+remapped+backfilling
io:
client: 997 B/s rd, 939 KiB/s wr, 1 op/s rd, 70 op/s wr
recovery: 18 KiB/s, 13 objects/s
2. Operatorの停止
以前と同様の手順でOperator Podを停止します。
$ sudo kubectl -n rook-ceph scale deployment rook-ceph-operator --replicas=0
3. ノードの停止
これも特に変更はありません。cordon, drainを実行して十分に時間が経過してからshutdownをします。
$ sudo kubectl cordon node2
$ sudo kubectl drain node2 --ignore-daemonsets --delete-emptydir-data
しばらく様子を観察してから、ノードを停止します。
$ ssh node2
$ sudo shutdown -h now
4. HDDの交換とノードの起動
電源を停止している間にHDDを交換し、電源を投入します。
しばらく待ち、ノードの状態を確認します。
$ sudo kubectl get node
NAME STATUS ROLES AGE VERSION
node1 Ready control-plane 2y288d v1.25.6
node2 Ready,SchedulingDisabled control-plane 2y288d v1.25.6
node3 Ready <none> 2y288d v1.25.6
node4 Ready <none> 2y197d v1.25.6
node5 Ready <none> 2y197d v1.25.6
また新しいHDD(/dev/sda)が認識されていることも確認します。
$ lsblk -f
NAME FSTYPE LABEL UUID FSAVAIL FSUSE% MOUNTPOINT
loop0 squashfs 0 100% /snap/core18/2796
loop1 squashfs 0 100% /snap/core20/1974
loop2 squashfs 0 100% /snap/lxd/24061
loop3 squashfs 0 100% /snap/lxd/23991
loop4 squashfs 0 100% /snap/snapd/20290
loop5 squashfs 0 100% /snap/core18/2790
loop6 squashfs 0 100% /snap/core20/2015
loop7 squashfs 0 100% /snap/snapd/20092
sda
sdb
├─sdb1 vfat 9E99-F4DC 504.9M 1% /boot/efi
└─sdb2 ext4 20ee9608-b523-49f3-b0fd-a040aa1d1d1b 351.9G 18% /
sr0
5. uncordonの実行
STATUSがReadyである事を確認し、uncordonして復帰させます。
$ sudo kubectl uncordon node2
6. Operatorの起動
続いてOperatorを起動します。
$ sudo kubectl -n rook-ceph scale deployment rook-ceph-operator --replicas=1
7. 稼動確認
しばらく待ち、operatorがjob.batch/rook-ceph-osd-prepare-node2
を完了させるまで待ちます。
その後、ceph status
でOSDの状況を確認します。
cluster:
id: 51464e80-fbf5-44cd-b033-a2e1374526cf
health: HEALTH_OK
services:
mon: 3 daemons, quorum l,p,q (age 3m)
mgr: a(active, since 7w)
mds: 1/1 daemons up, 1 hot standby
osd: 5 osds: 5 up (since 93s), 5 in (since 108s); 55 remapped pgs
data:
volumes: 1/1 healthy
pools: 4 pools, 97 pgs
objects: 7.46M objects, 180 GiB
usage: 1.8 TiB used, 16 TiB / 18 TiB avail
pgs: 3057930/22384596 objects misplaced (13.661%)
54 active+remapped+backfill_wait
42 active+clean
1 active+remapped+backfilling
io:
client: 1.2 KiB/s rd, 43 KiB/s wr, 2 op/s rd, 4 op/s wr
recovery: 0 B/s, 1.02k keys/s, 10 objects/s
OSD数が4から5に増加し、PGsの再配置が開始されました。
ここまでで障害発生時からの一連の作業は完了したことになります。
故障したHDDはHGSTのDeskstar NAS 4TB (May-2018製造)でした。
Deskstar NASは他のNASやKubernetesクラスターでもRook/Cephのbluestoreとして利用しています。
これまでのところ異常が発生したのはこの一台でしたし、SMARTの結果も問題ありません。
保証期間も過ぎていていてRMAもできませんが、よく動いてくれたと思います。
交換したHDDはUltrastar HC310になっています。
突発的に発生したHDD故障の対応を終えて
計画的にHEALTH_OKの状態で実施したOSDの削除が、突発的な事象の場合にはすぐに実施できませんでした。
osd-purge.yamlの**--force-osd-removal**オプションを有効にすれば可能だったと思いますが、予備のHDDがなかったことから取り寄せの時間的な余裕もあってこのオプションは使用しませんでした。
ただ、その他の手順は概ね計画交換時と同様だったことと、backfillingが終わってHEALTH_OKとなるまでの時間がおよそ72時間後だということが予測できたことは良かったと思います。
本番環境でRook/Cephを動作させるのであれば、一度はOSDを削除して交換作業を試してみるのも良いでしょう。
以上