技術本部 サービスリライアビリティグループ(SRG)の長谷川 @rarirureluis です☺
#SRG(Service Reliability Group)は、主に弊社メディアサービスのインフラ周りを横断的にサポートしており、既存サービスの改善や新規立ち上げ、OSS貢献などを行っているグループです。

弊社では Cycloud と呼ばれる、サイバーエージェント社内で運営されているプライベートクラウドがあります。
CyberAgentのプライベートクラウド Cycloudの運用及びモニタリングについて #CODT2020 / Administration and Monitoring for Cycloud

僕が担当しているいくつかのサービスでも Cycloud を利用していますがその中で問題になるのが 「MySQL のバックアップをどうするか」です。

社内監査の関係で Cycloud の中にバックアップすることは禁止されており、プライベートクラウド外へのバックアップが必須になります。
そんな中で、600GB 程度の MySQL をどうやってパブリッククラウドへバックアップしているかをご紹介したいと思います。
(というより、これから説明する xbcloud に送っていた Feature Request で --s3-storage-classオプションに対応したことでとても使いやすくなったので紹介したかったのが理由です)

GTID ベースのレプリケーション(not Group Replication)環境での説明になりますが、Group Replication 環境でも大体同じです。

ここでは、プライベートクラウド、つまりオンプレミス環境での話でありパブリッククラウド(DBaaS)はまた別の機会でお話しようと思います。

 

バックアップポリシーについて

本題の前に MySQL を始めとしたデータストアのバックアップポリシーを前もって決めておくのが重要です。

バックアップポリシーとはフルバックアップをどれぐらいの頻度で、何世代保存するか等です。

僕が担当しているサービスは

  • フルバックアップは毎日取得し、3世代残す。
  • バイナリログは毎日漏れなくバックアップ

としています。

何故、バックアップが必要か。どういった手法があるのかを紹介している Percona 社のブログ記事を貼っておきます。
MySQL Backup and Recovery Best Practices

そんな MySQL のバックアップには Percona XtraBackup を使うと便利だよというご紹介です。

Percona XtraBackup

Percona XtraBackup(以下 PXB)は Percona 社が公開しているオンラインでMySQLのバックアップを取得できるツールです。
Percona XtraBackup for MySQL Databases

MySQL のバックアップには mysqldump を使用するかと思いますが mysqldump はデータベース内のデータをテキスト(INSERT文)として保存します。
そのため,リストアにも INSERT 文を使用しなければならず、遅いのが欠点です。

PXB は,物理バックアップであり、実際のデータベースのファイルを物理的にコピーすることでバックアップを取得します。リストアはそのファイルに対して,バックアップの開始時間からの差分データをリカバリしてファイルを配置するだけなので,論理バックアップのリストアよりも高速です。

そして mysqld を落とすことなくバックアップすることができます。

xbstream

xbstream はストリーミングフォーマットです。

圧縮とストリーミングを同時にサポートするために、TAR フォーマットに加えて、xbstream と呼ばれる新しいカスタム ストリーミング フォーマットが PXB に導入されました。

従来のストリーミング/アーカイブフォーマットに対する xbstream の他の利点としては、複数のファイルを同時にストリーミングできること (xbstream フォーマットのストリーミングを -parallel オプションと一緒に使用することが可能です) です。

xbcloud

PXB パッケージの中には xbcloud というツールが存在します。

xbcloud の目的は、xbstream ファイルの全部または一部を Amazon S3(以下 S3) や、S3 Compatible なストレージ(minio等)、Google Cloud Storage 等にアップロードすることです。もちろん既存の AWS CLI 等を利用してアップロードすることはできますが、xbcloud は純正ツール(AWS CLI や、gsutil)よりもパフォーマンスに優れています。

xbcloud は backup_name/database/table.ibd.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN のような感じでチャンクとして保存します。

xbcloud と、各 IaaS の純正 CLI とのパフォーマンスの比較記事は Percona 社によって公開されています。
Comparing S3 Streaming Tools with Percona XtraBackup – percona.com

AWS CLI を高速に使用するにはチューニング(AWS CLI の設定変更)が必要ですが、xbcloud ではノーマルでも十分に高速に動作します。
xbcloud の方が優位だなと個人的に思っている理由は、ここであり CI や導入の手軽さが AWS CLI よりもあります。

 

インストール

AWS CLI を使う場合は pip で入れて、pip install が必要ですが(v1 まで。v2 以降はスクリプトをダウンロードして実行、インストールという若干簡素化されました)、xbcloud は percona-xtrabackup を入れれば全て勝手に入ります。
何が嬉しいかというと Ansible で管理するときや、CI で使う場合では楽になります。

インストール手順は公式をご覧ください。
Installing Percona XtraBackup 8.0

インストールするバージョンは使っている MySQL のバージョンによって変わります。
今回は MySQL 8.0.22 + XtraBackup 8.0 で試します。

 

バックアップ

xtrabackup はフルバックアップ、差分バックアップに対応しています。

$ xtrabackup --backup --stream=xbstream --target-dir=/tmp --user=root --password='' --safe-slave-backup --slave-info --compress --parallel=16 | xbcloud put --storage=s3 --s3-endpoint=s3.ap-northeast-1.amazonaws.com --s3-region=ap-northeast-1 --s3-storage-class=STANDARD --s3-access-key='' --s3-secret-key='' --s3-bucket=bucket --parallel=16 path/to/backup

上記の例では、実際に S3 へフルバックアップを行っているコマンドです。

詳しいオプション等は公式ドキュメントをご覧ください。
The xtrabackup Option Reference

xtrabackup はストレージ料金を削減するために --compress を使うファイル自体を圧縮します。
xbcloud では --s3-storage-class='STANDARD'を設定して S3 へアップロードしています。

--s3-storage-class を適用させるために --s3-regionを指定しないといけないようです。
[PXB-2386] –s3-storage-class is not working. – Percona JIRA

--s3-storage-class に対応しているバージョンは

  • ~> 2.4.21
  • ~> 8.0.22-15.0

それ以下のバージョンのストレージクラスは S3 の場合 STANDARD がデフォルトになります。

ストレージクラスを何にするかはバックアップの頻度、目的、容量によって変わります。
僕の環境ではレプリカの追加や、検証環境の作成であればレプリケーションの中にあるサービスから参照されないレプリカがあるためそこから作成することはできます。

前述の通り僕が担当しているサービスでは毎日フルバックアップを取得し、3世代分残すというポリシーのため
STANDARDクラスを利用しています。
(ONEZONE_IA やその他では、最小ストレージ期間が 30日等に設定されており、30日以内にオブジェクトを削除しても 30日分の課金が発生します)
Amazon S3 ストレージクラス – Amazon Simple Storage Service

STANDARD ではなく、ONEZONE_IA で保存したい!という場合もあると思うので今回の –s3-storage-class はとても良い機能追加だと思います。

 

リストア

上記でバックアップした場合のリストア方法になります。

S3 からバックアップを取得

$ cd /mnt/data
$ xbcloud get s3://bucket/path/to/backup --storage=s3 --s3-endpoint=s3.ap-northeast-1.amazonaws.com --s3-access-key='' --s3-secret-key='' --parallel=16 2>download.log | xbstream -x -C restore --parallel=16

compress したので decompress

$ xtrabackup --decompress --target-dir=/mnt/data/restore --remove-original

--remove-original をつけるとストレージ容量を圧迫せずに解凍できます。

ここからはお作法

$ xtrabackup --prepare --target-dir=/mnt/data/restore
$ xtrabackup ---move-back /mnt/data/restore
$ mv /mnt/data/restore /path/to/datadir
$ chown -R mysql: /path/to/datadir
$ systemctl start mysqld

GTID 関連

バックアップを取得すると xtrabackup_slave_infoファイルに GTID 環境の場合は GTID_PURGED が記載されています。
※ バックアップ時に --slave-info が必要

その値を復元した 復元した MySQL に適用します。

SET GLOBAL GTID_PURGED='e9043a49-18c3-11ea-89ae-fa163e4dcf94:1-183923308';

その後、レプリケーションをスタートさせます。

CHANGE MASTER TO 省略, mysql_auto_position=1;

XtraBackup + xbcloud ぜひ使ってみてください☺