IBM CloudのRedHat OpenShiftクラスターにOADP Operator(Velero)をインストールして利用する

クラスター上のリソースのバックアップのために、OADP Operatorをインストールしてバックアップのテストをしてみた。

### OADP Operatorとは
OpenShift APIs for Data Protectionのこと。  
FAQはこちらを参照。Veleroのラッパー的なものだと理解した。
https://access.redhat.com/articles/5456281

記事作成時点では、IBM Cloud上のROKSクラスターに導入するには少しコツが必要だった。

### Operatorの導入
OpenShiftのコンソールから導入する。Operator Hubに"OADP"と検索すると出てくる。
導入先のネームスペースは、デフォルトのoadp-operatorとした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449737/e739b26e-0251-9174-7e36-a7577e5d0352.png)


### Veleroの構成
インストールが成功したのち、まずはVeleroを構成する。
YAML画面から必要な情報を入力していく。

![スクリーンショット 2021-03-15 23.54.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449737/bc09224c-83fb-8073-0791-acb2eda27976.png)

awsやazureには対応しているが、IBM Cloud仕様にはなっていないようで、この後の工程でいろいろと対処が必要になる。

metadata.name ：お好きな名前を入れる 
spec.region : 今回は東京とする(jp-tok)。この項目は必須だが、jp-tokというリージョンはawsには存在しないため…後ほど
credentials~ : バックアップ先のs3バケットのシークレットを事前に作成しておき、ここで定義する。
volume_snapshot_locations配下は削除する。
IBM CloudではVeleroによるVolumeSnapshotが取得できないっぽい。
参考: https://www.ibm.com/cloud/blog/stateful-application-migration-from-ibm-cloud-vpc-gen-1-to-vpc-gen-2-kubernetes-clusters

シークレットのフォーマット

```bash
$ cat ./os-cred-for-velero
[default]
aws_access_key_id=xxxxxxxxxxxxxxx
aws_secret_access_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

### oadp-operatorネームスペースに作成する
$ oc create secret generic cloud-credentials --namespace oadp-operator --from-file cloud=./os-cred-for-velero
secret/cloud-credentials created
```

ここまで完了したらCreateを押下する。
ステータスを確認すると、`oadp-default-aws-registry` がErrorになっている。

```bash
$ oc get all -n oadp-operator
NAME                                             READY   STATUS    RESTARTS   AGE
pod/oadp-default-aws-registry-8448ff9f55-7td2w   0/1     Error     3          87s
pod/oadp-operator-65fdbb6b6-sw9xd                1/1     Running   0          20m
pod/restic-72mzz                                 1/1     Running   0          89s
pod/restic-s7hsn                                 1/1     Running   0          89s
pod/restic-skhq5                                 1/1     Running   0          89s
pod/restic-wpqgt                                 1/1     Running   0          89s
pod/velero-59c8b79699-j9qmv                      1/1     Running   0          90s


NAME                                    TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
service/oadp-default-aws-registry-svc   ClusterIP   172.21.59.4   <none>        5000/TCP   86s


NAME                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/restic   4         4         4       4            4           <none>          90s


NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/oadp-default-aws-registry   0/1     1            0           88s
deployment.apps/oadp-operator               1/1     1            1           20m
deployment.apps/velero                      1/1     1            1           92s


NAME                                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/oadp-default-aws-registry-8448ff9f55   1         1         0       88s
replicaset.apps/oadp-operator-65fdbb6b6                1         1         1       20m
replicaset.apps/velero-59c8b79699                      1         1         1       91s


NAME                                                       HOST/PORT                                                                                                                                      PATH   SERVICES                        PORT       TERMINATION   WILDCARD
route.route.openshift.io/oadp-default-aws-registry-route   oadp-default-aws-registry-route-oadp-operator.xxxxxxxxxxxxxxxx.jp-tok.containers.appdomain.cloud ... 1 more          oadp-default-aws-registry-svc   5000-tcp                 None
```

ログを確認すると、jp-tokというリージョンはawsには存在していないためエラーになっていることがわかる。

```
panic: invalid region provided: jp-tok
```

(邪道だが) Deployment: oadp-default-aws-registryに環境変数 `REGISTRY_STORAGE_S3_REGIONENDPOINT` を定義すると、リージョンのチェックがスルーされるようだ。

こんな感じで加筆してSaveする。Operator管理なので、更新しても自動的に上書きされるという警告が出るが、envは大丈夫だったりする。本来Velero構成時のYAMLで設定できるのではないかと思うのだが、方法が分からなかった…

![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449737/a0df700a-d661-5166-4813-44b21634809b.png)

よし、おっけぇ

```bash
$ oc get all -n oadp-operator
NAME                                             READY   STATUS    RESTARTS   AGE
pod/oadp-default-aws-registry-64b467d9fd-dqmws   1/1     Running   0          6m
pod/oadp-operator-54788cfd48-ntwkj               1/1     Running   0          25m
pod/restic-c4snc                                 1/1     Running   0          7m58s
pod/restic-k294s                                 1/1     Running   0          7m58s
pod/restic-msk2f                                 1/1     Running   0          7m58s
pod/restic-rkm2t                                 1/1     Running   0          7m58s
pod/velero-59c8b79699-mz8hg                      1/1     Running   0          7m59s
:

```

### バックアップしてみる

あらかじめVeleroのCLIを導入しておく。

```bash
## ネームスペースをセット
$ velero client config set namespace=oadp-operator
## バックアップ
$ velero backup create default-backup --include-namespaces default
Backup request "default-backup" submitted successfully.
Run `velero backup describe default-backup` or `velero backup logs default-backup` for more details.

##　確認
$ velero get backup
NAME             STATUS   ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
default-backup   Failed   0        0          2021-03-11 18:41:34 +0900 JST   30d       default            <none>
```

失敗。ログを確認する。

```bash
$ velero backup logs default-backup
An error occurred: Get "https://xxxxxxxxxx.s3.jp-tok.amazonaws.com/backups/default-backup/default-backup-logs.gz(中略): dial tcp: lookup xxxxxx.s3.jp-tok.amazonaws.com on 127.0.0.1:53: no such host
```

バケットを探しにAWSに行ってしまったようだ。がんばれIBM Cloud。
これは、BackupStorageLocationが正しく構成されていないことが原因だった。
これも邪道だが、直接YAMLを修正しちゃう。spec.configに以下を追加する。

`s3ForcePathStyle: 'true'`
`s3Url: https://s3.direct.jp-tok.cloud-object-storage.appdomain.cloud`

![image (1615456131232).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449737/c5f85de6-fc1b-af89-5f69-47e202b6e82d.png)


これでうまくいくようになる。
Velero作成時のYAMLで `backup-storage-locations` という項目があるが、ここで上記のs3ForcePathStyleとs3Urlを指定しても無視されてしまったためこのような方法を採ったが、これも本来Velero構成時に設定できるのではないかと思っている(が、諦めました)。

再度、バックアップを試みる。

```bash
### バックアップ
$ velero backup create default-backup --include-namespaces default
Backup request "default-backup" submitted successfully.
Run `velero backup describe default-backup` or `velero backup logs default-backup` for more details.

### 確認
$ velero get backup
NAME             STATUS       ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
default-backup   InProgress   0        0          2021-03-11 18:47:16 +0900 JST   30d       default            <none>

$ velero get backup
NAME             STATUS      ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
default-backup   Completed   0        0          2021-03-11 18:47:16 +0900 JST   29d       default            <none>
```

今度は成功した。

### PVありPodの場合

PV有りの場合、通常はVolumeSnapshotを利用するようだが、今回は定義していないため、別の方法を採用する。
以下のようにバックアップ対象のStatefulsetのYAMLにアノテーション `backup.velero.io/backup-volumes` を付与する。
YAMLは[こちらの記事](https://qiita.com/ysakashita/items/3a0b2ad9ac37e2ce315a) を真似させていただきました。


```nginx-sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-sts
  namespace: kame
spec:
  serviceName: nginx-sts
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
      annotations:
        backup.velero.io/backup-volumes: nginx-logs
        pre.hook.backup.velero.io/container: fsfreeze
        pre.hook.backup.velero.io/command: '["/sbin/fsfreeze", "--freeze", "/var/log/nginx"]'
        post.hook.backup.velero.io/container: fsfreeze
        post.hook.backup.velero.io/command: '["/sbin/fsfreeze", "--unfreeze", "/var/log/nginx"]'
    spec:
      serviceAccountName: nginx-sts
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: nginx-logs
          mountPath: /var/log/nginx
      - name: fsfreeze
        image: ubuntu
        securityContext:
          privileged: true
        volumeMounts:
          - name: nginx-logs
            mountPath: /var/log/nginx
        command:
          - "/bin/bash"
          - "-c"
          - "sleep infinity"
      volumes:
      - name: nginx-logs
        persistentVolumeClaim:
          claimName: kame-pvc
```

※サイドカーのubuntuが特権モードになっているので、デプロイ時には権限付与が必要となる。

```bash
$ oc create sa nginx-sts -n <namespace>
$ oc adm policy add-scc-to-user privileged -z nginx-sts -n <namespace>
$ oc apply -f nginx-sts.yaml
```

これでバックアップができるようになる(PodVolumeBackup)。

![スクリーンショット 2021-03-18 8.43.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449737/6177cda0-233f-36b8-c29e-cd606059714e.png)


ドキュメントがあまり多くなく、意外と面倒くさかった。
リストアのテストは割愛させていただきました。
今回の方法だと、手動で手直しした定義が、Operator更新時にもとに戻ってしまうかもしれません。