PVC-based の Rook/Ceph で osd に紐付いた PV を入れ替える

# 免責

たぶん執筆時点では合理的な手順と思っているが、この手順を真似して何らかの損害が発生したとしても、責任は持てない。
そして将来の Rook では、もっと簡単な手順になる可能性は低くないと思っている。

# この作業が必要になりそうな動機

osd 毎に与える PV のサイズをシュリンクしたいとか。
何らかのストレージ障害で、PV が再起不能になったとか。

# 環境

```
kubectl exec -it -n rook-ceph deploy/rook-ceph-tools -- ceph version
ceph version 17.2.5 (98318ae89f1a893a6ded3a640405cdbb33e08757) quincy (stable)
```

```
kubectl get deploy -n rook-ceph rook-ceph-operator -o jsonpath='{.spec.template.spec.containers[0].image}'
rook/ceph:v1.11.4
```

# 手順

## Ceph クラスタが正常であることを確認する。

作業前に、 Ceph クラスタに異常がないことを確認する。
Ceph クラスタは不健康な状態でも、なんとなく動いてしまっていたりするので。

```
kubectl exec -it deploy/rook-ceph-tools -n rook-ceph -- ceph health
```

`HEALTH_OK` が出たら次のステップに進んで良い。
`HEALTH_WARN` や `HEALTH_ERR` が出ている場合は、その解決を行う必要がある。

## 削除対象としたい PVC を見つける。

本文書では、例として、 set1 に含まれるもの対象とする。(適宜読み替え。以下同様)

```
kubectl -n rook-ceph get pvc -l ceph.rook.io/DeviceSet=set1
```

今回はこの 700Gi のストレージ `set-1-data-1pnmvs` を入れ替え対象とする。

```
NAME               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
set1-data-1pnmvs   Bound    pvc-77599c50-ad58-42aa-acb2-ddcf019bbed7   700Gi      RWO            default            26d
set1-data-3cf4xv   Bound    pvc-430cc274-1418-4543-bd72-20faaf477da1   300Gi      RWO            managed-standard   24h
(以下略)
```

# PVC に紐付いた osd を取得する。

まずこの OSD を代表する Deployment を特定する。

```
kubectl -n rook-ceph get deploy -l ceph.rook.io/pvc=set1-data-1pnmvs -o name
```

下記の通り、`rook-ceph-osd-2` と判明した。 

```
deployment.apps/rook-ceph-osd-2
```

つづいて入れ替え対象となる OSD のidを特定する。

```
kubectl -n rook-ceph get deploy rook-ceph-osd-2 -o jsonpath='{.metadata.labels.ceph-osd-id}'
```

結果、下記のように、osd の id は `2` と判明した。

```
2
```



## 対象となる osd を out させる

```
kubectl exec -it deploy/rook-ceph-tools -n rook-ceph -- ceph osd out osd.2
```

即座にメッセージが帰る。

```
marked out osd.2. 
```

ちなみにここで `down` させても効果は無い。operator が osd を `up` に戻すので。

## HEALTH_OK を待つ。

```
kubectl exec -it deploy/rook-ceph-tools -n rook-ceph -- ceph health
```

`HEALTH_OK` が出たら次のステップに進んで良い。

### `HEALTH_WARN` が出た場合。

`HEALTH_WARN` が出た場合には、status を確認する。

```
kubectl exec -it deploy/rook-ceph-tools -n rook-ceph -- ceph status
```

ありがちなのが、OSD を out したことで、クラスタ全体の空き容量が足りなくなるケース。その場合は、こんなメッセージが現れる。

```
    health: HEALTH_WARN
            Low space hindering backfill (add storage if this doesn't resolve itself): 44 pgs backfill_toofull
            Degraded data redundancy: 1 pg degraded
```

当面の対策としては、OSD を in し直す。たとえば、こんな感じ。

```
kubectl exec -it deploy/rook-ceph-tools -n rook-ceph -- ceph osd in osd.2
```

out できないと入れ替えは無理なので、下記対応が必要となる。

* (一時的にでも) OSD を増やす。
* 使っていなかったり一時的なバックアップを取れる RBD や CephFS を消して、RADOS の空き容量を増やす。

### `HEALTH_ERR` が出た場合。

ほぼ出現する可能性はないはず。
…が、万が一にも出た場合には、緊急事態なので、ステークホルダへの通知など必要に応じて行う。

## (念のため) mispaced object の解消まで待つ。

このステップは、急ぎなら飛ばしてもよい…が、万全を期すなら行ったほうが良い。
ひたすら画面を見ていても非生産的なので、下記ワンライナーが便利。コマンドプロンプトに帰ってくるまで放置しておく。

```
#!/bin/bash
while true; do kubectl exec -t deploy/rook-ceph-tools -n rook-ceph -- ceph status | grep misplaced || break; sleep 60; done
```

## PVC の削除を指示する。

```
kubectl delete pvc -n rook-ceph --wait=false set1-data-1pnmvs
```

deployment の削除前に PVC を削除するのが重要。rook-ceph-operator は PVC に付いているラベルを見て deployment を生成する。よって、deployment だけ消しても、新たに deployment が生成されるという堂々巡りになる。

また、PVC を delete しても、PVC は pod にマウントされているので、削除が完了せずコマンドプロンプトに帰ってこない。回避のため `--wait=false` を明示し、削除完了を確認せずに kubectl を終了させるようにする。

## osd を起動している deployment を削除する。

```
kubectl delete deploy -n rook-ceph rook-ceph-osd-2 
```

deploument が生成した pod がマウントしていた PVC は、この時点で削除される。

## osd をクラスタから外す

osd を実行している Pod の termination が完了したのを確認したら osd をクラスタから外す。

```
kubectl exec -it deploy/rook-ceph-tools -n rook-ceph -- ceph osd purge osd.2 --force
```

ここで down してないというエラーが帰ってくる場合、ここまでの手順に沿えていないので、はじめからやり直す必要がある。


## 首尾よく作業完了していれば…

operator が、消えた osd.2 のための PVC や Deployment といったリソースを生成し、osd.2 は ceph の CRUSH map に追加される。