はじめに
今回は、mariadb-operatorのバックアップ及びリストアについて検証しました。
mariadb-operatorは、クラウドネイティブな環境でMariaDBを効率的に運用するためのツールです。以下のように、柔軟で便利なバックアップ機能があります。
mariadb-operator/mariadb-operator: Run and operate MariaDB in a cloud native way
- 柔軟なストレージ構成。ボリューム拡張。
- バックアップを作成、復元、スケジュールします。
- 複数のバックアップ ストレージ タイプ: S3 互換、PVC、Kubernetes ボリューム。
- bzip および gzip圧縮オプションを使用したポリシー駆動型のバックアップ保持。
- ターゲット復旧時間: 指定された時間に最も近い利用可能なバックアップを復元します。
- バックアップ、S3、PVC などから新しいインスタンスをブートストラップします。
また、インストール方法につきまして、前回ブログで紹介しておりますので良ければ先にご参照いただけますと幸いです。
Kubernetes mariadb-operatorでクラウドネイティブなデータベース運用【構築編】
mariadb-operatorのインストール
今回の検証用に新しくmariadb-operator
というNamespaceを作成します。
1 2 |
kubectl create namespace mariadb-operator kubectl config set-context --current --namespace mariadb-operator |
mariadb-operatorをHelmチャートからインストールします。
1 2 3 4 |
helm repo add mariadb-operator https://helm.mariadb.com/mariadb-operator helm repo update mariadb-operator helm install mariadb-operator-crds mariadb-operator/mariadb-operator-crds helm install mariadb-operator mariadb-operator/mariadb-operator |
インストールされたことの確認です。
1 2 3 4 5 6 7 8 9 10 |
$ helm list NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION mariadb-operator mariadb-operator 1 2025-05-15 10:33:11.555626587 +0900 JST deployed mariadb-operator-0.38.1 0.38.1 mariadb-operator-crds mariadb-operator 1 2025-05-15 10:33:10.369655079 +0900 JST deployed mariadb-operator-crds-0.38.1 0.0.0 $ kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE mariadb-operator 1/1 1 1 77s mariadb-operator-cert-controller 1/1 1 1 77s mariadb-operator-webhook 1/1 1 1 77s |
後で使うので、Gitリポジトリをクローンしておきます。
1 2 |
git clone --depth=1 https://github.com/mariadb-operator/mariadb-operator.git cd mariadb-operator |
MariaDB Galera Clusterの作成
バックアップ検証用のMariaDBリソースをGalera Cluster構成で作成していきます。
パスワード用のSecretを事前に作成しておきます。
1 2 3 4 5 6 7 8 9 10 11 |
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: mariadb labels: k8s.mariadb.com/watch: "" stringData: password: MariaDB11! root-password: MariaDB11! EOF |
MariaDBリソースを作成します。
rootPasswordSecretKeyRef
:先ほど作成したSecret名を指定します。replica
:Galera Cluster構成の場合は、3台以上にする必要があります。galera
:true
を指定してGalera Clusterを有効化します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
cat <<EOF | kubectl apply -f - apiVersion: k8s.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera spec: rootPasswordSecretKeyRef: name: mariadb key: root-password storage: size: 1Gi replicas: 3 galera: enabled: true service: type: LoadBalancer metadata: annotations: metallb.universe.tf/loadBalancerIPs: 172.18.0.150 primaryService: type: LoadBalancer metadata: annotations: metallb.universe.tf/loadBalancerIPs: 172.18.0.160 secondaryService: type: LoadBalancer metadata: annotations: metallb.universe.tf/loadBalancerIPs: 172.18.0.161 metrics: enabled: true EOF |
作成してしばらく待つと、mariadb-galeraというMariaDBリソースが起動します。
1 2 3 |
$ kubectl get mariadbs NAME READY STATUS PRIMARY UPDATES AGE mariadb-galera True Running mariadb-galera-0 ReplicasFirstPrimaryLast 3m |
テストデータ投入
色々やり方はあると思いますが、深くは考えずに原始的なやり方でデータ投入しようと思います。
接続用にPodを作成して、Sakila Sample Database をインポートします。
接続に使用するホスト名は、MariaDBリソースと同時に作成されるサービス名を指定することができます。
クラスター内部接続用のmariadb-galera-internal
を用いて、mariadb-galera-internal.mariadb-operator.svc.cluster.local
とDNS名を指定します。
1 2 3 4 5 6 |
export MARIADB_ROOT_PASSWORD=$(kubectl get secret/mariadb \ -ojsonpath="{.data.root-password}" | base64 -d) kubectl run connect --image=mariadb:11.4.5 --rm -it --restart=Never \ -- sh -c "mariadb -u root -p$MARIADB_ROOT_PASSWORD -P 3306 \ -h mariadb-galera-internal.mariadb-operator.svc.cluster.local" |
プライマリに接続していることがhostnameから確認できます。
1 2 3 4 5 6 7 |
MariaDB [(none)]> select @@hostname; +------------------+ | @@hostname | +------------------+ | mariadb-galera-0 | +------------------+ 1 row in set (0.000 sec) |
MariaDBターミナルはそのままにしておき、
別のターミナルを立ち上げて、データインポート用SQLファイルをコピーします。
1 2 3 4 |
wget https://downloads.mysql.com/docs/sakila-db.tar.gz tar xvf sakila-db.tar.gz kubectl cp sakila-db/sakila-data.sql connect:/tmp/ kubectl cp sakila-db/sakila-schema.sql connect:/tmp/ |
MariaDBターミナルに戻り、sourceコマンドでインポートします。
sakilaデータベースの存在が確認できました。
1 2 3 4 5 6 7 8 9 |
MariaDB [(none)]> source /tmp/sakila-schema.sql MariaDB [(none)]> source /tmp/sakila-data.sql MariaDB [(none)]> show database like 'sakila'; +-------------------+ | Database (sakila) | +-------------------+ | sakila | +-------------------+ 1 row in set (0.001 sec) |
S3互換ストレージへバックアップ
バックアップは、大きく分けて3種類のストレージタイプがサポートされています。
- S3互換ストレージ
- PVC(Persistent Volume Claim)
- その他のKubernetesでネイティブサポートされているボリューム
今回の検証では、S3互換ストレージのMinIOを使用していきます。
事前にMinIO用のアクセスキーなどのSecretを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Secret metadata: name: minio stringData: access-key-id: mariadb-operator secret-access-key: Minio11! session-token: token --- apiVersion: v1 kind: Secret metadata: name: minio-play stringData: access-key-id: Q3AM3UQ867SPQQA43P2F secret-access-key: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG session-token: token EOF |
MinIOおよびmcクライアントのインストール
MinIOは、mariadb-operatorのGitリポジトリに同梱されているmakeコマンドで簡単にインストールできるようになっています。
Namespaceなど、今回の検証用に少しスクリプトを修正してから行います。
1 2 3 4 5 6 7 8 |
sed -i.bk 's/$(EC_HASH) -sha256 -days/$(EC_HASH) -days/' make/pki.mk sed -i 's/CA_SECRET_NAMESPACE=default/CA_SECRET_NAMESPACE=$(CA_SECRET_NAMESPACE)/' make/pki.mk sed -i 's/CERT_SECRET_NAMESPACE=default/CERT_SECRET_NAMESPACE=$(CERT_SECRET_NAMESPACE)/' make/pki.mk CA_SECRET_NAMESPACE=mariadb-operator \ MARIADB_NAMESPACE=mariadb-operator \ CERT_SECRET_NAMESPACE=mariadb-operator \ make install-minio |
makeコマンドにより必要なリソースが自動的に作成されたことが確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ helm --namespace minio ls NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION minio minio 1 2025-05-15 10:13:49.478160598 +0900 JST deployed minio-5.4.0 RELEASE.2024-12-18T13-15-44Z $ kubectl --namespace minio get deployments,services,secret NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/minio 1/1 1 1 3m46s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/minio LoadBalancer 10.96.161.244 <pending> 9000:30815/TCP 3m46s service/minio-console LoadBalancer 10.96.222.14 <pending> 9001:31451/TCP 3m46s NAME TYPE DATA AGE secret/minio Opaque 2 3m46s secret/minio-tls kubernetes.io/tls 2 3m46s secret/sh.helm.release.v1.minio.v1 helm.sh/release.v1 1 3m46s |
ポートフォワードしてホストOSから接続できるようにします。
1 |
kubectl port-forward -n minio svc/minio 9000:9000 & |
MinIO のデフォルト認証情報を取得し、mcクライアント接続用のエイリアスを作成します。
1 2 3 4 5 6 |
export MINIO_ROOT_USER=$(kubectl get secret minio \ --namespace minio -o jsonpath="{.data.rootUser}" | base64 --decode) export MINIO_ROOT_PASSWORD=$(kubectl get secret minio \ --namespace minio -o jsonpath="{.data.rootPassword}" | base64 --decode) export MC_HOST_minio_local=https://$MINIO_ROOT_USER:$MINIO_ROOT_PASSWORD@localhost:9000 |
mcクライアントを公式リファレンス MinIO Client — MinIO Object Storage for Linux を参考にインストールします。
1 2 3 |
curl -fLO https://dl.min.io/client/mc/release/linux-amd64/mc chmod +x mc sudo mv mc /usr/local/bin/ |
これで、mcクライアントが使えるようになりました。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ mc --version mc version RELEASE.2025-04-16T18-13-26Z (commit-id=b00526b153a31b36767991a4f5ce2cced435ee8e) Runtime: go1.24.2 linux/amd64 Copyright (c) 2015-2025 MinIO, Inc. License GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html> $ mc --insecure ls minio_local Handling connection for 9000 [2025-05-15 10:14:01 JST] 0B backups/ [2025-05-15 10:14:01 JST] 0B test-backup/ [2025-05-15 10:14:04 JST] 0B test-mariadb/ [2025-05-15 10:14:04 JST] 0B test-restore/ |
フルバックアップ
まずフルバックアップの取得方法です。
Backupリソースを作成します。
args
:バックアップは、mariadb-dump
を内部的に実行する論理バックアップとなっています。mariadb-dump
のすべてのオプションをサポートしているわけではありませんが一部は使えるようです。ここでは--single-transaction --all-databases --verbose
を指定しています。- 物理バックアップは実装されておらず、今後のアップデートに期待です。
schedule.cron
:時刻を指定して、CronJobを作成することが可能になっています。検証のため、1分間隔でバックアップを取得します。mariaDbRef.name
:対象のMariaDBリソースの名前を指定します。storage
:S3ストレージの情報を指定しています。storage.s3.prefix
:MinIOのプレフィックスを指定します。
stagingStorage
:S3ストレージを使用する場合に必要です。Podのローカルストレージがいっぱいになるのを回避するため、別途PVCにステージング領域を定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
cat <<EOF | kubectl apply -f - apiVersion: k8s.mariadb.com/v1alpha1 kind: Backup metadata: name: backup-scheduled spec: mariaDbRef: name: mariadb-galera schedule: cron: "*/1 * * * *" # every 1 minute suspend: false timeZone: "UTC" maxRetention: 720h # 30 days compression: bzip2 storage: s3: bucket: backups prefix: mariadb-galera endpoint: minio.minio.svc.cluster.local:9000 accessKeyIdSecretKeyRef: name: minio key: access-key-id secretAccessKeySecretKeyRef: name: minio key: secret-access-key tls: enabled: true caSecretKeyRef: name: minio-ca key: ca.crt # Define a PVC to use as staging area for keeping the backups while they are being processed. stagingStorage: persistentVolumeClaim: resources: requests: storage: 10Gi accessModes: - ReadWriteOnce args: - --single-transaction - --all-databases - --verbose logLevel: info EOF |
Backupリソースの作成が確認できます。
作成後は、CronJobによって1分ごとにバックアップジョブが作成され続けます。
1 2 3 |
$ kubectl get backups NAME COMPLETE STATUS MARIADB AGE backup True Success mariadb-galera 15m |
MinIOストレージにもファイルが保管されていることが確認できました。
1 2 3 4 5 6 7 |
$ mc --insecure ls minio_local/backups/mariadb-galera Handling connection for 9000 Handling connection for 9000 Handling connection for 9000 [2025-05-15 11:17:07 JST]1011KiB STANDARD backup.2025-05-15T02:17:04Z.bzip2.sql [2025-05-15 11:18:03 JST]1011KiB STANDARD backup.2025-05-15T02:18:00Z.bzip2.sql [2025-05-15 11:19:04 JST]1011KiB STANDARD backup.2025-05-15T02:19:00Z.bzip2.sql |
リストア
ブートストラップ機能
ブートストラップ機能を使って、取得したバックアップをリストアし新規MariaDBリソースを作成することが可能です。
MariaDBのクローンを作成するイメージを持ってもらえば良いと思います。
bootstrapFrom
:先ほど取得したバックアップの情報を指定します。bootstrapFrom.restoreJob.args
:バックアップ時同様にmariadb-dumpの追加オプションを指定できます。ここでは--verbose
オプションを指定しています。bootstrapFrom.targetRecoveryTime
:リカバリしたい日時を指定します。指定した日付以前で取得したバックアップがリストアに使用されるようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
cat <<EOF | kubectl apply -f - apiVersion: k8s.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb-galera-from-s3 spec: rootPasswordSecretKeyRef: name: mariadb key: root-password storage: size: 1Gi replicas: 3 galera: enabled: true bootstrapFrom: s3: bucket: backups prefix: mariadb-galera endpoint: minio.minio.svc.cluster.local:9000 accessKeyIdSecretKeyRef: name: minio key: access-key-id secretAccessKeySecretKeyRef: name: minio key: secret-access-key tls: enabled: true caSecretKeyRef: name: minio-ca key: ca.crt targetRecoveryTime: 2025-05-15T02:18:30Z stagingStorage: persistentVolumeClaim: resources: requests: storage: 1Gi accessModes: - ReadWriteOnce restoreJob: metadata: labels: sidecar.istio.io/inject: "false" args: - --verbose service: type: LoadBalancer metadata: annotations: metallb.universe.tf/loadBalancerIPs: 172.18.0.150 primaryService: type: LoadBalancer metadata: annotations: metallb.universe.tf/loadBalancerIPs: 172.18.0.160 secondaryService: type: LoadBalancer metadata: annotations: metallb.universe.tf/loadBalancerIPs: 172.18.0.161 metrics: enabled: true EOF |
すべてのPodが起動し終えたら、リストアジョブが開始されます。
1 2 3 |
$ kubectl get restores -w NAME COMPLETE STATUS MARIADB AGE mariadb-galera-from-s3-restore True Success mariadb-galera-from-s3 12s |
リストアジョブが完了したら、無事にMariaDBを使用開始することができます。
1 2 3 |
$ kubectl get mariadbs/mariadb-galera-from-s3 NAME READY STATUS PRIMARY UPDATES AGE mariadb-galera-from-s3 True Running mariadb-galera-from-s3-0 ReplicasFirstPrimaryLast 165m |
ちゃんとsakilaデータベースがリストアされた状態で作成されていました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ kubectl run connect --image=mariadb:11.4.5 --rm -it --restart=Never \ -- sh -c "mariadb -u root -p$MARIADB_ROOT_PASSWORD -P 3306 \ -h mariadb-galera-from-s3-internal.mariadb-operator.svc.cluster.local" If you don't see a command prompt, try pressing enter. MariaDB [sakila]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sakila | | sys | +--------------------+ 5 rows in set (0.001 sec) |
部分バックアップ・部分リストア
部分バックアップ
mariadb-dumpのオプションではなく、Backupリソースには専用のdatabases
フィールドが用意されていますので、そちらを使用して部分バックアップが取得可能です。
databases
:バックアップしたいデータベースを複数指定できます。args
:--all-databases
オプションは外しておきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
cat <<EOF | kubectl apply -f - apiVersion: k8s.mariadb.com/v1alpha1 kind: Backup metadata: name: backup-partial spec: mariaDbRef: name: mariadb-galera databases: - sakila maxRetention: 720h # 30 days compression: bzip2 storage: s3: bucket: backups prefix: mariadb-galera-partial endpoint: minio.minio.svc.cluster.local:9000 accessKeyIdSecretKeyRef: name: minio key: access-key-id secretAccessKeySecretKeyRef: name: minio key: secret-access-key tls: enabled: true caSecretKeyRef: name: minio-ca key: ca.crt # Define a PVC to use as staging area for keeping the backups while they are being processed. stagingStorage: persistentVolumeClaim: resources: requests: storage: 10Gi accessModes: - ReadWriteOnce args: - --single-transaction - --verbose logLevel: info EOF |
MinIOストレージにもファイルが保管されていることが確認できました。
1 2 3 |
$ mc --insecure ls minio_local/backups/mariadb-galera-partial Handling connection for 9000 [2025-05-19 18:03:36 JST] 584KiB STANDARD backup.2025-05-19T09:03:35Z.bzip2.sql |
部分リストア
リストア対象のsakilaデータベースを削除しておきます。
1 2 |
MariaDB [(none)]> drop database sakila; Query OK, 23 rows affected (0.162 sec) |
Restoreリソースを作成します。
database
:注意点として、部分バックアップ作成時は複数指定が可能でしたが、部分リストアでは単一のデータベースしか指定できません。またフィールド名も単数形になっています。
123456789101112131415161718192021222324252627282930cat <<EOF | kubectl apply -f -apiVersion: k8s.mariadb.com/v1alpha1kind: Restoremetadata:name: restore-partialspec:mariaDbRef:name: mariadb-galeradatabase: sakilatargetRecoveryTime: 2025-05-15T02:18:30Zs3:bucket: backupsprefix: mariadb-galera-partialendpoint: minio.minio.svc.cluster.local:9000region: us-east-1accessKeyIdSecretKeyRef:name: miniokey: access-key-idsecretAccessKeySecretKeyRef:name: miniokey: secret-access-keytls:enabled: truecaSecretKeyRef:name: minio-cakey: ca.crtargs:- --verboselogLevel: infoEOF
残念ながら作成エラーとなってしまいました。
1 2 3 |
$ kubectl get restores NAME COMPLETE STATUS MARIADB AGE restore-partial False Running mariadb-galera 13s |
エラーメッセージを読むと、sakilaデータベースが存在していないのが原因のようです。
1 2 3 4 |
$ kubectl logs job/restore-partial Defaulted container "mariadb" out of: mariadb, mariadb-operator (init) Restoring backup: /backup/mariadb-galera-sakila/backup.2025-05-19T09:03:35Z.sql ERROR 1049 (42000): Unknown database 'sakila' |
リストア対象のデータベースを事前に作成しておきます。
1 2 |
MariaDB [(none)]> create database sakila; Query OK, 1 row affected (0.005 sec) |
一旦削除し、先ほどと同じものを再作成します。
1 2 3 4 5 6 7 8 |
$ kubectl delete restore/restore-partial restore.k8s.mariadb.com "restore-partial" deleted $ cat <<EOF | kubectl apply -f - apiVersion: k8s.mariadb.com/v1alpha1 kind: Restore (...) restore.k8s.mariadb.com/restore-partial created |
リストアジョブが完了していました。
1 2 3 |
$ kubectl get restores NAME COMPLETE STATUS MARIADB AGE restore-partial True Success mariadb-galera 11s |
中のデータがリストアされていることを確認しました。
1 2 3 4 5 6 7 |
MariaDB [sakila]> select count(*) from sakila.rental; +----------+ | count(*) | +----------+ | 16044 | +----------+ 1 row in set (0.003 sec) |
まとめ
今回はバックアップ及びリストアについて検証しました。
現在も新機能開発が盛んに行われているようですので、物理バックアップ機能やPITR機能など、mariadb-operatorの今後の改良に期待大ですね。
ロードマップは以下から確認できるので、是非チェックしてみてください。
mariadb-operator/ROADMAP.md at main · mariadb-operator/mariadb-operator