スマートスタイル TECH BLOG

データベース&クラウド技術情報

Percona XtraBackup + xbcloud で S3 へダイレクトにバックアップする

はじめに

今回の記事は、Percona XtraBackup と、同梱の xbcloud バイナリを使って Amazon S3 および S3 互換のオブジェクトストレージサービスへバックアップを取得する方法を紹介します。

現在(2022年1月12日)の XtraBackup の最新バージョンは 8.0.26-18.0 になります。

Percona XtraBackup 8.0.26-18.0 Release Notes

Percona XtraBackup 8.0.26-18.0 GA版(リリース日:2021年9月2日) ※弊社OSSニュースでのPercona公式リリースノート翻訳

xbcloud は XtraBackup によって取得する(した)バックアップデータを扱う際に xbstream という形式を用いてクラウドサービスへアップロードまたはダウンロードするためのツールです。

The xbcloud Binary

バックアップ取得時の例としては、バックアップデータの出力ストリームをパイプを介してxbcloud に渡す、以下のような実行コマンドになります。

xbcloud がサポートしているクラウドストレージタイプは以下の通りです。

  • OpenStack Object Storage (Swift)
  • Amazon Simple Storage (S3)
  • Google Cloud Storage (gcs)
  • MinIO

S3互換APIを使用しているため、実際は上記サービスのみならず Alibaba Cloud OSS や Wasabi, IBM Cloud Object Storage といったクラウドサービスでも使用可能です。

利点はなんといってもバックアップファイル用のローカルストレージを必要とせず、運用管理やコスト面でメリットがあるオブジェクトストレージに直接バックアップできることが挙げられます。

また、同じような仕組み・方式を取ろうとした場合、 オブジェクトストレージへデータをアップロードする処理で aws cli や rclone, gof3r などのツールを用いるよりもパフォーマンス面で優れているという点もあります。

この辺りの比較検証については、Percona社からブログ記事が公開されていますので、興味がありましたらご一読ください。(Githubに実行コマンドも掲載されています)

Comparing S3 Streaming Tools with Percona XtraBackup – Percona Database Performance Blog

k8s-lab/pxb-s3 at main · Percona-Lab/k8s-lab · GitHub

そして、最新版の 8.0.26-18.0 で追加された新機能 Exponential Backoff によって、バックアップ実行中の転送エラー発生時耐障害性が向上し、信頼性が増しました。

以降では、AWS 環境で xbcloud によるバックアップとリストアの実行方法を紹介します。

更に、後半パートでは MinIO を用いた環境での Exponential Backoff の効果も確認してみたいと思います。

AWS EC2 MySQL + S3 環境での動作確認

環境準備

AWS EC2 に MySQL Community Edition 8.0.26XtraBackup(以降 PXBと表記) 8.0.26-18.0 をインストールします。

今回 EC2インスタンスは t3a.medium、OS は Amazon Linux 2 を選択しました。

MySQL インストール

MySQL のインストールおよびセットアップについての説明は割愛します。 (パラメータはデフォルトのままです)

サンプルデータ(datacharmer/test_db) を投入

バックアップ用に適当なデータを投入しておきます。

PXB インストール

Percona XtraBackup と qpress パッケージをインストールします。

ご参考(弊社過去ブログ記事):Percona XtraBackup 8.0.23 を使ってみる | スマートスタイル TECH BLOG

バックアップ実行ユーザー作成

必要な権限はマニュアルページを参照願います。

S3 バケットを作成

バックアップデータの出力・保管先バケットを作成しておきます。

バックアップの実行

パラメータ構成ファイルを準備する

PXB と xbcloud のコマンドに渡すオプションを別ファイルに外出しで定義できます。
そのままだとコマンドラインが冗長になってしまうのと、バックアップスクリプトなどでオブジェクトストレージへの接続情報が直書きになってしまうのを回避したい場合にお勧めです。

今回の設定例では、xbstream・xbcloud それぞれ 8並列で処理を実行するようにし、各データチャンクファイルは qpress で圧縮しています。
[xbcloud] セクションの s3-bucket に、先ほど作成したバケット名を設定しておきます。

xbcloud S3用オプションについては以下のページをご参照ください。
Using xbcloud Binary with Amazon S3

完全バックアップ

下準備が整ったので、漸くバックアップ実行となります。
まずは完全バックアップを取得してみましょう。

先ほど作成したパラメータ構成ファイルを xtrabackup では --defaults-extra-file, xbcloud では --defaults-file オプションで指定しています。

xbcloud のほうは、マニュアルにこの指定方法が明記されていません。(put/get の前に指定しないと正しく読み込まれないのでご注意ください)

コマンドを実行すると、通常の PXB と同じようにコンソールに実行状況が出力されていきます。

出力内容を見ていくと、xbcloud ツールがオブジェクトストレージへ接続成功した旨が確認できます。

下記のように、qpress(.qp) で圧縮されたバックアップファイルがさらに細切れになりマルチスレッドでアップロードしている様子が確認できます。
各アップロードチャンクサイズはデフォルトで10Mとなります。 (xtrabackup の --read-buffer-size オプションで変更可能です)

上記のメッセージが出力されれば、バックアップ&アップロードが成功です。

無事バックアップコマンドが完了したら、S3 バケット内にバックアップファイルが格納されていることを確認しましょう。

libcurl のバージョンが古い場合に発生する Segmentation fault への対応

なお、今回の Amazon Linux 2 では発生しませんでしたが、CentOS 7 の curl が 7.29.0 とバージョンの古い環境では、バックアップ実行の最終フェーズに、xbcloud が Segmentation fault を引き起こして異常終了するという問題があります。

具体的には xbcloud の Bug ではなく、curl のライブラリの不具合になりますが、マルチパートでアップロードした際に使用していた複数の接続を全て閉じるときに上手く処理しきれずクラッシュが発生してしまう、というものです。

Bug #63799 for WWW-Curl: Segfault if curl handle persists until global destruction

対応方法としては、curl を最新バージョンにアップグレードするか、以下のように libcurl のみ最新版を抽出し、xbcloud に参照させることで回避可能です。ご参考まで。

増分バックアップ実行

増分バックアップは、以下のように前回のバックアップのLSN番号を参照するために --incremental-basedir を付与して実行します。
(よって、この例では累積増分ではなく差分増分バックアップになります)

こちらもバックアップが成功したら、S3 バケット内を確認してみましょう。

リストア

S3 に取得したバックアップ(完全+増分)を使って MySQL をリストアします。

まずはインスタンスを停止し、datadir 配下のファイルを削除しておきます。

完全バックアップのリストア

xbcloud get で完全バックアップのフォルダを指定してダウンロードし、ローカル上の指定のリストアディレクトリに展開します。

実行ログの出力でコンソールがあふれるので、xbcloud によるファイルダウンロードと xbstream によるファイルストリーミングの標準エラー出力を別のログファイルにリダイレクトしています。
実行結果を確認してみましょう。

S3 からローカルへ正常にファイルを取得出来たら、以下のコマンドで解凍とREDOログ適用 (prepare) を行います。

増分バックアップのリストア

増分バックアップの場合も同様のコマンドになります。対象ディレクトリの指定を間違えないようにしましょう。

これは xbcloud に限った話ではありませんが、増分バックアップの prepare についての注意としては、最後の増分バックアップ適用までは、--apply-log-only オプションをつける必要があります。

これは --prepare 実行時のロールバックフェーズを防止するためのものです。
増分バックアップに対してトランザクションがロールバックされてしまうと、それ以降増分バックアップを適用できなくなります。

そのため、逆に一番最後の増分バックアップを適用する時は、下記のように --apply-log-only オプションを付けずロールバックフェーズも含めて適用してください。

バックアップファイルの準備が整ったら、ファイルを datadir にリストアし、MySQLを起動します。

8.0.26-18.0 新機能 Exponential Backoff について

以前のバージョンの PXB では、チャンク操作のエラーが発生した場合、リトライは行われるものの、すぐに復旧できなければプロセスは異常終了してしまっていました。

8.0.26-18.0 で追加された Exponential Backoff と呼ばれる新機能は、この点を克服する目的の仕組みと言えます。

  • xbcloud によるチャンクデータのアップロードまたはダウンロード操作で失敗が発生した場合、そのエラーがリトライ対象と定義されている場合、xbcloud はリトライする前に一定期間スリープ(バックオフ)します。
  • 同じチャンクを指定回数リトライしても以前失敗する場合はプロセス全体が中止されます。

指数バックオフアルゴリズムによってリトライ時のネットワーク輻輳を回避しつつ、極力リトライに努める機能とのことです。

公式ドキュメントによる機能説明および紹介については以下のページをご一読ください。

Exponential Backoff

Introducing xbcloud: Exponential Backoff Feature in Percona XtraBackup – Percona Database Performance Blog

まずは、以前のバージョンの PXB では具体的にどのような挙動となるか、改めて確認してみたいと思います。

MySQL 8.0.25 + PXB 8.0.25-17 をインストールした別環境を用意しておきます。

ただし、S3 の疑似障害を作り出すのがなかなか困難と思い、MinIO でローカルオブジェクトストレージを構築して動作確認を行います。

AWS Fault Injection SimulatorではS3は未対応でした…

環境準備

MinIO をインストール

Go 言語で書かれているので簡単にインストールでき、また docker イメージも用意されていますので手軽に環境構築できます。

インストール手順は公式ドキュメントにあるクイックスタートガイドを元にしました。

以下のコマンドでサービスを起動します。

デフォルトのままなので色々と警告が出ていますが、もし管理者ユーザ名とパスワードを変更したい場合は上記の案内の通り環境変数を設定してサービス起動してください。

また、もし HTTPS/TLSアクセスを試したい場合は、こちらのページを参考に自己署名鍵と証明書を生成して ~/.minio/certs/ ディレクトリに配置してサービスを起動してください。(HTTPSアドレスになります)

MinIO クライアントをインストールしバケットを作成

バケット作成や参照などの操作を行うため、クライアントツールもインストールしておきます。

サーバ同様、至ってシンプルにインストールできます。

先ほどサービス起動したときのコンソール出力の真ん中あたりに表示されていた alias コマンドを実行するとクライアントツールに接続情報をセットしておくことができ便利です。

そのエイリアス名を指定してサービスの稼働状態をコマンドで確認してみます。

バックアップ出力・保管用のバケットを作成しておきます。

バックアップ実行中に S3 サービス停止 : PXB 8.0.25 の場合

MinIO 向けに xbcloud のパラメータを設定します。

バックアップ実行のコマンドは前述同様以下となります。

バックアップ実行後に別コンソールから以下のコマンドを実行し、オブジェクトストレージサービス停止~2分後復旧という状況を発生させます。

すると、PXB 8.0.25 では以下のように「エラー直後4回リトライするものの合計5回のエラー発生で断念し異常終了となる」動作になりました。(エラー発生後1秒以内で異常終了となる)

当然ながらバックアッププロセスは異常終了、オブジェクトストレージ側には中途半端な状態でアップロードされているままとなってしまいます。

バックアップ実行中に S3 サービス停止 : PXB 8.0.26 (Exponential Backoff) の場合

次に 8.0.26 の確認です。まずはパッケージをアップグレードしましょう。

パラメータ構成ファイルに Exponential Backoff 機能のパラメータとなる --max-retries--max-backoff を追加します。

--curl-retriable-errors--http-retriable-errors パラメータについて先に説明してしまいますが、今回動作確認している MinIO による疑似環境では、サービスを停止すると Curl error (7)http error (0) が発生します。

xbcloud の Retriable errors デフォルト定義にはこれらのエラーが含まれていないので、エラー発生時にリトライを行ってくれません。

そのため、リトライ対象となるように今回予め追加している設定になります。

実は、発生したエラーの詳細情報は xbcloud の --verbose を付けて実行することで以下のようにサジェスト込みで確認できますので、これを元に設定を行いました。

実運用でも、デフォルトのリトライ対象エラー以外に対象とすべきエラーを選定するために、この機能を使うのが有益かと考えます。
(ただし curl の実行ログが大量に出力されるので、通常運用には適さず、あくまで障害時調査やデバッグ用と考えてください)

先ほどの 8.0.25 と同じように MinIO のオブジェクトストレージサービスを停止~2分後復旧させてみます。

(長いログになりますが、ご容赦ください…)

以前のバージョンと異なり、Sleeping for XXXX ms before retrying ~~ と表示されるようになったのが確認できます。

対象のチャンクファイルのアップロードをリトライする前に XXXX ミリ秒待機する、という意味合いになります。

メッセージ末尾の [n] はそのチャンクファイルのアップロードに失敗した回数のカウンタです。

ここから待機秒数が増加しています。(2秒台→4秒台)

オブジェクトストレージサービスは依然停止中。ここから更に増加しています。(4秒台→8秒台)

サービス復旧し、失敗していたチャンクのアップロードが再開、成功しました。

アップロード失敗回数が増える度、指数バックオフアルゴリズムに基づいてスリープ秒数が増加設定されます。

これにより、複数のチャンクアップロードにおけるネットワークの輻輳を回避しています。

そして、スリープ秒数の増加上限は --max-backoff で制御できます。(--max-backoff で指定した秒数に到達して以降は、同じ値でスリープする動作となります)

チャンクのアップロード操作失敗回数が --max-retries に達するまで操作はリトライされ、最後のリトライで失敗すると xbcloud プロセスは終了となります。(今回の例では 3/5回 で復旧となりました)

なお、本機能のパラメータを明示的に設定していなくても、8.0.26-18.0 であれば以下のデフォルト値で動作します。

まとめ

PXB 8.0.26-18.0 では、xbcloud によるチャンクデータのマルチパートアップロードという処理特性を生かし、エラー発生時に安全かつ調整可能なリトライが出来るようになり、xbcloud によるバックアップ実行の信頼性が高まりました。

この点を懸念していてこれまで実用を見送っていたり、別の仕組みで実装していたユーザも少なからずいらっしゃるのではと思いますが、ぜひこの機会にお試しいただいてはいかがでしょうか。

Return Top