Db2 for OpenShift/Kubernetes の Storage Snapshot 取得手順

## はじめに
OpenShift/Kubernetes環境でDb2を動かすには、マイクロサービスとして開発される、k8s環境専用のDb2製品を導入します。
このDb2は、[Db2 for Red Hat OpenShift and Kubernetes](https://www.ibm.com/docs/en/db2/11.5?topic=deployments-db2-rhos-k8s)、別名Db2Uとも呼ばれます。
Db2として公式の Kubernetes Operator が提供されています。

Db2 for OpenShift のバックアップには、いくつかの方法が提供されます。
 * [BACKUPコマンド(従来のオンプレミス版Db2とほぼ同じ)](https://www.ibm.com/docs/en/db2/11.5?topic=up-online-backup)
 * [ストレージ機能を利用したスナップショット](https://www.ibm.com/docs/en/db2/11.5?topic=up-performing-snapshot-backup-db2-container-commands)
 * [Velero (Kubernetes環境に特化したバックアップツール)](https://www.ibm.com/docs/en/db2/11.5?topic=db2-velero-backup-restore)
 * Db2バックアップ用に提供されるカスタムリソース [Db2uBackup](https://www.ibm.com/support/pages/node/6962831), [Db2uRestore](https://www.ibm.com/support/pages/node/6962833) (2023.03時点 TechPreview)

このうち、ストレージ機能を利用した[スナップショット取得](https://www.ibm.com/docs/en/db2/11.5?topic=up-performing-snapshot-backup-db2-container-commands)と[リストア](https://www.ibm.com/docs/en/db2/11.5?topic=restoring-performing-snapshot-restore-db2-container-commands)を試すことができたので、この手順を備忘録として残します。
スナップショット取得/リストアの操作はコマンドラインでも実行可能ですが、オプション指定が不要で使い勝手の良いGUI(OCP Webコンソール)を利用します。



## 環境

### 全体構成
 * Red Hat OpenShift Kubernetes Service (ROKS) 上に Db2 for OpenShift をデプロイ
 * 最小構成である、2つのPVCにDb2関連データを保持する構成とする
     * ユーザデータ、トランザクションログ、メタデータ等を配置するため
     * より多くのPVCに分散配置し、I/Oを分散させる構成も可能 → [Link](https://qiita.com/mi-kana/items/82ad881172b715b73ffe))
 * ストレージは、[OpenShift Data Foundation](https://access.redhat.com/documentation/ja-jp/red_hat_openshift_data_foundation/4.10/html/planning_your_deployment/odf-architecture_rhodf) を利用

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/f5a575cc-3fdf-98d6-89e3-6b14bbfd830e.png)


| コンポーネント | バージョン |
|:-:|:-:|
| OpenShift  | 4.10.52  |
| OpenShift Data Foundation  |odf-operator.v4.10.9   |
| Db2 for OpenShift  | s11.5.8.0  |

参考：[Db2マニュアル Db2 for RHOS and K8s > 11.5.8 > Installing Db2](https://www.ibm.com/docs/en/db2/11.5?topic=1158-installing-db2)

### ボリュームスナップショットクラス
cephfs用、cephrbd用のスナップショットクラスを利用してSnapshot取得、リストアを行います。
```
root@IBM-PF2E8K5F:~# oc get volumesnapshotclass
NAME                                        DRIVER                                  DELETIONPOLICY   AGE
ocs-storagecluster-cephfsplugin-snapclass   openshift-storage.cephfs.csi.ceph.com   Delete           35d
ocs-storagecluster-rbdplugin-snapclass      openshift-storage.rbd.csi.ceph.com      Delete           35d
root@IBM-PF2E8K5F:~#
```

## Snapshot取得検証

### 全体の流れ

以下の流れで取得します。
Snapshotを取得した後、データを追加しておきます。(ユーザミスにより不要データが混入した状態とみなす)
取得したSnapshotのリストアにより、この不要なデータは消えて元の状態に戻ったことを確認します。

1. 検証開始前のデータ内容確認
2. Snapshot取得
3. Snapshot取得後のデータ編集
4. リストア
5. リストア後のデータ内容確認



### Step1. 検証開始前のデータ内容確認
T1表に1行のみ格納した状態でSnapshotを取得します。
```
[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$ db2 "select * from t1"

C1          C2                               C3

----------- -------------------------------- --------------------------
          1 before snapshot                  2023-02-28-06.56.11.996187

  1 record(s) selected.
```



### Step2. Snapshot取得
スナップショット取得にあたり、静止点を作る必要があります。
この点は従来からあるオンプレミス版Db2と同じです。
Db2 for OpenShift/Kubernetes環境においてDb2によるデータ領域へのwrite処理を静止するための専用コマンドが用意されています。書き込み処理をサスペンドしている間に、Snapshotを取得します。

以下のマニュアルに従って進めます。
[Performing a snapshot backup with Db2 container commands](
https://www.ibm.com/docs/en/db2/11.5?topic=up-performing-snapshot-backup-db2-container-commands)

#### Step2-1. 書き込み処理の静止

```
date ; oc exec -it c-db2ucluster-2-db2u-0 -- manage_snapshots --action suspend
2023年  2月 28日 火曜日 16:00:19 JST
Defaulted container "db2u" out of: db2u, init-labels (init), init-kernel (init)
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
Wolverine HA management state was disabled successfully.

connect to SAMPLEDB

   Database Connection Information

 Database server        = DB2/LINUXX8664 11.5.8.0
 SQL authorization ID   = DB2INST1
 Local database alias   = SAMPLEDB


terminate
DB20000I  The TERMINATE command completed successfully.

*************************************************

Suspending write on the databases...this may take a while
Database Member 0 -- Database SAMPLEDB -- Active -- Up 10 days 19:56:36 -- Date 2023-02-28-07.00.29.315480
Database is in write suspend state NO                   NO
Database: SAMPLEDB
Validating if write suspend on SAMPLEDB was successful ...
Database Member 0 -- Database SAMPLEDB -- Active -- Up 10 days 19:56:43 -- Date 2023-02-28-07.00.36.896384
Database is in write suspend state YES                  YES

*************************************************
Successfully suspended writes on the database(s)
*************************************************
```

db2diag.logにも、write suspended が実行された際のログが出力されます。
出力量が多いため、当記事末尾に添付します。


#### Step2-2. Db2 HA モニターを停止
Db2 for OpenShift/Kubernetes同梱のHAモニターを停止します。
```
date ; oc exec -it c-db2ucluster-2-db2u-0 -- wvcli system status
2023年  2月 28日 火曜日 16:00:59 JST
Defaulted container "db2u" out of: db2u, init-labels (init), init-kernel (init)
HA Management is DISABLED at 2023-02-28 07:01:02.657.
root@IBM-PF2E8K5F:~#
```


#### Step2-3. ODF Snapshot取得（VolumeSnapshot作成）

ストレージスナップショットをOCP Webコンソールから取得します。
Db2マニュアルでは、各ストレージ製品のマニュアルを参照するようガイドされます。
今回はODFを利用するためODFのスナップショット作成手順に従い作業します。
[Documentation > OpenShift Container Platform > Storage Using Container Storage Interface (CSI) > CSI volume snapshot > Creating a volume snapshot](https://docs.openshift.com/container-platform/4.12/storage/container_storage_interface/persistent-storage-csi-snapshots.html#persistent-storage-csi-snapshots-create_persistent-storage-csi-snapshots)

##### Step2-3-1. メタデータ用領域のSnapshot取得
左メニューリストより、ストレージ ＞ ボリュームスナップショットを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/a8a70273-8646-98ea-940d-19796a00158e.png)

「ボリュームスナップショットの作成」を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/d01b7ca9-b084-5960-380f-9c6269e502ae.png)

「永続ボリューム要求」のドロップダウンリストから、Db2が利用するPVCを選択
　※ 複数あるため、利用するPVCについて同じ作業を繰り返します。(順不同)
 
| PVC |Db2uClusterデプロイ時のPVC名 | 
|:-|:-|
| メタデータ用PVC  | c-db2ucluster-2-meta  |
|  データ用PVC | data-c-db2ucluster-2-db2u-0  |  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/9a917e66-3498-9d34-5bb4-e11d39a49884.png)

Db2メタデータ用PVCのバックアップを取得
 * PVCを選択すると、スナップショット名もスナップショットクラスも自動選択される
     * cephfs：ocs-storagecluster-cephfsplugin-snapclass
     * cephrdb：ocs-storagecluster-rbdplugin-snapclass

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/7a0fb059-823b-495a-c78d-82f8a262e514.png)

取得中の画面：
「作成した時間」が「進行中」と表記されます。1分程度で遷移します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/9c9f724d-b75a-8a37-503b-531c631bc7cf.png)

取得されたスナップショットは、「ボリュームスナップショット」の画面で確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/86ecb747-356f-9ce8-b81e-308a0d41c642.png)

##### Step2-3-2. データ用領域のSnapshot取得
手順は、「Step2-3-1. メタデータ用領域のSnapshot取得」と同一のため割愛します
 * スナップショットクラス：ocs-storagecluster-rbdplugin-snapclass
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/6e435ae9-3b38-6ddb-c99b-061d72052355.png)

(Snapshot取得完了後のWebコンソール画面。2つのPVCのボリュームスナップショットが取得済)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/1791ce34-bb3d-e7a2-294e-6074510a54ea.png)


##### Step2-3-3. (蛇足) 書き込み静止中のSQL実行可否を確認
従来のオンプレミス版Db2であれば、以下のようになります。Db2Uでも同様か、確認しました。
 * 表スペース、ログ領域への書き込みを伴わない読取処理(SELECT文など)　→　実行可能
 * 上記を伴う書き込み処理(INSERT文など) → 待機させられる

結果としてはオンプレミス版同様の挙動となりました。

```SELECT文は即時実行結果が戻された
[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$ db2 "select * from t1"

C1          C2                               C3

----------- -------------------------------- --------------------------
          1 before snapshot                  2023-02-28-06.56.11.996187

  1 record(s) selected.

[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$
```


```INSERT文は書き込み解除(Step2-4)まで待機させられる
[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$ db2 "insert into t1 values (2, 'during write suspend' , current timestamp)" 
　　　　←--- 待機させられる
　　　　←--- 後続 Step2-4. の Write Suspend Resume コマンド実行中にDB20000I メッセージが戻りINSERT完了
DB20000I  The SQL command completed successfully.
[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$
```

(事後確認結果：INSERT文はWRITE SUSPEND中は待機させられていたが、無事完了)
```
[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$ date ; db2 "select * from t1"
Tue Feb 28 07:25:55 UTC 2023
C1          C2                               C3
----------- -------------------------------- --------------------------
          1 before snapshot                  2023-02-28-06.56.11.996187
          2 during write suspend             2023-02-28-07.19.10.095425

  2 record(s) selected.

[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$
```

#### Step2-4. 書き込み静止の解除

```
date ; oc exec -it c-db2ucluster-2-db2u-0 -- manage_snapshots --action resume
2023年  2月 28日 火曜日 16:20:57 JST
Defaulted container "db2u" out of: db2u, init-labels (init), init-kernel (init)
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

connect to SAMPLEDB

   Database Connection Information

 Database server        = DB2/LINUXX8664 11.5.8.0
 SQL authorization ID   = DB2INST1
 Local database alias   = SAMPLEDB

terminate
DB20000I  The TERMINATE command completed successfully.

connect to SAMPLEDB

   Database Connection Information

 Database server        = DB2/LINUXX8664 11.5.8.0
 SQL authorization ID   = DB2INST1
 Local database alias   = SAMPLEDB

terminate
DB20000I  The TERMINATE command completed successfully.

*************************************************
Resuming write on SAMPLEDB...this may take a while

   Database Connection Information

 Database server        = DB2/LINUXX8664 11.5.8.0
 SQL authorization ID   = DB2INST1
 Local database alias   = SAMPLEDB

DB20000I  The SET WRITE command completed successfully.
connect to SAMPLEDB

   Database Connection Information

 Database server        = DB2/LINUXX8664 11.5.8.0
 SQL authorization ID   = DB2INST1
 Local database alias   = SAMPLEDB

terminate
DB20000I  The TERMINATE command completed successfully.

Successfully resumed write on SAMPLEDB
*************************************************

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
Wolverine HA management state was enabled successfully.
```

※上記のとおりコマンド出力として下記メッセージが出力されますが、この間、db2diag.logには何もメッセージが出ません。ただしこのコマンド実行中に、仕掛けておいたINSERT文も成功しているので書き込み静止状態の解除処理は想定どおり実行されているようです。
> DB20000I  The SET WRITE command completed successfully.


#### Step2-5. Db2 HA モニターの再開
Db2 for OpenShift/Kubernetes同梱のHAモニターを開始します。
```
date ; oc exec -it c-db2ucluster-2-db2u-0 -- wvcli system status
2023年  2月 28日 火曜日 16:26:14 JST
Defaulted container "db2u" out of: db2u, init-labels (init), init-kernel (init)
HA Management is RUNNING at 2023-02-28 07:26:17.920.
```


### Step3. Snapshot取得後のデータ編集
WRITE SUSPEND状態を解除しHAモニターを再開した状態で、データベースに更新(新規データ追加)を行います。

```
◆データ行追加
[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$ date ; db2 "insert into t1 values (3, 'after snapshot', current timestamp)"
Tue Feb 28 07:27:51 UTC 2023
DB20000I  The SQL command completed successfully.

◆データ確認
[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$ date ; db2 "select * from t1 order by c3"
Tue Feb 28 07:28:09 UTC 2023
C1          C2                               C3
----------- -------------------------------- --------------------------
          1 before snapshot                  2023-02-28-06.56.11.996187
          2 during write suspend             2023-02-28-07.19.10.095425
          3 after snapshot                   2023-02-28-07.27.51.146033  ← 追加されている
  3 record(s) selected.

[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$
```

### Step4. リストア
PVC Snapshotリストアにあたっては、[Db2マニュアル](https://www.ibm.com/docs/en/db2/11.5?topic=restoring-performing-snapshot-restore-db2-container-commands)に記載される通り、事前にDb2クラスタをメンテナンスモードとし、すべてのPodを停止(replicas数=0)しておく必要があります。

ODF Snapshotのリストア作業自体は、以下のマニュアルに従って進めます。
[Performing a snapshot restore with Db2 container commands in Db2](
https://www.ibm.com/docs/en/db2/11.5?topic=restoring-performing-snapshot-restore-db2-container-commands)

Step4-2で設定するOS環境変数はリストア操作を通じて利用することになるため、リストア作業が終わるまで同じターミナルを利用しつづけるほうが楽です。

#### Step4-1. Db2クラスタをメンテナンスモードにする
```
date ; oc annotate db2ucluster $DB2U_CLUSTER db2u.databases.ibm.com/maintenance-pause-reconcile=true --overwrite
2023年  2月 28日 火曜日 19:55:36 JST
db2ucluster.db2u.databases.ibm.com/db2ucluster-2 annotated
```

#### Step4-2. Deployment 停止

Db2UではDb2エンジン本体のPodだけでなく、LDAP, etcdなど複数種類のPodが連動しサービス提供を行うものです。
Db2uClusterカスタムリソース配下すべてのDepoyment/StatefulSetのレプリカ数を0に変更し、Podを停止します。

Db2uClusterカスタムリソース名をOS環境変数にセットします
```
DB2U_CLUSTER=db2ucluster-2
```

Db2uClusterのStatefulSet名称を取得します（→c-db2ucluster-2-db2u）
```
DB2U_STS=$(oc get sts --selector="app=${DB2U_CLUSTER},type=engine" --no-headers | awk '{print $1}');echo $DB2U_STS
c-db2ucluster-2-db2u
```
Db2uエンジン本体(StatefulSet)のレプリカ数を取得し、OS環境変数にセットします
（→NEW_REPLICAS=1）
```
NUM_REPLICAS=$(oc get sts ${DB2U_STS} -ojsonpath={.spec.replicas}) ; echo $NUM_REPLICAS
1
```
Db2U StatefulSetのレプリカ数を0に変更しPodを停止します
```
date ; oc scale sts ${DB2U_STS} --replicas=0
2023年  2月 28日 火曜日 20:03:59 JST
statefulset.apps/c-db2ucluster-2-db2u scaled
```

etcdのStatefulSet名を取得します（→ c-db2ucluster-2-etcd）
```
ETCD_STS=$(oc get sts --selector="app=${DB2U_CLUSTER},component=etcd" --no-headers | awk '{print $1}'); echo $ETCD_STS
c-db2ucluster-2-etcd
```
etcd StatefulSetのレプリカ数を0に変更しPodを停止します
```
date ; oc scale sts ${ETCD_STS} --replicas=0
2023年  2月 28日 火曜日 20:04:07 JST
statefulset.apps/c-db2ucluster-2-etcd scaled
```

LDAP Deploymentのレプリカ数を0に変更しPodを停止します
```
date ; oc scale deploy c-db2ucluster-2-ldap --replicas=0
2023年  2月 28日 火曜日 20:28:51 JST
deployment.apps/c-db2ucluster-2-ldap scaled
```
※今回検証した時点ではDb2マニュアルに不備がありLDAP Deploymentを停止する手順がありませんでした。事後(リストア失敗後)にLDAPレプリカ数を0としたため、タイムスタンプが他と一致しません。

マニュアルに提示される、"role=tools"に該当するDeploymentは今回の環境には存在しないため、Deployment停止(レプリカ数変更)操作の対象外とします
```
TOOLS_DEPLOY=$(oc get deploy --selector="app=${DB2U_CLUSTER},role=tools" --no-headers | awk '{print $1}'); echo $TOOLS_DEPLOY
No resources found in db2u-1 namespace.
```
補足：
マニュアルを見ると、role=toolsに該当するDeploymentが存在する環境ではc-<Deployment-name>-tools-xxxxx というPodが稼働するようでした。
[Enabling the Db2 REST interface](https://www.ibm.com/docs/en/db2/11.5?topic=drs-enabling-db2-rest-interface-2)

#### Step4-3. 既存PVC定義をコピー

リストア対象となるPVC2つにラベルを付与します
```
date ; oc label pvc c-${DB2U_CLUSTER}-meta app=${DB2U_CLUSTER}
2023年  2月 28日 火曜日 20:06:54 JST
persistentvolumeclaim/c-db2ucluster-2-meta labeled
```
PVC定義Yamlのコピーを作成します
```
for PVC in $(oc get pvc -l app=$DB2U_CLUSTER --no-headers | awk '{print $1}'); do oc get pvc $PVC -o yaml > ${PVC}_copy.yaml ; done
```
Yamlファイルが作成されたことを確認します。(Yamlは当記事末尾に添付)
```
ls -ltr
合計 8
-rw-r--r-- 1 root root 1143  2月 28 20:18 c-db2ucluster-2-meta_copy.yaml
-rw-r--r-- 1 root root 1180  2月 28 20:18 data-c-db2ucluster-2-db2u-0_copy.yaml
```

#### Step4-4. 有事に備え、既存PVのReclaim PolicyをRetainに変更
OpenShift(Kubernetes)ではPVCのデフォルトとしてReclaim Policy=Deleteとなっていて、PVCを削除すると紐づけられていたPVは自動削除されます。
ここでは、万が一Snapshotリストア前の状態のデータを復元する必要が生じた場合に備えて、PVC削除後もPVがそのまま残存する構成に変更しておきます。

変更前：Reclaim Policy=Delete
```
date ; oc get pv | grep -i db2ucluster-2
2023年  2月 28日 火曜日 20:21:04 JST
pvc-5c9cd839-470e-47bc-b6e3-190520325572   10Gi       RWO            Delete           Bound    db2u-1/data-c-db2ucluster-2-db2u-0                                   ocs-storagecluster-ceph-rbd                11d
pvc-d2b126cc-a486-419b-b239-39c4e90b2ea6   10Gi       RWX            Delete           Bound    db2u-1/c-db2ucluster-2-meta                                          ocs-storagecluster-cephfs                  11d
```

Reclaim Policy変更：
```
for PV in $(oc get pv --no-headers | grep $DB2U_CLUSTER | awk '{print $1}'); do oc patch pv $PV -p "{\"spec\":{\"persistentVolumeReclaimPolicy\":\"Retain\"}}" ; done
persistentvolume/pvc-5c9cd839-470e-47bc-b6e3-190520325572 patched
persistentvolume/pvc-d2b126cc-a486-419b-b239-39c4e90b2ea6 patched
```

変更後：Reclaim Policy=Retain
```
date ; oc get pv | grep -i db2ucluster-2
2023年  2月 28日 火曜日 20:21:40 JST
pvc-5c9cd839-470e-47bc-b6e3-190520325572   10Gi       RWO            Retain           Bound    db2u-1/data-c-db2ucluster-2-db2u-0                                   ocs-storagecluster-ceph-rbd                11d
pvc-d2b126cc-a486-419b-b239-39c4e90b2ea6   10Gi       RWX            Retain           Bound    db2u-1/c-db2ucluster-2-meta                                          ocs-storagecluster-cephfs                  11d
```


#### Step4-5. 既存PVCの削除

PVCを削除します。
```
date ; oc delete pvc -l app=${DB2U_CLUSTER}
2023年  2月 28日 火曜日 20:22:04 JST
persistentvolumeclaim "c-db2ucluster-2-meta" deleted
persistentvolumeclaim "data-c-db2ucluster-2-db2u-0" deleted
```

PVCが削除されている(→存在しない)ことを確認します。
```
date ; oc get pvc | grep -i db2ucluster-2
2023年  2月 28日 火曜日 20:38:00 JST
　　←--- 出力無となった
root@IBM-PF2E8K5F:~/db2u/pvc#
```

PVはReleased状態として残存していることも確認できました。
```
oc get pv | grep -i db2ucluster-2
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM
                                              STORAGECLASS                      REASON   AGE
(中略)
pvc-5c9cd839-470e-47bc-b6e3-190520325572   10Gi       RWO            Retain           Released   db2u-1/data-c-db2ucluster-2-db2u-0                                   ocs-storagecluster-ceph-rbd                38d
pvc-d2b126cc-a486-419b-b239-39c4e90b2ea6   10Gi       RWX            Retain           Released   db2u-1/c-db2ucluster-2-meta                                          ocs-storagecluster-cephfs                  38d
```
※後日取得のためdateコマンド取得せず


#### Step4-6. 元のnamespaceへ、同名PVCとして、volumesnapshotをリストアする （Webコンソール）
こちらのマニュアルの手順に従い操作します。
[Documentation > OpenShift Container Platform > Storage Using Container Storage Interface (CSI) > CSI volume snapshots > Restoring a volume snapshot](https://docs.openshift.com/container-platform/4.12/storage/container_storage_interface/persistent-storage-csi-snapshots.html#persistent-storage-csi-snapshots-restore_persistent-storage-csi-snapshots)

復元対象は、Db2uClusterからmountされるすべてのPVCです。
今回の環境では下記2つで、特に順序依存性はなく対象PVCをすべて復元します。

| PVC |Db2uClusterデプロイ時のPVC名 | Step2で取得したVolume Snapshot名 |
|:-|:-|:-|
| メタデータ用PVC  | c-db2ucluster-2-meta  |c-db2ucluster-2-meta-snapshot   | 
|  データ用PVC | data-c-db2ucluster-2-db2u-0  | data-c-db2ucluster-2-db2u-0-snapshot  | 


ここではメタデータ用PVCから復元します。

Webコンソールから、ストレージ > ボリュームスナップショット　の画面を開きます。
取得されているボリュームスナップショットの一覧から、
Db2メタデータ用PVC(もしくはデータ)を探し、最右列の縦三点リーダーボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/8de5f39f-a170-699a-6c7f-ef623c4c16d1.png)

「新規PVCとして復元」を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/7ced08c9-546e-007c-bfe6-1f574224357e.png)

復元されるPVCの名前だけ変更します。
(デフォルトでSnapshot取得した場合、元のPVC名末尾に[-snapshot-restore]と付与されているのを削除する)
その他の設定項目は、自動選択されているものを受け入れて「復元」します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/38f025c5-0407-4351-e88c-5807af267ec3.png)

開始直後しばらくは以下のようなPending / 進行中 というステータスとなります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/ef38bd00-ec34-4efd-3fc1-a56f208bfb8c.png)

1分程度でBOUND状態になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/31435ed6-2fe1-5485-9032-4284befe2490.png)

同じ要領で、データ用PVCも復元します。
　　※ PVC名を、元のPVC名に編集すること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/203f7cca-d6b5-62f1-fddb-41158d1ac94d.png)


#### Step4-7. Deployment, StatefulSetの起動

Step4-2.で確認したレプリカ数に戻し、Podを再稼働させます。
今回の環境では、replicas=1　に戻すことになります。

※ 再掲：Snapshotリストア前の確認結果では、db2u(StatefulSet)のレプリカ数は1でした
```text: (再掲) レプリカ数確認結果
NUM_REPLICAS=$(oc get sts ${DB2U_STS} -ojsonpath={.spec.replicas}) ; echo $NUM_REPLICAS
1
```

引き続き同じターミナルで作業しているためNUM_REPLICAS変数は維持されています
```
echo ${NUM_REPLICAS}
1
```
※この環境変数が失われている場合は、`NUM_REPLICAS=1`と設定しなおした上で後続コマンドを実行します。

etcd のレプリカ数を1に戻し、起動します
```
date ; oc scale sts ${ETCD_STS} --replicas=${NUM_REPLICAS}
2023年  2月 28日 火曜日 20:52:55 JST
statefulset.apps/c-db2ucluster-2-etcd scaled
```

ldap のレプリカ数を1に戻し、起動します
```
date ; oc scale deploy c-db2ucluster-2-ldap --replicas=${NUM_REPLICAS}
2023年  2月 28日 火曜日 20:53:13 JST
deployment.apps/c-db2ucluster-2-ldap scaled

```

Db2u (Db2エンジン本体の載るStatefulSet) のレプリカ数を1に戻し、起動します
```
date ; oc scale sts ${DB2U_STS} --replicas=${NUM_REPLICAS}
2023年  2月 28日 火曜日 20:53:19 JST
statefulset.apps/c-db2ucluster-2-db2u scaled
```

稼働状況を取得します。
db2u, ldap, etcd のPodのSTATUSがRunning、READY 1/1の状態となっていて正常稼働状態に復旧できていることが確認できます
```
oc get all

NAME                                         READY   STATUS      RESTARTS     AGE
pod/c-db2ucluster-2-db2u-0                   1/1     Running     0            86s
pod/c-db2ucluster-2-etcd-0                   1/1     Running     0            112s
pod/c-db2ucluster-2-instdb-2tlpk             0/1     Completed   0            11d
pod/c-db2ucluster-2-ldap-557898d945-2kr4r    1/1     Running     0            94s
pod/c-db2ucluster-2-restore-morph-kwn5d      0/1     Completed   0            11d
pod/db2u-operator-manager-74c8746449-ncplx   1/1     Running     1 (8d ago)   25d

NAME                                         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/c-db2ucluster-2-db2u                 ClusterIP   172.21.229.55    <none>        50000/TCP,50001/TCP,25000/TCP,25001/TCP,25002/TCP,25003/TCP,25004/TCP,25005/TCP   11d
service/c-db2ucluster-2-db2u-engn-svc        NodePort    172.21.173.50    <none>        50000:30770/TCP,50001:31605/TCP                                                   11d
service/c-db2ucluster-2-db2u-head-engn-svc   NodePort    172.21.236.242   <none>        50000:31406/TCP,50001:31701/TCP                                                   11d
service/c-db2ucluster-2-db2u-internal        ClusterIP   None             <none>        50000/TCP,9443/TCP,50052/TCP                                                      11d
service/c-db2ucluster-2-etcd                 ClusterIP   None             <none>        2379/TCP,2380/TCP                                                                 11d
service/c-db2ucluster-2-ldap                 ClusterIP   172.21.124.70    <none>        50389/TCP
                                                                                  11d

NAME                                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/c-db2ucluster-2-ldap    1/1     1            1           11d
deployment.apps/db2u-operator-manager   1/1     1            1           25d

NAME                                               DESIRED   CURRENT   READY   AGE
replicaset.apps/c-db2ucluster-2-ldap-557898d945    1         1         1       11d
replicaset.apps/db2u-operator-manager-74c8746449   1         1         1       25d

NAME                                    READY   AGE
statefulset.apps/c-db2ucluster-2-db2u   1/1     11d
statefulset.apps/c-db2ucluster-2-etcd   1/1     11d

NAME                                      COMPLETIONS   DURATION   AGE
job.batch/c-db2ucluster-2-instdb          1/1           16s        11d
job.batch/c-db2ucluster-2-restore-morph   1/1           11m        11d
```

#### Step4-8. 書き込み静止状態の解除
Snapshotを取得したタイミングでは、書き込み静止処理が行われた状態となっているため、これを解除します。
manage_snapshots --action restore コマンドの実行により以下のような操作が行われるようです。
 * RESTART DATABASE コマンドの実行
 * 書き込み静止状態の解除
 * データベース活動化
 * HAモニターの有効化

Db2uのエンジンのPod名を取得します
```
CATALOG_POD=$(oc get po -l name=dashmpp-head-0,app=${DB2U_CLUSTER} --no-headers | awk '{print $1}') ; echo ${CATALOG_POD}

c-db2ucluster-2-db2u-0
```

manage_snapshots --action restore コマンド実行します
```
date ; oc exec -it ${CATALOG_POD} -- manage_snapshots --action restore
2023年  2月 28日 火曜日 20:57:49 JST
Defaulted container "db2u" out of: db2u, init-labels (init), init-kernel (init)
/db2u/.db2u_initialized
WV is not running yet...sleep 30
WV is not running yet...sleep 30
*************************************************
Restart and activate the database(s)...this may take a while
Wolverine HA management state was disabled successfully.
DB20000I  The RESTART DATABASE command completed successfully.
activate db SAMPLEDB
SQL1493N  The command failed because the application is already connected to
an active database.

Database was activated successfully
connect to SAMPLEDB

   Database Connection Information

 Database server        = DB2/LINUXX8664 11.5.8.0
 SQL authorization ID   = DB2INST1
 Local database alias   = SAMPLEDB

terminate
DB20000I  The TERMINATE command completed successfully.

Successfully resumed writes and activated SAMPLEDB

*************************************************
Wolverine HA management state was enabled successfully.
```
※db2diag.logに下記メッセージが出力されます。
> ADM6045I  The database is no longer in the WRITE SUSPEND state.


#### Step4-9. メンテナンスモードの終了
リストア処理冒頭でメンテナンスモードに設定していたため、これを解除します。
```
date ; oc annotate db2ucluster $DB2U_CLUSTER db2u.databases.ibm.com/maintenance-pause-reconcile=true --overwrite
2023年  2月 28日 火曜日 21:38:55 JST
db2ucluster.db2u.databases.ibm.com/db2ucluster-2 annotated
```

### Step5. リストア後のデータ内容確認

Snapshot取得前にINSERTしたデータのみ確認できました。
これは想定通りの結果で、Snapshot取得中(write suspend状態)やSnapshot取得後にINSERTした結果行のない状態に戻すことができました。

```
[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$ db2 "select * from t1 order by c3"

C1          C2                               C3
----------- -------------------------------- --------------------------
          1 before snapshot                  2023-02-28-06.56.11.996187

  1 record(s) selected.

[db2inst1@c-db2ucluster-2-db2u-0 - Db2U db2inst1]$
```

## 最後に
OpenShift Webコンソールを使うと、非常に簡単にSnapshotの取得・リストアができます。
Yamlを書いても同じことが出来ますが、コンソールを使うと、以下の項目は自動入力されユーザーが確認・判断を行う必要が無くなります。
 * Snapshot取得時
     * スナップショット名
     * スナップショットクラス

 * リストア時
     * アクセスモード
     * ボリュームモード(ファイルシステム or Block)
     * サイズ (Snapshot取得時点サイズが反映され、さらに増減の選択も可能)


このメリットは非常に大きくて、環境理解不足やコーディングのミスによる操作ミスを防ぎ、確実にSnapshotの取得、リストアを遂行することができるようになります。
ストレージの知識がなくても、安全確実しかも手軽にOpenShift環境のPVC Snapshotを取得できる、とても良いユーティリティでした。

## memo
### 補足1：PVC削除に失敗した場合の解消手順

対象となるPVCをmountしているPodが稼働状態のままoc delete pvc コマンドを実行すると、PVC削除は完了せず、Terminatingステータスのまま残存してしまいます。
このような状態になっても、こちらの手順に従って解除した上でpvcを削除するとうまくいきます。
参考：[Qiita記事: PersistentVolumeClaim (pvc)削除できず、Terminating ステータスのままとの問題](https://qiita.com/dss_hashimoto/items/8cbf834c504e57fbe1ff)

削除に失敗したPVCの状態を確認。pvc-protection となっている
```
root@IBM-PF2E8K5F:~/db2u/pvc# date ; oc describe pvc c-db2ucluster-2-meta | grep Finalizers
2023年  2月 28日 火曜日 20:37:35 JST
Finalizers:    [kubernetes.io/pvc-protection]
```
Protected状態を解除すると、PVC削除処理が再開される
```
date ; oc patch pvc c-db2ucluster-2-meta -p '{"metadata":{"finalizers": []}}' --type=merge
2023年  2月 28日 火曜日 20:37:44 JST
persistentvolumeclaim/c-db2ucluster-2-meta patched

```
削除が完了すると、get pvc コマンド出力からも消える
```
date ; oc get pvc | grep -i db2ucluster-2
2023年  2月 28日 火曜日 20:38:00 JST
root@IBM-PF2E8K5F:~/db2u/pvc#

```


### 補足2：書き込み静止/解除時の db2diag.log 出力

#### (1) Snapshot取得前の書き込み静止 (SET WRITE SUSPEND)
```text:実行コマンド
oc exec -it c-db2ucluster-2-db2u-0 -- manage_snapshots --action suspend
```

```text: db2diag.log
2023-02-28-07.00.31.460411+000 I477537E532           LEVEL: Info
PID     : 21363                TID : 140438413502208 PROC : db2sysc 0
INSTANCE: db2inst1             NODE : 000            DB   : SAMPLEDB
APPHDL  : 0-33295              APPID: *LOCAL.db2inst1.230228070031
AUTHID  : DB2INST1             HOSTNAME: c-db2ucluster-2-db2u-0
EDUID   : 51                   EDUNAME: db2agent (SAMPLEDB) 0
FUNCTION: DB2 UDB, base sys utilities, sqleSetWriteSuspend, probe:4596
DATA #1 : <preformatted>
Set Write Suspend issued from member 0

2023-02-28-07.00.31.606775+000 I478070E561           LEVEL: Warning
PID     : 21363                TID : 140438413502208 PROC : db2sysc 0
INSTANCE: db2inst1             NODE : 000            DB   : SAMPLEDB
APPHDL  : 0-33295              APPID: *LOCAL.db2inst1.230228070031
AUTHID  : DB2INST1             HOSTNAME: c-db2ucluster-2-db2u-0
EDUID   : 51                   EDUNAME: db2agent (SAMPLEDB) 0
FUNCTION: DB2 UDB, data protection services, sqlpSuspendLog, probe:205
DATA #1 : <preformatted>
LSO at suspend time is 395588553. Log file at suspend time is 15

2023-02-28-07.00.31.608307+000 I478632E547           LEVEL: Info
PID     : 21363                TID : 140438413502208 PROC : db2sysc 0
INSTANCE: db2inst1             NODE : 000            DB   : SAMPLEDB
APPHDL  : 0-33295              APPID: *LOCAL.db2inst1.230228070031
AUTHID  : DB2INST1             HOSTNAME: c-db2ucluster-2-db2u-0
EDUID   : 51                   EDUNAME: db2agent (SAMPLEDB) 0
FUNCTION: DB2 UDB, data protection services, sqlpSuspendLog, probe:205
DATA #1 : <preformatted>
LSO/LSN at suspend time is 395588553/0000000000161F5F

2023-02-28-07.00.31.632810+000 E479180E588           LEVEL: Warning
PID     : 21363                TID : 140438413502208 PROC : db2sysc 0
INSTANCE: db2inst1             NODE : 000            DB   : SAMPLEDB
APPHDL  : 0-33295              APPID: *LOCAL.db2inst1.230228070031
AUTHID  : DB2INST1             HOSTNAME: c-db2ucluster-2-db2u-0
EDUID   : 51                   EDUNAME: db2agent (SAMPLEDB) 0
FUNCTION: DB2 UDB, base sys utilities, sqleSetWriteSuspend, probe:5300
MESSAGE : ADM6075W  The database has been placed in the WRITE SUSPENDED state.
          Database name: "SAMPLEDB".

2023-02-28-07.00.32.094343+000 E479769E445           LEVEL: Info
PID     : 21363                TID : 140438509971200 PROC : db2sysc 0
INSTANCE: db2inst1             NODE : 000            DB   : SAMPLEDB
HOSTNAME: c-db2ucluster-2-db2u-0
EDUID   : 27                   EDUNAME: db2logmgr (SAMPLEDB) 0
FUNCTION: DB2 UDB, data protection services, sqlpgArchiveLogFile, probe:3108
DATA #1 : <preformatted>
Started archive for log file S0000015.LOG.

2023-02-28-07.00.32.096411+000 E480215E441           LEVEL: Info
PID     : 21363                TID : 140438509971200 PROC : db2sysc 0
INSTANCE: db2inst1             NODE : 000            DB   : SAMPLEDB
HOSTNAME: c-db2ucluster-2-db2u-0
EDUID   : 27                   EDUNAME: db2logmgr (SAMPLEDB) 0
FUNCTION: DB2 UDB, data protection services, sqlpgArchiveLogFile, probe:3109
MESSAGE : ADM1844I  Started archive for log file "S0000015.LOG"

2023-02-28-07.00.32.247631+000 I480657E606           LEVEL: Info
PID     : 21363                TID : 140438509971200 PROC : db2sysc 0
INSTANCE: db2inst1             NODE : 000            DB   : SAMPLEDB
HOSTNAME: c-db2ucluster-2-db2u-0
EDUID   : 27                   EDUNAME: db2logmgr (SAMPLEDB) 0
FUNCTION: DB2 UDB, data protection services, sqlpgArchiveLogFile, probe:3180
DATA #1 : <preformatted>
Completed archive for log file S0000015.LOG to /mnt/bludata0/db2/archive_log/db2inst1/SAMPLEDB/NODE0000/LOGSTREAM0000/C0000000/ from /mnt/blumeta0/db2/databases/db2inst1/NODE0000/SQL00001/LOGSTREAM0000/.

2023-02-28-07.00.32.249554+000 E481264E651           LEVEL: Info
PID     : 21363                TID : 140438509971200 PROC : db2sysc 0
INSTANCE: db2inst1             NODE : 000            DB   : SAMPLEDB
HOSTNAME: c-db2ucluster-2-db2u-0
EDUID   : 27                   EDUNAME: db2logmgr (SAMPLEDB) 0
FUNCTION: DB2 UDB, data protection services, sqlpgArchiveLogFile, probe:3175
MESSAGE : ADM1846I  Completed archive for log file "S0000015.LOG" to
          "/mnt/bludata0/db2/archive_log/db2inst1/SAMPLEDB/NODE0000/LOGSTREAM00
          00/C0000000/" from
          "/mnt/blumeta0/db2/databases/db2inst1/NODE0000/SQL00001/LOGSTREAM0000
          /".

2023-02-28-07.03.47.839876+000 E481916E803           LEVEL: Warning
PID     : 21363                TID : 140438522554112 PROC : db2sysc 0
INSTANCE: db2inst1             NODE : 000            DB   :
APPHDL  : 0-33296              APPID: *LOCAL.db2inst1.230228070347
AUTHID  : DB2INST1             HOSTNAME: c-db2ucluster-2-db2u-0
EDUID   : 24                   EDUNAME: db2agent (instance) 0
FUNCTION: DB2 UDB, database monitor, sqm___sqlmonssagnt, probe:14
DATA #1 : <preformatted>

This occurs when snapshot is run on a database iswrite suspended.
Due to latching contention, we will obtain minimal snapshot info for
the current database 'SAMPLEDB'. We will process other databases normally.

For more information on write suspend, please see the
'db2 set write suspend for database' command.

```

#### (2) Snapshotリストア後の書き込み静止解除 (SET WRITE RESUME)

```text: 実行コマンド
oc exec -it c-db2ucluster-2-db2u-0 -- manage_snapshots --action restore
```

```text: db2diag.log
2023-02-28-11.59.00.782641+000 E688288E587           LEVEL: Info
PID     : 2716                 TID : 140344624670464 PROC : db2sysc 0
INSTANCE: db2inst1             NODE : 000            DB   : SAMPLEDB
APPHDL  : 0-30                 APPID: *LOCAL.db2inst1.230228115900
AUTHID  : DB2INST1             HOSTNAME: c-db2ucluster-2-db2u-0
EDUID   : 24                   EDUNAME: db2agent (SAMPLEDB) 0
FUNCTION: DB2 UDB, base sys utilities, sqleDoRestartDBWriteResume, probe:2777
MESSAGE : ADM6045I  The database is no longer in the WRITE SUSPEND state.
          Database name: "SAMPLEDB".
```

### 補足3：Step4-3.で出力されたYaml
#### (1) メタデータ用PVC
```yaml:c-db2ucluster-2-meta_copy.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    formation_id: db2ucluster-2
    pv.kubernetes.io/bind-completed: "yes"
    pv.kubernetes.io/bound-by-controller: "yes"
    storageConfigType: create
    volume.beta.kubernetes.io/storage-provisioner: openshift-storage.cephfs.csi.ceph.com
    volume.kubernetes.io/storage-provisioner: openshift-storage.cephfs.csi.ceph.com
  creationTimestamp: "2023-02-17T10:50:48Z"
  finalizers:
  - kubernetes.io/pvc-protection
  labels:
    app: db2ucluster-2
    formation_id: db2ucluster-2
  name: c-db2ucluster-2-meta
  namespace: db2u-1
  ownerReferences:
  - apiVersion: db2u.databases.ibm.com/v1
    controller: true
    kind: Formation
    name: db2ucluster-2
    uid: f4bf8c75-5986-497a-bf72-3b0610b52ecb
  resourceVersion: "75175063"
  uid: d2b126cc-a486-419b-b239-39c4e90b2ea6
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: ocs-storagecluster-cephfs
  volumeMode: Filesystem
  volumeName: pvc-d2b126cc-a486-419b-b239-39c4e90b2ea6
status:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 10Gi
  phase: Bound
```
#### (2) データ用PVC
```yaml:data-c-db2ucluster-2-db2u-0_copy.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    formation_id: db2ucluster-2
    pv.kubernetes.io/bind-completed: "yes"
    pv.kubernetes.io/bound-by-controller: "yes"
    storageConfigType: template
    volume.beta.kubernetes.io/storage-provisioner: openshift-storage.rbd.csi.ceph.com
    volume.kubernetes.io/storage-provisioner: openshift-storage.rbd.csi.ceph.com
  creationTimestamp: "2023-02-17T10:51:32Z"
  finalizers:
  - kubernetes.io/pvc-protection
  labels:
    app: db2ucluster-2
    component: db2oltp
    formation_id: db2ucluster-2
    role: db
    type: engine
  name: data-c-db2ucluster-2-db2u-0
  namespace: db2u-1
  ownerReferences:
  - apiVersion: db2u.databases.ibm.com/v1
    kind: Formation
    name: db2ucluster-2
    uid: f4bf8c75-5986-497a-bf72-3b0610b52ecb
  resourceVersion: "74786853"
  uid: 5c9cd839-470e-47bc-b6e3-190520325572
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: ocs-storagecluster-ceph-rbd
  volumeMode: Filesystem
  volumeName: pvc-5c9cd839-470e-47bc-b6e3-190520325572
status:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 10Gi
  phase: Bound
```