7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

OpenShiftAdvent Calendar 2022

Day 21

OpenShift API for Data Protection (OADP) を使ってアプリをバックアップ/リストアしてみよう

Posted at

はじめに

OpenShift環境を運用するにあたり、「これどうすればいいの?」となりがちなのが、アプリケーションのバックアップ/リストアです。残念ながら従来の仮想サーバの運用のときのように、VMスナップショット取ってはい終わり、とはいきません。コンテナやKubernetes/OpenShiftの特性を把握し、それに適したバックアップ/リストア手法を採用する必要があります。

そこで今回は、OpenShiftが提供しているアプリケーションバックアップツールであるOpenShift API for Data Protection (OADP)を触ってみて、どのようにアプリケーションのバックアップを取得できるのかをご紹介します。

OpenShift API for Data Protectionとは?

Red HatがOpenShiftクラスター上でバックアップ・リストアを実現するために作成したOperatorです。アップストリームはこちらになりますが、Veleroをベースとしたツールになっており、OADPをインストールすることでVeleroのAPIも使用することができます。
OpenShift Container Platformのサブスクリプションに包含されているため、ユーザーは追加料金なしに利用することができます。
バックアップの対象は、OpenShiftクラスターリソース(yamlファイル)、内部イメージ、および永続ボリュームのデータになります。注意するべきは、基本的にNamespaceごとの情報を対象としたバックアップになりますので、このバックアップさえあれば有事の際も全部元に戻せる、といったものではないことを誤認識ください。

手順

前提条件

本手順は、以下の環境で実施します。

  • AWS上にIPIインストールしたOpenShift Container Platform 4.11.18
  • cluster-adminを持つOpenShiftユーザー
  • AdministratorAccessのポリシーを持つIAMユーザー

OADP Operatorをインストールする

OADPはOperatorを使ってインストールします。
まずWebコンソールで「OADP Opetaror」を検索します。

OADP1.png

インストール画面では特に設定を変えず、そのまま「インストール」をクリックします。
OADP2.png

インストールが終わると様々なAPIが利用可能になっていることがわかります。
OADP3.png

AWSの設定

OADP Operatorの準備は一旦これくらいにして、AWSの設定に入ります。

IAMの準備

OADPでは永続ボリュームのバックアップ手法としてresticと呼ばれるオープンソースのバックアップツールと、CSIスナップショットの2種類をサポートしています。ここではAWS上に構築していることから、AWSのEBSを使ったCSIスナップショットを使ってみます。
また、OADPでは取得したバックアップの保存先としてオブジェクトストレージを使います。こちらもAWSを使っていることからS3に保存していきます。

EBSのスナップショットやS3へのputを行うにあたり、OADP用のIAMポリシー/IAMユーザーを作成する必要がありますが、今回は割愛してAdministratorAccessの権限を持つIAMユーザーのアクセスキー/シークレットキーを使います。OADP用のIAMを作成する場合は公式ドキュメントを参照ください。

のちほどAWSのIAM情報をSecretとしてデプロイするため、必要なファイルを作成しておきます。

cat << EOF > ./credentials-velero
[default]
aws_access_key_id=<AWS_ACCESS_KEY_ID>
aws_secret_access_key=<AWS_SECRET_ACCESS_KEY>
EOF

オブジェクトストレージの準備

バックアップ情報を格納するS3バケットを作成します。
AWSのWebコンソールからS3のバケット作成画面に行き、OpenShiftクラスターがあるリージョン(今回は東京リージョン)にバケットを作成します。
名前以外は全てデフォルトのままでOKです。

OADP4.png

OpenShiftの設定

AWS側の設定が完了したので、今度はOpenShiftの設定を行います。
まずはEBSのCSIスナップショットを使うための設定変更です。

IPIインストールした時点でのデフォルトのストレージクラスがgp2という、CSIではないものになっているため、これをgp3-csiに変更します。

$ oc get storageclass
NAME            PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
gp2 (default)   kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   true                   5d7h
gp2-csi         ebs.csi.aws.com         Delete          WaitForFirstConsumer   true                   5d7h
gp3-csi         ebs.csi.aws.com         Delete          WaitForFirstConsumer   true                   5d7h

以下のコマンドで変更できます。

$ oc patch storageclass gp2 --type json -p '[{ "op": "remove", "path": "/metadata/annotations" }]'
$ oc patch storageclass gp3-csi -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
$ oc get storageclass
NAME                PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
gp2                 kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   true                   5d7h
gp2-csi             ebs.csi.aws.com         Delete          WaitForFirstConsumer   true                   5d7h
gp3-csi (default)   ebs.csi.aws.com         Delete          WaitForFirstConsumer   true                   5d7h

次にVolumeSnapshotClassを修正します。
VolumeSnapshotClassとは、通常のPVでいうStorageClassのように、動的のボリュームスナップショットの作成・削除を実現します。
OpenShiftをインストールした時点で、csi-aws-vscというVolumeSnapshotClassが作成されています。

$ oc get vsclass
NAME                    DRIVER            DELETIONPOLICY   AGE
csi-aws-vsc             ebs.csi.aws.com   Delete           5d7h

中身を見ると、gp3-csiStorageClassのProvisionerであるebs.csi.aws.comがDriverとして指定されていることがわかります。

$ oc get vsclass csi-aws-vsc -o yaml
apiVersion: snapshot.storage.k8s.io/v1
deletionPolicy: Delete
driver: ebs.csi.aws.com
kind: VolumeSnapshotClass
metadata:
  annotations:
    snapshot.storage.kubernetes.io/is-default-class: "true"
  generation: 1
  name: csi-aws-vsc

これにveleroでCSIスナップショットを取得するためのannotationを追加していきます。

$ oc patch vsclass csi-aws-vsc -p '{"metadata":{"labels":{"velero.io/csi-volumesnapshot-class":"true"}}}' --type=merge

最後に、少し前に作成したAWSのcredentialをデプロイします。

$ oc create secret generic cloud-credentials -n openshift-adp --from-file cloud=credentials-velero

これでOpenShiftの設定は完了です。

OADPの設定

最後に本丸のOADPの設定を行います。OADPのバックアップ/リストアの基本的な構成設定は、DataProtectionApplicationというカスタムリソースで行います。
さまざまな設定項目があるので、詳細は公式ドキュメントを確認いただければと思いますが、ここでは最低限の設定例をお見せします。

dataprotectionapplication.yaml
apiVersion: oadp.openshift.io/v1alpha1
kind: DataProtectionApplication
metadata:
  name: velero-sample
  namespace: openshift-adp
spec:
  configuration:
    velero:
      defaultPlugins:
        - openshift
        - aws
        - kubevirt
        - csi
    featureFlags:
    - EnableCSI
  backupLocations:
    - velero:
        config:
          profile: default
          region: ap-northeast-1
        credential:
          key: cloud
          name: cloud-credentials
        objectStorage:
          bucket: oadp-demo
          prefix: velero
        default: true
        provider: aws

ちなみに、webコンソールで作成しようとすると、あらかじめ以下のようにデフォルトの設定が確認できます。OpenShiftはこういったある程度のサンプルyamlファイルが確認できるのがいいですよね。
OADP5.png

上記のファイルをデプロイします。

$ oc apply -f dataprotectionapplication.yaml

デプロイするとOADPのコンポーネントが立ち上がります。
OADP6.png

色々準備しましたが、以上でOADPでバックアップを取得する準備が完了しました。

バックアップを取得する

では実際にバックアップを取得してみましょう。
今回はこちらのサンプルブログのアプリを対象とします。
このアプリはNginx-Django-Mysql/Redisの構成になっており、MysqlはStatefulsetでEBSをPersistentVolumeとして使っています。
READMEの手順に従いアプリをデプロイすると、Sample-blogNamespace配下に以下のようなコンポーネントがデプロイされます。

$ oc get pods,deploy,statefulsets,service,route,pv,pvc -n sample-blog
NAME                          READY   STATUS      RESTARTS   AGE
pod/django-1-build            0/1     Completed   0          34h
pod/django-5cd9f75c58-bcxvt   1/1     Running     0          33h
pod/mysql-0                   1/1     Running     0          33h
pod/nginx-1-build             0/1     Completed   0          34h
pod/nginx-7f98dd9f54-dv772    1/1     Running     0          33h
pod/redis-0                   1/1     Running     0          33h

NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/django   1/1     1            1           34h
deployment.apps/nginx    1/1     1            1           34h

NAME                     READY   AGE
statefulset.apps/mysql   1/1     34h
statefulset.apps/redis   1/1     34h

NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/django   ClusterIP   172.30.87.142    <none>        8000/TCP   34h
service/mysql    ClusterIP   172.30.209.214   <none>        3306/TCP   34h
service/nginx    ClusterIP   172.30.163.114   <none>        80/TCP     34h
service/redis    ClusterIP   172.30.49.173    <none>        6379/TCP   34h

NAME                             HOST/PORT                                                 PATH   SERVICES   PORT   TERMINATION   WILDCARD
route.route.openshift.io/nginx   sample-blog.apps.aws-cluster-01.xxx.com          nginx      8080                 None

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                         STORAGECLASS   REASON   AGE
persistentvolume/pvc-a2c8e63a-5e95-46bb-9833-3e82d10d8a05   10Gi       RWO            Delete           Bound    sample-blog/redis-pv-claim    gp3-csi                 33h
persistentvolume/pvc-ee7a59d0-2ec2-48bf-ae91-60a18115b9f9   20Gi       RWO            Delete           Bound    sample-blog/mysql-pv-claim    gp3-csi                 33h

NAME                                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/mysql-pv-claim   Bound    pvc-ee7a59d0-2ec2-48bf-ae91-60a18115b9f9   20Gi       RWO            gp3-csi        33h
persistentvolumeclaim/redis-pv-claim   Bound    pvc-a2c8e63a-5e95-46bb-9833-3e82d10d8a05   10Gi       RWO            gp3-csi        33h

バックアップの取得前にサンプルブログに適当に記事を投稿しておきます。

OADP7.png

ではbackup用のyamlファイルを作成します。

backup.yaml
apiVersion: velero.io/v1
kind: Backup
metadata:
  name: backup-sample-blog-01
  namespace: openshift-adp
spec:
  storageLocation: velero-sample-1
  includedNamespaces:
  - sample-blog
  • spec.storageLocationにはDataProtectionApplicationのNameに-1をつけたものを指定します。これはDataProtectionApplicationを作成した際に生成されるbackupStorageLocationsというカスタムリソース名になります。
  • includedNamespacesには、バックアップの対象となるNamespaceのリストを記述します。今回はsample-blogを指定します。

そのほかの設定については公式ドキュメントを参照ください。特定のクラスターリソースのみをバックアップするなど、柔軟な設定が可能です。

ではバックアップを取得します。

$ oc apply -f backup.yaml

デプロイすると、バックアップ処理が開始されます。
OADP.png

ちなみにバックアップの処理に関するログはDataProtectionApplicationのデプロイ時に生成されたveleroPodの標準出力に表示されます。

$ oc logs velero-76c54bcb77-hqtpt

完了するとステータスがCompletedになります。
スクリーンショット 2022-12-21 20.49.23.png

 実際に取得したバックアップを見てみましょう。
あらかじめ設定したS3バケット内に色々なデータが格納されていることが確認できます。
OADP.png
永続ボリューム(MySQL/Redisのデータ)については、EBSのスナップショットで取得しています。こちらもAWSのWebコンソールで確認できます。
OADP.png

リストアを実行する

さて、無事にバックアップが取得できたので、次はリストアを実行します。
リストアの実行前に、今稼働しているサンプルブログにひとつ記事を追加しておきます。リストア後、これが消えていたらリストアが正常に完了しているといっていいでしょう。

OADP.png

リストア用のyamlを作成します。

restore.yaml
apiVersion: velero.io/v1
kind: Restore
metadata:
  name: restore-sample-blog-01
  namespace: openshift-adp
spec:
  backupName: backup-sample-blog-01
  includedNamespaces:
  - sample-blog
  excludedResources:
  - nodes
  - events
  - events.events.k8s.io
  - backups.velero.io
  - restores.velero.io
  - resticrepositories.velero.io
  restorePVs: true

こちらの詳細な設定は公式ドキュメントを参照ください。

ではリストアを実行しましょう。

$ oc apply -f restore.yaml

こちらもしばらくするとステータスがCompletedになります。
OADP.png

サンプルブログにアクセスすると、2つ目の記事が消えているため、無事リストアされていることがわかります。
OADP.png

おわりに

今回はOADPの基本的な機能を使ってOpenShift環境のアプリケーションバックアップ/リストアを実現できることを確認しました。
別の記事にて、もうすこしバックアップ/リストアというテーマを俯瞰して、「そもそもOpenShift環境のバックアップ/リストアってどう考えたらいいの?」という点についてまとめていこうと思いますので、乞うご期待ください!

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?