Portworx PX-DR:コンテナのディザスタ・リカバリ(非同期レプリケーション編)

【05.21.2021 JST】今回は Portworx のデータ保護機能のうち、コンテナのディザスタ・リカバリ機能を提供する「PX-DR」の非同期レプリケーションをご紹介します。

Portworx PX-DR 非同期レプリケーション

image_pdfimage_print

今回は、Portworx のコンテナのディザスタ・リカバリ機能を提供する PX-DR の非同期レプリケーション機能についてご説明します。同期レプリケーション機能については、こちらのブログご覧ください。本ブログは、テクニカル・マーケティング・マネージャーのライアン・ウォルナー(Ryan Wallner)による記事を参考に、わたくし溝口が日本語化および加筆、再構成したものです。

なお、PX-DR は 30 日間のトライアル・ライセンスには含まれません。もし、PoC をご検討いただける場合は、sales-japan@purestorage.com までお問い合わせください。

非同期レプリケーション

同期レプリケーションに関するブログでご説明したとおり、データベースのようなステートフル・アプリケーションを Kubernetes プラットフォームで実行しようとする場合には、データ保護の問題が発生します。PX-DR は、主に同期レプリケーションと非同期レプリケーションという 2 つの方法でこれらの問題を解決します。

非同期レプリケーションは、2 つの異なる Portworx クラスタを地理的に異なるエリアに配置し、それらをクラスタ・ペアにします。スタンバイ・サイトでは、継続的に非同期にレプリケーションをスケジューリングして、定義された RPO(目標復旧時点)および RTO の条件のもと、ディザスタ・リカバリ先のクラスタとして動作します。

ボリュームの非同期レプリケーションの設定

非同期レプリケーションには 2 つの Portworx クラスタを使用します。このうち 1 つのクラスタは DR サイトです。クラスタ・ペアは PX-DR の 2 つのクラスタ間で作成されます。クラスタがペアリングされた後、非同期レプリケーションは、スケジュール・ポリシーとマイグレーション・スケジュールの 2 つを使用して実施されます。

Portworx PX-DR 非同期レプリケーション

スケジュール・ポリシー

スケジュール・ポリシーは、マイグレーションをトリガーするタイミングを指定します。ポリシー自体にはアクションは含まれていませんが、マイグレーション機能によって参照および使用されます。

スケジュール・ポリシーには 4 つのセクションがあります。

  • インターバル(interval:アクションがトリガーされる間隔を分単位で指定します。
  • 日次(daily:アクションが毎日トリガーされる時刻を指定します。
  • 週次(weekly:アクションがトリガーされる曜日と、その日の時刻を指定します。
  • 月次(monthly:アクションがトリガーされる月の日付と、その日の時刻を指定します。

以下に mysql という名前空間(namespace)を対象として、インターバル、日次、週次および月次で DR サイトと同期する設定例を示します。

apiVersion: stork.libopenstorage.org/v1alpha1
kind: SchedulePolicy
metadata:
  name: testpolicy
  namespace: mysql
policy:
  interval:
    intervalMinutes: 1
  daily:
    time: "10:14PM"
  weekly:
    day: "Thursday"
    time: "10:13PM"
  monthly:
    date: 14
    time: "8:05PM"

マイグレーション・スケジュール

マイグレーション・スケジュールにより、SchedulePolicy とマイグレーションを関連付けることができます。以下は、上記の testpolicy を使用した例です。このマイグレーションは mysql という名前空間を指し、その名前空間で remotecluster という名前の clusterPair(後述)が存在する場合、それを使用します。また、includeResourcesincludeVolumes および、startApplicationsspec の中で指定することでマイグレーションを制御できます。

  • includeResources:Secret、ConfigMaps、Service など、ボリュームに関連付けられた Kubernetes オブジェクトを含めるかどうか。
  • includeVolumes:PVC に関連付けられた Portworx ボリュームのマイグレーションを含めるかどうか。
  • startApplications:リソースやボリュームが同期した後、Destination クラスタでアプリケーションを開始するかどうか。
apiVersion: stork.libopenstorage.org/v1alpha1
kind: MigrationSchedule
metadata:
  name: mysqlmigrationschedule
  namespace: mysql
spec:
  template:
    spec:
      clusterPair: remotecluster
      includeResources: true
      includeVolumes: true
      startApplications: false
      namespaces:
      - mysql
  schedulePolicyName: testpolicy

Kubernetes ディザスタ・リカバリのワークフロー例

では、Portworx で Google Kubernetes Engine(GKE) を使用して、2 つのサイト間で DR サイトの非同期レプリケーションを設定してみましょう。

Portworx PX-DR 非同期レプリケーション

以下のゾーンでクラスタを作成しました。us-east4-c に存在するクラスタは、DR サイトです。

  • クラスタ 1:米国サウスカロライナ州モンクスコーナーのゾーン D、別名 us-east1-d
  • クラスタ 2:米国バージニア州北部アッシュバーンのゾーン C、別名 us-east4-c(DR サイト)

クラスタ 1 とクラスタ 2 をペアにするには、DR 側のクラスタ(以降、「宛先クラスタ」)からトークンを取得し、ソース・クラスタがアクセス可能な宛先クラスタの Portworx ノードの IP アドレスを少なくとも 1 つ用意します。

$ kubectl config use-context gke_portworx-cluster-2
$ PX_POD=$(kubectl get pods -l name=portworx -n kube-system -o jsonpath='{.items[0].metadata.name}')\n
$ kubectl exec $PX_POD -n kube-system -- /opt/pwx/bin/pxctl cluster token show
$ kubectl describe no | grep ExternalIP

宛先クラスタで storkctl を使用して、DR を行う名前空間の clusterpair を生成します。

$ storkctl generate clusterpair incremental-dr --namespace mysql

出力を pair.yaml という名前のファイルに保存し、Portworx のノード IP と、先に取得したトークンを追加します。詳細は、同期レプリケーションに関するブログの「手順 2. ClusterPair」をご参照ください。

次に、pair.yaml をソース・クラスタに適用し、状態が Ready であることを確認します。

$ kubectl config use-context gke_portworx_cluster-1
$ kubectl create -f pair.yaml
$ storkctl get clusterpair
NAME             STORAGE-STATUS   SCHEDULER-STATUS   CREATED
incremental-dr   Ready            Ready              08 Mar 19 15:32 EST

これでクラスタがペアになったので、アプリケーションの非同期レプリケーションを設定できます。MySQL データベースを使用してこれを行う方法を以下に示します。

まず、先に作成した clusterpair がターゲットとする mysql という名前の名前空間を作成します。

$ kubectl create ns mysql

次に、Portworx ボリュームと MySQL ポッドを含む MySQL デプロイメントを適用します。

kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
    name: mysql-tester-class
provisioner: kubernetes.io/portworx-volume
parameters:
   repl: "1"
---
##### Portworx persistent volume claim
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
   # Important do not change for testing
   name: mysql-data
   namespace: mysql
   annotations:
     volume.beta.kubernetes.io/storage-class: mysql-tester-class
spec:
   accessModes:
     - ReadWriteOnce
   resources:
     requests:
       storage: 12Gi
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: mysql
  namespace: mysql
spec:
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.6
        env:
          # Use secret in real usage
        - name: MYSQL_ROOT_PASSWORD
          value: password
        - name: ENVVARTEST
          value: foo
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-data
        persistentVolumeClaim:
          claimName: mysql-data

$ kubectl apply -f mysql-pwx.yml

pxctl コマンドを使用して、MySQL デプロイメントによって作成された Portworx ボリュームを一覧表示します。

$ kubectl exec $PX_POD -n kube-system -- /opt/pwx/bin/pxctl v l
ID			NAME						SIZE	HA	SHARED	ENCRYPTED	IO_PRIORITY	STATUS				SNAP-ENABLED
911201993725013670	pvc-6ecdbffb-41e3-11e9-918f-42010a8e00c7	12 GiB	1	no	no		LOW		up - attached on 10.142.0.27	no

次に、MySQL データベースにデータをいくつか追加します。

kubectl exec -it  mysql-7f45c7b6c6-5szcn -n mysql -- /bin/bash -c "mysql -uroot -ppassword -D foo -e 'create database foo;'"

kubectl exec -it  mysql-7f45c7b6c6-5szcn -n mysql -- /bin/bash -c "mysql -uroot -ppassword -D foo -e \"CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20),species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);\""

kubectl exec -it  mysql-7f45c7b6c6-5szcn -n mysql -- /bin/bash -c "mysql -uroot -ppassword -D foo -e 'SHOW TABLES;'" 

kubectl exec -it  mysql-7f45c7b6c6-5szcn -n mysql -- /bin/bash -c "mysql -uroot -ppassword -D foo -e 'DESCRIBE pet;'"

kubectl exec -it  mysql-7f45c7b6c6-5szcn -n mysql -- /bin/bash -c "mysql -uroot -ppassword -D foo -e \"INSERT INTO pet VALUES ('Roscoe','Beau','dog','m','2000-03-30',NULL);\""

kubectl exec -it  mysql-7f45c7b6c6-5szcn -n mysql -- /bin/bash -c "mysql -uroot -ppassword -D foo -e 'select * from pet;'"
+----------+-------+---------+------+------------+-------+
| name     | owner | species | sex  | birth      | death |
+----------+-------+---------+------+------------+-------+
| Puffball | Diane | hamster | f    | 1999-03-30 | NULL  |
+----------+-------+---------+------+------------+-------+
1 row in set (0.00 sec)

非同期 PX-DR のセットアップ

スケジュール・ポリシーを適用します。

$ cat policy.yaml 
apiVersion: stork.libopenstorage.org/v1alpha1
kind: SchedulePolicy
metadata:
  name: mysql-policy
  namespace: mysql
policy:
  interval:
    intervalMinutes: 1
  daily:
    time: "10:14PM"
  weekly:
    day: "Thursday"
    time: "10:13PM"
  monthly:
    date: 9
    time: "8:05PM"

$ kubectl apply -f policy.yaml
schedulepolicy.stork.libopenstorage.org/mysql-policy created

$ storkctl get schedulepolicy
NAME           INTERVAL-MINUTES   DAILY    WEEKLY               MONTHLY
mysql-policy   1                  10:14PM  Thursday@10:13PM     9@8:05PM

次に、マイグレーション・スケジュールを構成します。

$ cat mig-schedule.yml
apiVersion: stork.libopenstorage.org/v1alpha1
kind: MigrationSchedule
metadata:
  name: mysqlmigrationschedule
  namespace: mysql
spec:
  template:
    spec:
      clusterPair: incremental-dr
      includeResources: true
      includeVolumes: true
      startApplications: false
      namespaces:
      - mysql
  schedulePolicyName: mysql-policy

$ kubectl apply -f mig-schedule.yml

$ kubectl describe migrationschedules mysqlmigrationschedule -n mysql

以上で完了です!

現在の名前空間のアクティブなマイグレーションのリストを取得するには、kubectl を使用します。ここでは、ポリシーで選択した 1 分の間隔に基づいた初期同期であることを示しています。ポリシーで構成されている時間設定ごとに同期(マイグレーション)が表示されます。

$ kubectl get migration -n mysql
NAME                                                AGE
mysqlmigrationschedule-interval-2019-03-12-150954   7s

マイグレーションの詳細を表示するには、kubectl を使用します。これにより、ボリュームやその他の Kubernetes リソースのマイグレーションの成功または失敗を示す以下のようなイベントが表示されます。

$ kubectl describe migration mysqlmigrationschedule-interval-2019-03-12-150954  -n mysql
.
. 
.
Events:
  Type    Reason      Age   From   Message
  ----    ------      ----  ----   -------
  Normal  Successful  18s   stork  /v1, Kind=PersistentVolumeClaim mysql/mysql-data: Resource migrated successfully
  Normal  Successful  18s   stork  /v1, Kind=PersistentVolume /pvc-0c067805-44d8-11e9-a638-42010a8e0094: Resource migrated successfully
  Normal  Successful  18s   stork  apps/v1, Kind=Deployment mysql/mysql: Resource migrated successfully

また、storkctl コマンドを使用すると、作成したスケジュールで実施されたマイグレーションの成功や失敗、進捗状況といった Stage や Status を表示できます。

$ storkctl get migration -n mysql
NAME                                                CLUSTERPAIR      STAGE     STATUS       VOLUMES   RESOURCES   CREATED
mysqlmigrationschedule-interval-2019-03-12-154216   incremental-dr   Final     Successful   1/1       3/3         12 Mar 19 11:42 EDT
mysqlmigrationschedule-interval-2019-03-12-164400   incremental-dr   Volumes   InProgress   0/1       0/0         12 Mar 19 12:44 EDT

それでは、ソース・クラスタから同期したデータを使用して、DR サイトでアプリケーションをリストアしてみましょう。

まず、新しいクラスタで使用可能なボリュームを確認します。Creation time は、ソース・クラスタからの最新の同期と一致している必要があります。startApplicationsfalse に設定したため、detached になっていることに留意してください。

$ kubectl exec $PX_POD -n kube-system -- /opt/pwx/bin/pxctl v list -l owner=Migration
ID			NAME						SIZE	HA	SHARED	ENCRYPTED	IO_PRIORITY	STATUS		SNAP-ENABLED
696635235911597484	pvc-0c067805-44d8-11e9-a638-42010a8e0094	12 GiB	1	no	no		LOW		up - detached	no

次に、ボリュームを調べて、そのタイム・スタンプをメモします。

$ kubectl exec $PX_POD -n kube-system -- /opt/pwx/bin/pxctl v inspect 696635235911597484
Volume	:  696635235911597484
	Name            	 :  pvc-0c067805-44d8-11e9-a638-42010a8e0094
	Size            	 :  12 GiB
      ...
      
      ...	
	Format          	 :  ext4
	HA              	 :  1
	Creation time   	 :  Mar 12 15:44:23 UTC 2019
	Shared          	 :  no
	Status          	 :  up

DR サイトのクラスタ内にあるポッド(pod)とデプロイメント(deployment)を見て、これらが正しく動作しているかを確認できます。

$ kubectl get po -n mysql
No resources found.

$ kubectl get deployment -n mysql
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
mysql     0         0         0            0           1h

上記のとおり、こちらにはアクティブなポッドはありませんが、デプロイメントが存在します。これは、Kubernetes オブジェクトをマイグレーションするかどうかを設定する includeResourcestrue にしたためです。Kubernetes オブジェクトはマイグレートされましたが、startApplicationsfalse に設定したため、ポッドのアクティブなレプリカはない状態となっています。

【ポイント】Portwox ボリュームのみをマイグレーションし、Kubernetes リソースをマイグレーションしない場合は、includeResourcesfalse に設定します。

 

DR サイトでアプリケーションをリストアするには、storkctl コマンドを使用して、最新のマイグレーションを activate します。

$ storkctl activate migrations -n mysql
Updated replicas for deployment mysql/mysql to 1

次に mysql という名前の名前空間内のポッドを DR サイトで確認します。

$ kubectl get po -n mysql
NAME                        READY     STATUS     RESTARTS   AGE
mysql-7f45c7b6c6-xjcb9      1/1       Running    0          6s

これで、アプリケーションのコピーが DR サイトに正常にリストアされました。

補足情報として、動画をご紹介します。MySQL と WordPress を使用して複数のボリューム、サービスおよびオブジェクトを DR サイトにマイグレーションするという同様のユースケースのデモ動画です。ぜひご覧ください。

 

PX-DR により、さまざまなタイプの災害からのフェイルオーバーが可能となり、より自信を持ってミッション・クリティカルなデータ・サービスを提供できるようになりました。将来のリリースでは、ここでご紹介したクラスタ・ペアリングやレプリケーション・タイプの設定などは、今後 GUI 等の提供により、直感的でシンプルなものにすることを目指してまいります!


Pure Storage、Pure Storage のロゴ、およびその他全ての Pure Storage のマーク、製品名、サービス名は、米国およびその他の国における Pure Storage, Inc. の商標または登録商標です。その他記載の会社名、製品名は、各社の商標または登録商標です。