はじめに
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」を検索します。
インストール画面では特に設定を変えず、そのまま「インストール」をクリックします。
インストールが終わると様々なAPIが利用可能になっていることがわかります。
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です。
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-csi
StorageClassの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
というカスタムリソースで行います。
さまざまな設定項目があるので、詳細は公式ドキュメントを確認いただければと思いますが、ここでは最低限の設定例をお見せします。
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ファイルが確認できるのがいいですよね。
上記のファイルをデプロイします。
$ oc apply -f dataprotectionapplication.yaml
色々準備しましたが、以上でOADPでバックアップを取得する準備が完了しました。
バックアップを取得する
では実際にバックアップを取得してみましょう。
今回はこちらのサンプルブログのアプリを対象とします。
このアプリはNginx-Django-Mysql/Redisの構成になっており、MysqlはStatefulset
でEBSをPersistentVolume
として使っています。
READMEの手順に従いアプリをデプロイすると、Sample-blog
Namespace配下に以下のようなコンポーネントがデプロイされます。
$ 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
バックアップの取得前にサンプルブログに適当に記事を投稿しておきます。
では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
ちなみにバックアップの処理に関するログはDataProtectionApplication
のデプロイ時に生成されたvelero
Podの標準出力に表示されます。
$ oc logs velero-76c54bcb77-hqtpt
実際に取得したバックアップを見てみましょう。
あらかじめ設定したS3バケット内に色々なデータが格納されていることが確認できます。
永続ボリューム(MySQL/Redisのデータ)については、EBSのスナップショットで取得しています。こちらもAWSのWebコンソールで確認できます。
リストアを実行する
さて、無事にバックアップが取得できたので、次はリストアを実行します。
リストアの実行前に、今稼働しているサンプルブログにひとつ記事を追加しておきます。リストア後、これが消えていたらリストアが正常に完了しているといっていいでしょう。
リストア用の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
になります。
サンプルブログにアクセスすると、2つ目の記事が消えているため、無事リストアされていることがわかります。
おわりに
今回はOADPの基本的な機能を使ってOpenShift環境のアプリケーションバックアップ/リストアを実現できることを確認しました。
別の記事にて、もうすこしバックアップ/リストアというテーマを俯瞰して、「そもそもOpenShift環境のバックアップ/リストアってどう考えたらいいの?」という点についてまとめていこうと思いますので、乞うご期待ください!