Rook/Cephで発生した不整合からの回復

# はじめに

停電から回復したKubernetesクラスターの状態を確認していたところ、1つのPod(gitbucket)だけが**ContainerCreating**状態のまま長時間停止していることが分かりました。

原因はPVCがmountできないことだったのですが、原因は停電によってext4のjournal dataが残ったままになっていた事にあります。

回復のためにfsck.ext4を実行すれば良いことはすぐに分かったのですが、どのボリュームに対して実行すれば良いのか直感的には分かりにくかったのでメモを残しておきます。

## 環境

* Kubernetes v1.16.9 deployed by Kubespray
* Rook/Ceph v1.1.9 with FlexVolumes (BlockStorage using ext4) 

パーティションが破壊された事に起因するデータ破壊については、以下のバージョンで発生しています。

* Rook/Ceph v1.6.7 with CSI BlueStore (with HDD 4TBx2)

## 状態

kubectlコマンドで確認したところ次のような状態になっています。

```bash:停止しているPodを削除した後、やはり起動しない状態
$ kubectl -n gitbucket get all
NAME                         READY   STATUS              RESTARTS   AGE
pod/bucket-9b8d9799-khsm8    0/1     Init:1/2            1          27h
pod/mysql-84d459c89c-w8pb6   0/1     ContainerCreating   0          15m
```

Pod:bucketはinitContainersでmysqlの起動を待っているので、init状態のまま停止しています。mysqlのコンテナが起動すれば、bucketコンテナは自然に回復するはずなので、まずmysqlコンテナの回復を目指します。

# BlockStorageの不具合

## エラーの状況

kubectl describeで起動時の状態を確認すると次のようになっていました。

```bash
$ kubectl -n gitbucket describe pod/mysql-84d459c89c-w8pb6
....
Events:
  Type     Reason       Age                  From               Message
  ----     ------       ----                 ----               -------
  Normal   Scheduled    16m                  default-scheduler  Successfully assigned gitbucket/mysql-84d459c89c-w8pb6 to node04
  Warning  FailedMount  15m (x5 over 16m)    kubelet, node04  MountVolume.SetUp failed for volume "pvc-8aaa318c-1212-415d-b00f-e88b9c3c3087" : mount command failed, status: Failure, reason: Rook: Mount volume failed: failed to attach volume pvc-8aaa318c-1212-415d-b00f-e88b9c3c3087 for pod gitbucket/mysql-84d459c89c-w8pb6. Volume is already attached by pod gitbucket/mysql-84d459c89c-rllg6. Status Pending
  Warning  FailedMount  2m46s (x3 over 11m)  kubelet, node04  Unable to attach or mount volumes: unmounted volumes=[mysql-persistent-storage], unattached volumes=[database-auth-conf default-token-txprc mysql-persistent-storage]: timed out waiting for the condition
  Warning  FailedMount  92s (x10 over 15m)   kubelet, node04  MountVolume.SetUp failed for volume "pvc-8aaa318c-1212-415d-b00f-e88b9c3c3087" : mount command failed, status: Failure, reason: failed to mount volume /dev/rbd2 [ext4] to /var/lib/kubelet/plugins/ceph.rook.io/rook-ceph/mounts/pvc-8aaa318c-1212-415d-b00f-e88b9c3c3087, error 'fsck' found errors on device /dev/rbd2 but could not correct them: fsck from util-linux 2.31.1
/dev/rbd2: Superblock needs_recovery flag is clear, but journal has data.
/dev/rbd2: Run journal anyway

/dev/rbd2: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
  (i.e., without -a or -p options)
. 
  Warning  FailedMount  32s (x4 over 14m)  kubelet, node04  Unable to attach or mount volumes: unmounted volumes=[mysql-persistent-storage], unattached volumes=[mysql-persistent-storage database-auth-conf default-token-txprc]: timed out waiting for the condition
```

このエラーメッセージから、ノード**node04**と**/dev/rbd2**で問題が発生していることが分かります。

## node04上での修正

最初は、どう対応して良いか分からなかったのですが、node04にログインして/dev/を確認してみると、rbd2が存在しているので、これをfsck.ext4コマンドの引数に与えてみることにしました。

```bash
$ ssh node04
$ sudo fsck.ext4 /dev/rbd2
e2fsck 1.44.1 (24-Mar-2018)
Superblock needs_recovery flag is clear, but journal has data.
Run journal anyway<y>? yes
/dev/rbd2: recovering journal
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Free blocks count wrong (5067650, counted=5067649).
Fix<y>? yes
Free inodes count wrong (1310519, counted=1310518).
Fix<y>? yes

/dev/rbd2: ***** FILE SYSTEM WAS MODIFIED *****
/dev/rbd2: 202/1310720 files (14.9% non-contiguous), 175231/5242880 blocks
```

このまま時間が経過すると無事にPodが動き始めました。

```bash
$ kubectl -n gitbucket get all
NAME                         READY   STATUS     RESTARTS   AGE
pod/bucket-9b8d9799-khsm8    0/1     Init:1/2   1          27h
pod/mysql-84d459c89c-w8pb6   0/1     Running    0          27m
```

xfsで構成した方が良かったかなと(xfsでも問題が発生する可能性はありますが)少し後悔しています。

以上

# その後に発生した障害

今回はHarborで利用しているPVCがmountできなくなったのですが、原因はまた別でした。

```text:エラーメッセージ
$ kubectl -n harbor describe pod/my-harbor-harbor-redis-0
...
Events:
  Type     Reason       Age                      From               Message
  ----     ------       ----                     ----               -------
  Warning  FailedMount  12m (x228 over 7h42m)    kubelet, node01  MountVolume.SetUp failed for volume "pvc-d37fd3f0-22ac-42c2-a90d-7427c2fa91d7" : mount command failed, status: Failure, reason: Rook: Mount volume failed: failed to attach volume pvc-d37fd3f0-22ac-42c2-a90d-7427c2fa91d7 for pod harbor/my-harbor-harbor-redis-0. Volume is already attached by pod harbor/my-harbor-harbor-redis-0. Status Pending
  Warning  FailedMount  7m18s (x151 over 7h40m)  kubelet, node01  Unable to attach or mount volumes: unmounted volumes=[data], unattached volumes=[data default-token-nnqmn]: timed out waiting for the condition
  Warning  FailedMount  2m47s (x51 over 7h38m)   kubelet, node01  Unable to attach or mount volumes: unmounted volumes=[data], unattached volumes=[default-token-nnqmn data]: timed out waiting for the condition
```

この時に PV: pvc-d37fd3f0-22ac-42c2-a90d-7427c2fa91d7 の状態がどうなっているのか確認します。

```bash:
$ kubectl -n harbor get pv pvc-d37fd3f0-22ac-42c2-a90d-7427c2fa91d7
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          
                        STORAGECLASS      REASON   AGE
pvc-d37fd3f0-22ac-42c2-a90d-7427c2fa91d7   1Gi        RWO            Delete           Bound    harbor/data-my-harbor-harbor-redis-0   rook-ceph-block            232d
```

Rook/Cephの側からみると特別な問題は発生していません。

```bash:現状、エラーメッセージなど
$ kubectl -n harbor get pvc data-my-harbor-harbor-redis-0
NAME                            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
data-my-harbor-harbor-redis-0   Bound    pvc-d37fd3f0-22ac-42c2-a90d-7427c2fa91d7   1Gi        RWO            rook-ceph-block   232d

$ kubectl -n rook-ceph exec -it rook-ceph-tools-7764cdbbc4-wkc64 ceph status
  cluster:
    id:     89ddf8a3-e7ce-41e6-a081-b6b5fab8b8e0
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum v,w,y (age 7h)
    mgr: a(active, since 7h)
    mds: myfs:1 {0=myfs-a=up:active} 1 up:standby-replay
    osd: 4 osds: 4 up (since 7h), 4 in (since 7h)
 
  data:
    pools:   13 pools, 104 pgs
    objects: 2.64k objects, 6.1 GiB
    usage:   567 GiB used, 6.6 TiB / 7.2 TiB avail
    pgs:     104 active+clean
 
  io:
    client:   938 B/s rd, 9.5 KiB/s wr, 1 op/s rd, 0 op/s wr

$ kubectl -n rook-ceph logs -l rook-ceph-agent
...
2020-09-04 01:59:27.976756 I | flexdriver: calling agent to attach volume replicapool/pvc-d37fd3f0-22ac-42c2-a90d-7427c2fa91d7
2020-09-04 01:59:27.979645 I | flexvolume: volume attachment record rook-ceph/pvc-d37fd3f0-22ac-42c2-a90d-7427c2fa91d7 exists for pod: harbor/my-harbor-harbor-redis-0
...
```

## 対応

どうにもStatefulSetの定義から削除する以外に対応が思いつかなかったので、helmで導入していたので、helmから削除して、再度インストールすることにしました。

```bash:Makefileから実行したコマンド
$ (cd harbor-helm; helm delete my-harbor)
$ (cd harbor-helm; helm install --replace --name my-harbor --namespace harbor .)
```

さすがにこの後は問題なくPVCがマウントできました。

調べてみると定期的に実施している夜間のノード毎の再起動タイミングが非常に近かったので、これを十分に話して不整合が発生しにくくしてしばらく様子をみることにしました。


# Filesystemの不具合

また別のPodではfilesystemがマウントできない状況になりました。

```text:エラーメッセージ
  Warning  FailedMount  13m  kubelet, node04  MountVolume.SetUp failed for volume "rook-data" : mount command failed, stat
us: Failure, reason: failed to mount filesystem myfs to /var/lib/kubelet/pods/297a0883-0d02-41c9-855b-b193f02210ec/volumes/c
eph.rook.io~rook/rook-data with monitor 10.233.32.156:6789,10.233.62.103:6789,10.233.34.233:6789:/ and options [name=admin s
ecret=AQBuk+pctG/7JBAATogIHHCDNN7W7u4zppFtaw== mds_namespace=myfs]: mount failed: exit status 32
Mounting command: systemd-run
Mounting arguments: --description=Kubernetes transient mount for /var/lib/kubelet/pods/297a0883-0d02-41c9-855b-b193f02210ec/
volumes/ceph.rook.io~rook/rook-data --scope -- mount -t ceph -o name=admin,secret=AQBuk+pctG/7JBAATogIHHCDNN7W7u4zppFtaw==,m
ds_namespace=myfs 10.233.32.156:6789,10.233.62.103:6789,10.233.34.233:6789:/ /var/lib/kubelet/pods/297a0883-0d02-41c9-855b-b
193f02210ec/volumes/ceph.rook.io~rook/rook-data
Output: Running scope as unit: run-r35a1db0e9e564106b94b7ea5d1973fb3.scope
mount: /var/lib/kubelet/pods/297a0883-0d02-41c9-855b-b193f02210ec/volumes/ceph.rook.io~rook/rook-data: mount(2) system call 
failed: No route to host.
  Warning  FailedMount  13m  kubelet, node04  MountVolume.SetUp failed for volume "rook-data" : mount command failed, stat
us: Failure, reason: failed to mount filesystem myfs to /var/lib/kubelet/pods/297a0883-0d02-41c9-855b-b193f02210ec/volumes/c
eph.rook.io~rook/rook-data with monitor 10.233.32.156:6789,10.233.62.103:6789,10.233.34.233:6789:/ and options [name=admin s
ecret=AQBuk+pctG/7JBAATogIHHCDNN7W7u4zppFtaw== mds_namespace=myfs]: mount failed: exit status 32
```

## 対応

MDSノードでも特にエラーメッセージは確認できませんでしたが、ノードをリスタートしてみます。
念のためStandbyになっている方からリスタートします。

```bash:ノード名は適宜変更すること
$ kubectl -n rook-ceph exec -it rook-ceph-tools-6dd7c595bc-xvk92 ceph status
...
services:
    mon: 3 daemons, quorum bm,bs,bu (age 15m)
    mgr: a(active, since 13m)
    mds: myfs:1 {0=myfs-a=up:active} 1 up:standby-replay
    osd: 4 osds: 4 up (since 60m), 4 in (since 5w)
...

## "a=up:active"の表示から、b側をまず再起動しておく
$ kubectl -n rook-ceph delete pod rook-ceph-mds-myfs-b-78ccfc6754-jff2f

## kubectl -n rook-ceph get pod でmyfs-bが正常に動いていることを確認してから、a側をリスタートする
$ kubectl -n rook-ceph delete pod rook-ceph-mds-myfs-a-87448c57b-lp7hl
```

一応は、この方法でMDSノードを再起動して無事にfilesystemにアクセスできるようになりました。

# HEALTH_ERR への対応

気がつくとノード全体が機能を停止していて、いろいろPodがPending状態やらTerminatingのまま固まっていたりとか、それらを解消した後にceph statusがエラーになっていました。

そもそものノードエラーは```shutdown -r now```でシステム全体をリスタートしました。この部分の根本原因については、推測はしていますが、追求していません。

その上で発生し続けたエラーについてメモを残しておきます。

## エラーの状況

ノードを再起動する前には、TerminatingなPodとPendingなPodの2つが同時に存在し続ける変な感じになっていたのですが、再起動してみるとRook/Cephが妙な結果になっている事に気がつきました。

```text:statusの確認
$ kubectl -n rook-ceph exec -it ... -- ceph status
  cluster:
    id:     3cedbf9c-82a4-4ce8-988b-9e64b1b3d97a
    health: HEALTH_ERR
            Module 'rook' has failed: HTTPSConnectionPool(host='10.233.0.1', port=443): Max retries exceeded with url: /api/v1/namespaces/rook-ceph/pods (Caused by ProtocolError('Connection aborted.', error(99, 'Cannot assign requested address')))

  services:
    mon: 3 daemons, quorum bm,bs,bu (age 104s)
    mgr: a(active, since 5m)
    mds: myfs:1 {0=myfs-b=up:active} 1 up:standby-replay
    osd: 4 osds: 4 up (since 112m), 4 in (since 8w)

  data:
    pools:   3 pools, 300 pgs
    objects: 2.01M objects, 11 GiB
    usage:   970 GiB used, 13 TiB / 14 TiB avail
    pgs:     300 active+clean

  io:
    client:   1.2 KiB/s rd, 46 KiB/s wr, 2 op/s rd, 2 op/s wr
```

つまり、問題なくMDS/OSDは稼動しているのに、HEALTH_ERRとなっている点に気がつきました。
いろいろ試行錯誤した後に、mgr podを再起動しました。

```bash:mgr再起動
$ kubectl -n rook-ceph delete replicaset.apps/rook-ceph-mgr-a-7644684465
replicaset.apps "rook-ceph-mgr-a-7644684465" deleted
```

しばらくしてからceph statusを確認し、問題が修正されたことを確認しました。

```text:
$ kubectl -n rook-ceph exec -it ... -- ceph status
  cluster:
    id:     3cedbf9c-82a4-4ce8-988b-9e64b1b3d97a
    health: HEALTH_OK
...
```

実際にはmds podの内部でエラーが発生していたり、いろいろあったので、standby側からリスタートしたり、全ての稼動しているPodのログは確認した上での作業でした。

本家のissuesでも解決策までは載っていなかったので、moduleをdisabled/enabledするべきなのか、他の方法で対応するべきなのか判断がつかなかったのですが、ひとまず問題はcloseしたので良かったです。

# 全台shutdownの影響によるrace conditionに遭遇した時のメモ

> このメモはリカバリーの記録ではありません。単純にテスト系で発生した事象に対して行なった操作と結果を残しているだけです。データの保全が必要な場合には別途方法を検討してください。

> 【2021/08/18追記】
この現象では、/dev/sdb2,/dev/sdc2などがbluestoreになっている事がデータ破壊の根本原因となっています。公式のドキュメントが更新され、v1.6.0以降のバージョンで現象が発生すること、v1.6.8以降へのアップグレードが推奨されています。解決策は、v1.6.8以降に更新した後、OSDを削除し、問題となっているディスクの初期化、再認識による正常化が指示されています。
[https://rook.github.io/docs/rook/v1.6/ceph-common-issues.html#unexpected-partitions-created](https://rook.github.io/docs/rook/v1.6/ceph-common-issues.html#unexpected-partitions-created)

2021/07にテスト系のk8sシステム全体をshutdownしてメンテナンスを行なってからシステムを再起動したところ次のような状況になりました。

少し冗長ですがメンテナンス用のBASH関数についても掲載しています。

race conditionが発生することは度々リポートされていて、issuesにも記録が残っています。
cri-oにすれば遭遇しないといったメモもありますが、VMware上でテストした範囲ではlibcephのエラーは発生していて違いは観測されませんでした。

* https://github.com/rook/rook/issues/7734
* https://github.com/rook/rook/issues/2517

今回発生したのは、最初のリンク先にあるRaw Deviceがおかしくなった点にあります。
クラスター全体では4TBのディスクを各ノード2つ、4ノードで計32TBを利用しています。

```bash:異常発生後のlsblkの出力
$ lsblk -l
NAME  MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
loop0   7:0    0  55.4M  1 loop /snap/core18/1944
loop1   7:1    0  55.5M  1 loop /snap/core18/2074
loop2   7:2    0  67.6M  1 loop /snap/lxd/20326
loop3   7:3    0  32.3M  1 loop /snap/snapd/12159
loop5   7:5    0  32.3M  1 loop /snap/snapd/12398
loop6   7:6    0  70.3M  1 loop /snap/lxd/21029
sda     8:0    0 465.8G  0 disk 
sda1    8:1    0   512M  0 part 
sda2    8:2    0 465.3G  0 part /
sdb     8:16   0   3.7T  0 disk 
sdb2    8:18   0    48G  0 part 
sdb3    8:19   0   6.7M  0 part 
sdc     8:32   0   3.7T  0 disk 
sdc2    8:34   0    48G  0 part 
sdc3    8:35   0   6.2M  0 part 
sr0    11:0    1  1024M  0 rom  

$ lsblk -f
NAME   FSTYPE         LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINT
loop0  squashfs                                                        0   100% /snap/core18/1944
loop1  squashfs                                                        0   100% /snap/core18/2074
loop2  squashfs                                                        0   100% /snap/lxd/20326
loop3  squashfs                                                        0   100% /snap/snapd/12159
loop5  squashfs                                                        0   100% /snap/snapd/12398
loop6  squashfs                                                        0   100% /snap/lxd/21029
sda                                                                             
├─sda1 vfat                 5AD4-66D1                                           
└─sda2 ext4                 42db9b49-9bb0-4590-a0f5-846f1a74058b  420.2G     3% /
sdb    ceph_bluestore                                                           
├─sdb2 ceph_bluestore                                                           
└─sdb3                                                                          
sdc    ceph_bluestore                                                           
├─sdc2 ceph_bluestore                                                           
└─sdc3                                                                          
sr0                           
```

期待するのは、/dev/sdb全体をceph_bluestoreとして利用している状態で、/dev/sdb{2,3}は存在自体が想定外のパーティションです。

```bash:障害時の状況
$ type get_toolbox_podname 
get_toolbox_podname is a function
get_toolbox_podname () 
{ 
    sudo kubectl -n rook-ceph get pod -l app=rook-ceph-tools -o jsonpath='{.items[*].metadata.name}'
}
$ type ceph_status
ceph_status is a function
ceph_status () 
{ 
    name=$(get_toolbox_podname);
    sudo kubectl -n rook-ceph exec -it "${name}" -- ceph status
}

## ここからがログ
$ ceph_status 
  cluster:
    id:     454d7e30-a1f5-4369-b1e5-6b9b2700054c
    health: HEALTH_ERR
            4/507 objects unfound (0.789%)
            1487 scrub errors
            Too many repaired reads on 5 OSDs
            Possible data damage: 4 pgs recovery_unfound, 26 pgs inconsistent
            Degraded data redundancy: 12/1521 objects degraded (0.789%), 4 pgs degraded
            3 pgs not deep-scrubbed in time
            4 pgs not scrubbed in time
            6 slow ops, oldest one blocked for 1584994 sec, daemons [osd.0,osd.1,osd.2,osd.4,osd.5] have slow 
ops.
 
  services:
    mon: 3 daemons, quorum a,b,c (age 2w)
    mgr: a(active, since 2w)
    mds: myfs:1 {0=myfs-b=up:active} 1 up:standby-replay
    osd: 16 osds: 16 up (since 2w), 16 in (since 2w)
    rgw: 1 daemon active (my.store.a)
 
  task status:
 
  data:
    pools:   11 pools, 177 pgs
    objects: 507 objects, 686 MiB
    usage:   19 GiB used, 29 TiB / 29 TiB avail
    pgs:     12/1521 objects degraded (0.789%)
             4/507 objects unfound (0.789%)
             148 active+clean
             13  active+clean+inconsistent
             12  active+clean+inconsistent+failed_repair
             3   active+recovery_unfound+degraded
             1   active+recovery_unfound+degraded+inconsistent+failed_repair
 
  io:
    client:   1.2 KiB/s rd, 2 op/s rd, 0 op/s wr
```

このログは、障害が発生してから数日経過した状態で出力したものです。
Clean-upのために、全てのPVCを削除すると、8時間ほど経過しても削除処理が完了せずに、このログは次のようになりました。

```bash:ceph_statusの出力
$ ceph_status

  cluster:
    id:     454d7e30-a1f5-4369-b1e5-6b9b2700054c
    health: HEALTH_ERR
            6/507 objects unfound (1.183%)
            1213 scrub errors
            Too many repaired reads on 5 OSDs
            Possible data damage: 6 pgs recovery_unfound, 20 pgs inconsistent
            Degraded data redundancy: 18/1521 objects degraded (1.183%), 6 pgs degraded
            3 pgs not deep-scrubbed in time
            4 pgs not scrubbed in time
            8 slow ops, oldest one blocked for 1614550 sec, daemons [osd.0,osd.1,osd.2,osd.4,osd.5] have slow 
ops.
 
  services:
    mon: 3 daemons, quorum a,b,c (age 2w)
    mgr: a(active, since 2w)
    mds: myfs:1 {0=myfs-b=up:active} 1 up:standby-replay
    osd: 16 osds: 16 up (since 2w), 16 in (since 2w)
    rgw: 1 daemon active (my.store.a)
 
  task status:
 
  data:
    pools:   11 pools, 177 pgs
    objects: 507 objects, 686 MiB
    usage:   19 GiB used, 29 TiB / 29 TiB avail
    pgs:     18/1521 objects degraded (1.183%)
             6/507 objects unfound (1.183%)
             154 active+clean
             10  active+clean+inconsistent+failed_repair
             7   active+clean+inconsistent
             3   active+recovery_unfound+degraded
             3   active+recovery_unfound+degraded+inconsistent+failed_repair
 
  io:
    client:   1.2 KiB/s rd, 2 op/s rd, 0 op/s wr
```

この時のPVCの状態は次のようなもので、たまたま最後に削除したRook/Cassandraが利用するPVCだけが残っています。
削除手順自体はドキュメントに従っています。

```bash:pvcの状態
$ sudo kubectl get pvc --all-namespaces
NAMESPACE        NAME                                                        STATUS        VOLUME             
                        CAPACITY   ACCESS MODES   STORAGECLASS      AGE
rook-cassandra   rook-cassandra-data-rook-cassandra-us-east-1-us-east-1a-0   Terminating   pvc-77d3d697-edd5-4
633-8b81-a8474eb94043   5Gi        RWO            rook-ceph-block   26d
rook-cassandra   rook-cassandra-data-rook-cassandra-us-east-1-us-east-1a-1   Terminating   pvc-c6bc0341-ba1d-4
419-b280-c143edf240bb   5Gi        RWO            rook-ceph-block   26d
rook-cassandra   rook-cassandra-data-rook-cassandra-us-east-1-us-east-1a-2   Terminating   pvc-c4261458-7d46-4
33a-a05f-7c94e93b7034   5Gi        RWO            rook-ceph-block   26d
```

とりあえず ``ceph health detail`` の出力はエラーのオンパレードのような状況になっています。

全てのPVを削除している状況なので、いろいろ試してみます。

```
# ceph health detail
HEALTH_ERR 1/397 objects unfound (0.252%); 920 scrub errors; Too many repaired reads on 5 OSDs; Possible data 
damage: 1 pg recovery_unfound, 19 pgs inconsistent; Degraded data redundancy: 3/1191 objects degraded (0.252%)
, 1 pg degraded; 1 pgs not deep-scrubbed in time; 1 pgs not scrubbed in time; 4 slow ops, oldest one blocked f
or 1626835 sec, daemons [osd.1,osd.2,osd.5] have slow ops.
[WRN] OBJECT_UNFOUND: 1/397 objects unfound (0.252%)
    pg 2.1a has 1 unfound objects
[ERR] OSD_SCRUB_ERRORS: 920 scrub errors
[WRN] OSD_TOO_MANY_REPAIRS: Too many repaired reads on 5 OSDs
    osd.3 had 16 reads repaired
    osd.1 had 18 reads repaired
    osd.7 had 31 reads repaired
    osd.2 had 32 reads repaired
    osd.4 had 34 reads repaired
[ERR] PG_DAMAGED: Possible data damage: 1 pg recovery_unfound, 19 pgs inconsistent
    pg 2.1 is active+clean+inconsistent+failed_repair, acting [7,0,6]
    pg 2.3 is active+clean+inconsistent+failed_repair, acting [3,5,6]
    pg 2.5 is active+clean+inconsistent, acting [6,4,1]
    pg 2.7 is active+clean+inconsistent+failed_repair, acting [1,7,4]
    pg 2.8 is active+clean+inconsistent+failed_repair, acting [3,2,0]
    pg 2.a is active+clean+inconsistent+failed_repair, acting [2,4,7]
    pg 2.11 is active+clean+inconsistent+failed_repair, acting [7,1,4]
    pg 2.18 is active+clean+inconsistent+failed_repair, acting [3,1,2]
    pg 2.1a is active+recovery_unfound+degraded, acting [5,6,4], 1 unfound
    pg 2.1b is active+clean+inconsistent+failed_repair, acting [6,5,3]
    pg 2.1c is active+clean+inconsistent+failed_repair, acting [2,1,0]
    pg 2.1d is active+clean+inconsistent+failed_repair, acting [3,6,5]
    pg 2.1e is active+clean+inconsistent+failed_repair, acting [4,6,3]
    pg 2.1f is active+clean+inconsistent+failed_repair, acting [4,1,2]
    pg 11.6 is active+clean+inconsistent, acting [3,0,1]
    pg 11.9 is active+clean+inconsistent, acting [4,1,7]
    pg 11.c is active+clean+inconsistent, acting [7,4,1]
    pg 11.14 is active+clean+inconsistent, acting [1,4,3]
    pg 11.1b is active+clean+inconsistent, acting [1,2,0]
    pg 11.1d is active+clean+inconsistent, acting [1,11,3]
[WRN] PG_DEGRADED: Degraded data redundancy: 3/1191 objects degraded (0.252%), 1 pg degraded
    pg 2.1a is active+recovery_unfound+degraded, acting [5,6,4], 1 unfound
[WRN] PG_NOT_DEEP_SCRUBBED: 1 pgs not deep-scrubbed in time
    pg 2.1a not deep-scrubbed since 2021-06-24T13:46:01.226873+0000
[WRN] PG_NOT_SCRUBBED: 1 pgs not scrubbed in time
    pg 2.1a not scrubbed since 2021-06-30T19:52:31.104830+0000
[WRN] SLOW_OPS: 4 slow ops, oldest one blocked for 1626835 sec, daemons [osd.1,osd.2,osd.5] have slow ops.
```

OBJECT_UNFOUND: なpgに対しては、mark_unfound_lost で対応していきます。

```bash
# ceph pg 2.1a mark_unfound_lost delete
pg has 1 objects unfound and apparently lost marking
```

 OSD_TOO_MANY_REPAIRS: に対しては、RedHatのドキュメントでは、強制的にメッセージを消去できそうな clear_shards_repaired が紹介されていますが、一般のcephでは提供されていないオプションのようです。

``osd repair <who>`` を試してみます。

```bash:
# ceph osd repair all
instructed osd(s) 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 to repair
```

これで、いくらかエラーは減っていき、次のようになりました。

```bash:
# ceph health detail
HEALTH_ERR 864 scrub errors; Too many repaired reads on 5 OSDs; Possible data damage: 6 pgs inconsistent; 3 sl
ow ops, oldest one blocked for 1627269 sec, daemons [osd.1,osd.2] have slow ops.
[ERR] OSD_SCRUB_ERRORS: 864 scrub errors
[WRN] OSD_TOO_MANY_REPAIRS: Too many repaired reads on 5 OSDs
    osd.3 had 16 reads repaired
    osd.1 had 18 reads repaired
    osd.7 had 31 reads repaired
    osd.2 had 32 reads repaired
    osd.4 had 35 reads repaired
[ERR] PG_DAMAGED: Possible data damage: 6 pgs inconsistent
    pg 11.6 is active+clean+inconsistent, acting [3,0,1]
    pg 11.9 is active+clean+inconsistent, acting [4,1,7]
    pg 11.c is active+clean+inconsistent, acting [7,4,1]
    pg 11.14 is active+clean+inconsistent, acting [1,4,3]
    pg 11.1b is active+clean+inconsistent, acting [1,2,0]
    pg 11.1d is active+clean+inconsistent, acting [1,11,3]
[WRN] SLOW_OPS: 3 slow ops, oldest one blocked for 1627269 sec, daemons [osd.1,osd.2] have slow ops.
```

しばらくすると、PG_DAMAGEDは全て消えて、OSD_TOO_MANY_REPAIRSだけが残りました。

```bash:
# ceph health detail
HEALTH_WARN Too many repaired reads on 5 OSDs; 3 slow ops, oldest one blocked for 1627335 sec, daemons [osd.1,
osd.2] have slow ops.
[WRN] OSD_TOO_MANY_REPAIRS: Too many repaired reads on 5 OSDs
    osd.3 had 16 reads repaired
    osd.1 had 18 reads repaired
    osd.7 had 31 reads repaired
    osd.2 had 32 reads repaired
    osd.4 had 35 reads repaired
[WRN] SLOW_OPS: 3 slow ops, oldest one blocked for 1627335 sec, daemons [osd.1,osd.2] have slow ops.


# ceph status
  cluster:
    id:     454d7e30-a1f5-4369-b1e5-6b9b2700054c
    health: HEALTH_WARN
            Too many repaired reads on 5 OSDs
            3 slow ops, oldest one blocked for 1627340 sec, daemons [osd.1,osd.2] have slow ops.
 
  services:
    mon: 3 daemons, quorum a,b,c (age 2w)
    mgr: a(active, since 2w)
    mds: myfs:1 {0=myfs-b=up:active} 1 up:standby-replay
    osd: 16 osds: 16 up (since 2w), 16 in (since 2w)
    rgw: 1 daemon active (my.store.a)
 
  task status:
 
  data:
    pools:   11 pools, 177 pgs
    objects: 343 objects, 184 MiB
    usage:   18 GiB used, 29 TiB / 29 TiB avail
    pgs:     177 active+clean
 
  io:
    client:   5.7 KiB/s rd, 426 B/s wr, 6 op/s rd, 2 op/s wr
```

ここから、``osd purge <id|osd.id> [--force] [--yes-i-really-mean-it]`` を試してみます。


```bash:
# ceph osd down osd.1
marked down osd.1. 
# ceph osd down osd.2
marked down osd.2. 

# ceph status
  cluster:
    id:     454d7e30-a1f5-4369-b1e5-6b9b2700054c
    health: HEALTH_WARN
            Too many repaired reads on 4 OSDs
            2 slow ops, oldest one blocked for 1627677 sec, osd.2 has slow ops
 
  services:
    mon: 3 daemons, quorum a,b,c (age 2w)
    mgr: a(active, since 2w)
    mds: myfs:1 {0=myfs-b=up:active} 1 up:standby-replay
    osd: 16 osds: 16 up (since 76s), 16 in (since 2w)
    rgw: 1 daemon active (my.store.a)
 
  task status:
 
  data:
    pools:   11 pools, 177 pgs
    objects: 343 objects, 184 MiB
    usage:   18 GiB used, 29 TiB / 29 TiB avail
    pgs:     177 active+clean
 
  io:
    client:   3.5 KiB/s rd, 511 B/s wr, 4 op/s rd, 3 op/s wr
```



# Rook/Cephを導入したらosdが沢山作られた

新規に構築したk8sクラスターにRook/Cephを導入したところ、本来4台に一つずつのBlueStore(HDD)しかないはずなのに6つのOSDが作成されてしまいました。

原因はOS導入時に使用したAutoInstallを走らせるUSBメモリーが差し込まれたままになっていた事で、ISO9660イメージだからCD-ROM扱いされて無視されるかなと思っていたのですが、システムでは/dev/sdcとして認識されていて、OSDが起動したようです。

当然、USBメモリーは回収されるため、その後は/dev/sdcそのものが存在しないことで、OSDが起動できずにエラーとなっています。

```bash:
$ sudo kubectl -n rook-ceph get pod -l osd
NAME                               READY   STATUS                  RESTARTS          AGE
rook-ceph-osd-0-5557b5c888-lj9x8   1/1     Running                 2 (16h ago)       6d15h
rook-ceph-osd-1-66bcb89669-ch5bx   1/1     Running                 2 (16h ago)       6d15h
rook-ceph-osd-2-9b8b5ff5b-44kbz    1/1     Running                 2 (16h ago)       6d15h
rook-ceph-osd-3-59bcb68f97-g9nl9   0/1     Init:CrashLoopBackOff   177 (24s ago)     14h
rook-ceph-osd-4-6745cf4d86-7vnht   0/1     Init:CrashLoopBackOff   192 (3m4s ago)    6d15h
rook-ceph-osd-5-f6cc674f4-6sp5q    1/1     Running                 2 (16h ago)       6d15h
rook-ceph-osd-6-f776bf965-xqbrg    0/1     Init:CrashLoopBackOff   175 (3m20s ago)   14h
```

## 環境

* Rook v1.9.10 (ceph 16.2.10)
* Kubernetes v1.23.7

## 作業手順

今回はBlueStoreの初期化などは不要で、そもそもPGsを構成していない不要なOSDだと分かっているので、影響を受けるPVがないという前提で作業を行ないます。

[公式ガイド Ceph OSD Management](https://www.rook.io/docs/rook/v1.9/Storage-Configuration/Advanced/ceph-osd-mgmt/)と[公式ガイド Ceph Configuration](https://www.rook.io/docs/rook/v1.9/Storage-Configuration/Advanced/ceph-configuration/)に従って単純に不要なOSD (ID: 3,4,6) を削除していきます。

1) Operatorの停止
2) ToolBoxからceph osd downの実行
3) ToolBoxからceph osd out/crush remove/auth del/rmの実行
4) OSDに対応するDeploymentオブジェクトの削除 (removeOSDsIfOutAndSafeToRemove: trueが設定されていない場合)
5) Operatorの復帰

### Operatorの停止

```bash:operatorの停止
$ sudo kubectl -n rook-ceph scale deployment rook-ceph-operator --replicas=0
```

### ToolBoxからceph osd downの実行

```bash:toolbox
$ sudo kubectl -n rook-ceph exec -it rook-ceph-tools-7d59b6df78-tlqrb -- bash
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd down osd.3
osd.3 is already down. 
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd down osd.4
osd.4 is already down. 
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd down osd.6
osd.6 is already down
```

### ToolBoxからceph osd out/crush remove/auth del/rmの実行

```bash:引き続きToolBoxでの作業
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd out osd.6
marked out osd.6. 
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd out osd.4
osd.4 is already out. 
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd out osd.3
osd.3 is already out.

[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd crush remove osd.3
removed item id 3 name 'osd.3' from crush map
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd crush remove osd.4
removed item id 4 name 'osd.4' from crush map
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd crush remove osd.6
removed item id 6 name 'osd.6' from crush map

[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph auth del osd.3
updated                             
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph auth del osd.4 
^Pupdated                           
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph auth del osd.6 
updated

[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd rm osd.3
removed osd.3
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd rm osd.4
removed osd.4
[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ ceph osd rm osd.6
removed osd.6

[rook@rook-ceph-tools-7d59b6df78-tlqrb /]$ exit
exit
$ 
```

### 対応するDeploymentオブジェクトの削除

```bash:
$ sudo kubectl -n rook-ceph delete deploy rook-ceph-osd-3
deployment.apps "rook-ceph-osd-3" deleted
$ sudo kubectl -n rook-ceph delete deploy rook-ceph-osd-4
deployment.apps "rook-ceph-osd-4" deleted
$ sudo kubectl -n rook-ceph delete deploy rook-ceph-osd-6
deployment.apps "rook-ceph-osd-6" deleted
```

### Operatorの復帰

```bash:
$ sudo kubectl -n rook-ceph scale deployment rook-ceph-operator --replicas=1
deployment.apps/rook-ceph-operator scaled
```

## 結果の確認

またToolBoxに入って、ceph statusの確認を行います。

```text:cephコマンドのstatus出力
  cluster:
    id:     8c9c83ef-4694-42b9-8cc7-cbb4a529e384
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum a,b,c (age 17h)
    mgr: a(active, since 17h), standbys: b
    osd: 4 osds: 4 up (since 17h), 4 in (since 41m); 2 remapped pgs
    rgw: 1 daemon active (1 hosts, 1 zones)
 
  data:
    pools:   9 pools, 113 pgs
    objects: 2.92k objects, 7.1 GiB
    usage:   16 GiB used, 3.6 TiB / 3.6 TiB avail
    pgs:     125/8769 objects misplaced (1.425%)
             111 active+clean
             1   active+remapped+backfilling
             1   active+remapped+backfill_wait
 
  io:
    client:   7.5 KiB/s rd, 204 KiB/s wr, 1 op/s rd, 1 op/s wr
    recovery: 6.5 MiB/s, 6 objects/s
```

ceph osd treeの出力は次のようになっています。

```text:
ID  CLASS  WEIGHT   TYPE NAME         STATUS  REWEIGHT  PRI-AFF
-1         3.63879  root default                               
-5         0.90970      host s10rx61                           
 1    hdd  0.90970          osd.1         up   1.00000  1.00000
-9         0.90970      host s10rx62                           
 5    hdd  0.90970          osd.5         up   1.00000  1.00000
-7         0.90970      host s10rx63                           
 2    hdd  0.90970          osd.2         up   1.00000  1.00000
-3         0.90970      host s10rx64                           
 0    hdd  0.90970          osd.0         up   1.00000  1.00000
```