kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

Percona XtraDB Clusterを試す

ゆえあってPercona XtraDB Clusterを試すメモです。基本的には公式のGetting Startを試すだけですw

環境

環境はVagrantで作ります。Vagrantfileはこんな感じ。

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vagrant.plugins = ["vagrant-vbguest", "vagrant-hostmanager"]
  config.hostmanager.enabled = true
  config.hostmanager.manage_guest = true

  config.vm.box = "centos/7"
  config.vm.synced_folder "./share", "/share" , type: "virtualbox"

  (1..3).each do |n|
    config.vm.define "node-#{n}" do |c|
      c.vm.hostname = "node-#{n}.internal"
      c.vm.network "private_network", ip: "192.168.33.2#{n}"
      c.vm.provider "virtualbox" do |v|
        v.gui = false
        v.cpus = 1
        v.memory = 1024
      end
      c.vm.provision "shell", :path => "base-setup.sh"
    end
  end
end

障害時のsplit brainを避けるためには最低3台必要です。OSは今回はCentOS7でやります。

起動します。

$ vagrant up

事前準備として以下が必要です。

  • SELinuxはpermissive
  • ポート3306/4444/4567/4568が開放されている

このあたりは起動時にプロビジョニング用のシェルスクリプト(base-sety)で行っています。

#!/bin/bash

set -euo pipefail

# disable SELinux
sudo setenforce 0
sudo sed -i -e "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

# disable firewalld
sudo systemctl stop firewalld
sudo systemctl disable firewalld

# set timezone
sudo timedatectl set-timezone Asia/Tokyo

Percona XtraDB Clusterのインストール

各nodeにPerconaのレポジトリを追加します。

$ for i in {1..3}; do vagrant ssh -c "sudo yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm" node-${i}; done

Percona XtraDB Clusterをインストールします。

$ for i in {1..3}; do vagrant ssh -c "sudo yum -y install Percona-XtraDB-Cluster-57" node-${i}; done

1台目ノードの設定

ここからは1台づつやります。まず、1台目のノードにsshします。

$ vagrant ssh node-1

Percona XtraDB Clusterを起動します。サービス名はMySQLと同じです、というか、普通にDBにアクセスする分にはMySQLと同じ感じでいけるみたいです。

$ sudo systemctl start mysql
$ sudo systemctl status mysql
● mysql.service - Percona XtraDB Cluster
   Loaded: loaded (/usr/lib/systemd/system/mysql.service; enabled; vendor preset: disabled)
   Active: active (running) since 日 2021-12-12 19:05:12 JST; 10s ago
  Process: 28558 ExecStartPost=/usr/bin/mysql-systemd start-post $MAINPID (code=exited, status=0/SUCCESS)
  Process: 28488 ExecStartPre=/usr/bin/mysql-systemd start-pre (code=exited, status=0/SUCCESS)
 Main PID: 28557 (mysqld_safe)
   CGroup: /system.slice/mysql.service
           ├─28557 /bin/sh /usr/bin/mysqld_safe --basedir=/usr
           └─28960 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql -..
(snip)

MySQLと同様、初回起動時にrootのテンポラリなパスワードが設定されますので、これを確認します。各ノードごとに異なるので注意してください。

$ sudo grep 'temporary password' /var/log/mysqld.log
2021-12-12T10:05:05.940157Z 1 [Note] A temporary password is generated for root@localhost: XXXXXXXX

表示されたパスワードを使って、スーパーユーザ(root)でPerconaにログインします。

$ mysql -u root -p
Enter password: XXXXXXXX
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 5.7.35-38-57-log

Copyright (c) 2009-2021 Percona LLC and/or its affiliates
Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

スーパーユーザのパスワードを変更します。

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'スーパーユーザのパスワード';
Query OK, 0 rows affected (0.01 sec)

次にPerconaがノードの同期に使用するユーザを追加しパスワードおよび権限を設定します。

mysql> CREATE USER 'sstuser'@'localhost' IDENTIFIED BY 'SSTのパスワード';
Query OK, 0 rows affected (0.01 sec)

mysql> GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO 'sstuser'@'localhost';
Query OK, 0 rows affected (0.01 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)

Perconaから抜けて一旦停止します。

mysql> quit
Bye
$ sudo systemctl stop mysql

Perconaの設定ファイル(/etc/percona-xtradb-cluster.conf.d/wsrep.cnf)を設定します。

$ sudo vi /etc/percona-xtradb-cluster.conf.d/wsrep.cnf

変更箇所だけ抜粋します。

# クラスタを構成する各ノードのIPアドレスを列挙します。
wsrep_cluster_address=gcomm://192.168.56.21,192.168.56.22,192.168.56.23

# 現在のノードのホスト名およびIPアドレスを設定します。
wsrep_node_address=192.168.56.21
wsrep_node_name=node-1.internal

# SSTユーザ及びパスワードを設定します
wsrep_sst_auth="sstuser:SSTのパスワード"

ではPerconaを起動します。クラスタ内で1台目のノードを起動する場合は以下のように起動します。

$ sudo systemctl start mysql@bootstrap.service

$ systemctl status mysql@bootstrap.service
● mysql@bootstrap.service - Percona XtraDB Cluster with config /etc/sysconfig/mysql.bootstrap
   Loaded: loaded (/usr/lib/systemd/system/mysql@.service; disabled; vendor preset: disabled)
   Active: active (running) since 日 2021-12-12 20:17:45 JST; 1min 15s ago
(snip)

起動したらmysqlコマンドでログインします。

$ mysql -u root -p

クラスタの状態を確認します。

mysql> show status like 'wsrep%';

+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| wsrep_local_state_uuid           | e51d77cf-5b39-11ec-bfac-f61aad5f31eb |
(...snip...)
| wsrep_local_state                | 4                                    |
| wsrep_local_state_comment        | Synced                               |
(...snip...)
| wsrep_incoming_addresses         | 192.168.56.21:3306                   |
(...snip...)
| wsrep_cluster_size               | 1                                    |
| wsrep_cluster_state_uuid         | e51d77cf-5b39-11ec-bfac-f61aad5f31eb  |
(...snip...)
| wsrep_cluster_status             | Primary                              |
| wsrep_connected                  | ON                                   |
(...snip...)
| wsrep_ready                      | ON                                   |
+----------------------------------+--------------------------------------+
75 rows in set (0.01 sec)

wsrep_cluster_statusがPrimaryになっていて、wsrep_local_state_commentがSyncedになっていれば、同期が取れておりクラスタとして正常に動作していると判断して良さそうです。wsrep_local_state_uuidがノードの状態IDで、wsrep_cluster_state_uuidがクラスタとしての状態です。ここが一致しているのでSyncedというわけですね。

wsrep_cluster_sizeがクラスタに参加しているノードの数ですね。wsrep_incoming_addressesには1台目のノードのIPアドレスが表示されています。

これで1台目のセットアップは完了です。

2台目以降のノードの設定

続けて2台め以降のノードの設定を行っていきましょう。基本的には1台目と大きく変わるわけではありません。

ノードにsshします。

$ vagrant ssh node-2

2台目以降ではスーパユーザーのパスワード設定は不要です。1台目と同じようにPerconaの設定を行います。

$ sudo vi /etc/percona-xtradb-cluster.conf.d/wsrep.cnf

変更箇所だけ抜粋します。wsrep_node_addressとwsrep_node_nameだけが各ノード似合わせて設定する必要がある箇所で、あとは共通です。

wsrep_cluster_address=gcomm://192.168.56.21,192.168.56.22,192.168.56.23

# 現在のノードのホスト名およびIPアドレスを設定します。
wsrep_node_address=192.168.56.22
wsrep_node_name=node-2.internal

# SSTユーザ及びパスワードを設定します
wsrep_sst_auth="sstuser:SSTのパスワード"

ではPerconaを起動します。今度は普通にmysqlを起動する感じでOKです。

$ sudo systemctl start mysql

$ sudo systemctl status mysql
● mysql.service - Percona XtraDB Cluster
   Loaded: loaded (/usr/lib/systemd/system/mysql.service; enabled; vendor preset: disabled)
   Active: active (running) since 日 2021-12-12 21:02:30 JST; 15s ago
(snip)

ではPerconaにスーパーユーザでアクセスしてみましょう。パスワードは1台目と同じものを指定します。

$ mysql -u root -p
Enter password:
(snip)
mysql> 

ログインできましたね。パスワードも同期されているということですね。

Perconaの状態も見てみましょう。

mysql> show status like 'wsrep%';
+----------------------------------+---------------------------------------+
| Variable_name                    | Value                                 |
+----------------------------------+---------------------------------------+
| wsrep_local_state_uuid           | e51d77cf-5b39-11ec-bfac-f61aad5f31eb  |
(...snip...)
| wsrep_local_state                | 4                                     |
| wsrep_local_state_comment        | Synced                                |
(...snip...)
| wsrep_incoming_addresses         | 192.168.56.21:3306,192.168.56.22:3306 |
(...snip...)
| wsrep_cluster_size               | 2                                     |
| wsrep_cluster_state_uuid         | e51d77cf-5b39-11ec-bfac-f61aad5f31eb  |
(...snip...)
| wsrep_cluster_status             | Primary                               |
| wsrep_connected                  | ON                                    |
(...snip...)
| wsrep_ready                      | ON                                    |
+----------------------------------+---------------------------------------+
75 rows in set (0.00 sec)

wsrep_incoming_addressesがふえて、wsrep_cluster_sizeが2になりました。つまりノードがクラスタに追加されたというわけですね。

またwsrep_local_state_uuid、wsrep_cluster_state_uuidともに1台目の状態IDと同じ、つまり1台目と同じ状態だということを表しています。

ちなみに1台目でも同じように表示されるはずです。

では、3台目も同様に設定すると最終的にはこうなります。

mysql> show status like 'wsrep%';
+----------------------------------+----------------------------------------------------------+
| Variable_name                    | Value                                                    |
+----------------------------------+----------------------------------------------------------+
| wsrep_local_state_uuid           | e51d77cf-5b39-11ec-bfac-f61aad5f31eb                     |
(...snip...)
| wsrep_local_state                | 4                                                        |
| wsrep_local_state_comment        | Synced                                                   |
(...snip...)
| wsrep_incoming_addresses         | 192.168.56.23:3306,192.168.56.21:3306,192.168.56.22:3306 |
(...snip...)
| wsrep_cluster_size               | 3                                                        |
(...snip...)
| wsrep_cluster_state_uuid         | e51d77cf-5b39-11ec-bfac-f61aad5f31eb                     |
| wsrep_cluster_status             | Primary                                                  |
| wsrep_connected                  | ON                                                       |
(...snip...)
| wsrep_ready                      | ON                                                       |
+----------------------------------+----------------------------------------------------------+
75 rows in set (0.01 sec)

動作確認

では動作確認を行ってみましょう。

node-1でデータベースを作成します。

# node-1

mysql> CREATE DATABASE percona;

node-2でテーブルを作成します。

# node-2

mysql> USE percona;
Database changed
mysql> CREATE TABLE example (node_id INT PRIMARY KEY, node_name VARCHAR(30));
Query OK, 0 rows affected (0.02 sec)

node-3でデータを追加します。

# node-3

mysql> INSERT INTO percona.example VALUES (1, 'percona1');
Query OK, 1 row affected (0.02 sec)

各ノードでSELECTしてみます。

# node-1

mysql> SELECT * FROM percona.example;
+---------+-----------+
| node_id | node_name |
+---------+-----------+
|       1 | percona1  |
+---------+-----------+
1 row in set (0.00 sec)
# node-2

mysql> SELECT * FROM percona.example;
+---------+-----------+
| node_id | node_name |
+---------+-----------+
|       1 | percona1  |
+---------+-----------+
1 row in set (0.01 sec)
# node-3

mysql> SELECT * FROM percona.example;
+---------+-----------+
| node_id | node_name |
+---------+-----------+
|       1 | percona1  |
+---------+-----------+
1 row in set (0.00 sec)

はい、CREATE DATABASE, CREATE TABLE, INSERTを別々のノードで実施しましたが、データはすべて同期されていることがわかりますね。

ノードの安全な停止

ノードが突発的に故障した場合も気になりますが、普通にノードを落としたり再起動したい場合もありますよね。まずは安全に停止してみましょう。

といっても単にPerconaを停止すれば良いだけです。

# node-3

$ sudo systemctl stop mysql

他のノードでPerconaの状態を見てみます。

mysql> show status like 'wsrep%';
+----------------------------------+-------------------------------------------------+
| Variable_name                    | Value                                           |
+----------------------------------+-------------------------------------------------+
| wsrep_local_state_uuid           | e51d77cf-5b39-11ec-bfac-f61aad5f31eb            |
(...snip...)
| wsrep_local_state                | 4                                               |
| wsrep_local_state_comment        | Synced                                          |
(...snip...)
| wsrep_incoming_addresses         | 192.168.56.21:3306,192.168.56.22:3306           |
(...snip...)
| wsrep_gcomm_uuid                 | 1bb6f56e-5b3d-11ec-8ed5-cf11b78e64e2            |
(...snip...)
| wsrep_cluster_size               | 2                                               |
| wsrep_cluster_state_uuid         | e51d77cf-5b39-11ec-bfac-f61aad5f31eb            |
| wsrep_cluster_status             | Primary                                         |
| wsrep_connected                  | ON                                              |
(...snip...)
| wsrep_ready                      | ON                                              |
+----------------------------------+-------------------------------------------------+
75 rows in set (0.01 sec)

3台目のノードがいなくなってますね。この状態でデータを追加してみます。

# node-1

mysql> INSERT INTO percona.example VALUES (2, 'percona2');
Query OK, 1 row affected (0.02 sec)

# node-2

mysql> SELECT * FROM percona.example;
+---------+-----------+
| node_id | node_name |
+---------+-----------+
|       1 | percona1  |
|       2 | percona2  |
+---------+-----------+
2 rows in set (0.00 sec)

では3台目のPerconaを再度起動します。

# node-3

$ sudo systemctl start mysql

データベースを見てみましょう。

# node-3

mysql> SELECT * FROM percona.example;
+---------+-----------+
| node_id | node_name |
+---------+-----------+
|       1 | percona1  |
|       2 | percona2  |
+---------+-----------+
2 rows in set (0.00 sec)

はい、停止中に追加されたデータも、きちんと同期されてきていますね。

ノードの突発的な障害

ノードの突発的な障害も試してみましょう。3台目のノードがいきなり電源断して復旧不可、再構築が必要なケースを想定します。VirtualBoxから該当ノードを電源OFFしてVagrantで削除します。

f:id:kun432:20211212221807j:plain

$ vagrant destroy -f node-3

再度起動してインストールなどを行っていきます。

$ vagrant up node-3
$ vagrant ssh node-3
# node-3

$ sudo yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
$ sudo yum -y install Percona-XtraDB-Cluster-57
$ sudo vi /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
(...snip...)
wsrep_cluster_address=gcomm://192.168.56.21,192.168.56.22,192.168.56.23

(...snip...)

wsrep_node_address=192.168.56.23
wsrep_node_name=node-3.internal

(...snip...)

wsrep_sst_auth="sstuser:SSTのパスワード"

(...snip...)

準備ができたらMySQLを起動します。

$ sudo systemctl start mysql

では状態を見てみましょう。

# node-3

mysql> show status like 'wsrep%';
+----------------------------------+----------------------------------------------------------+
| Variable_name                    | Value                                                    |
+----------------------------------+----------------------------------------------------------+
| wsrep_local_state_uuid           | e51d77cf-5b39-11ec-bfac-f61aad5f31eb                     |
(...snip...)
| wsrep_local_state                | 4                                                        |
| wsrep_local_state_comment        | Synced                                                   |
(...snip...)
| wsrep_incoming_addresses         | 192.168.56.23:3306,192.168.56.21:3306,192.168.56.22:3306 |
(...snip...)
| wsrep_cluster_size               | 3                                                        |
| wsrep_cluster_state_uuid         | e51d77cf-5b39-11ec-bfac-f61aad5f31eb                     |
| wsrep_cluster_status             | Primary                                                  |
| wsrep_connected                  | ON                                                       |
(...snip...)
| wsrep_ready                      | ON                                                       |
+----------------------------------+----------------------------------------------------------+
75 rows in set (0.00 sec)

さらに通常のデータベースも見てみます。

# node-3

mysql> SELECT * FROM percona.example;
+---------+-----------+
| node_id | node_name |
+---------+-----------+
|       1 | percona1  |
|       2 | percona2  |
+---------+-----------+
2 rows in set (0.01 sec)

はい、こちらも問題ないですね。

そういえば、Perconaの起動の方法が1台目とそれ以外で違うのでした。1台目を停止する場合はどうなるのでしょうか?

# node-1

$ sudo systemctl status mysql@bootstrap
● mysql@bootstrap.service - Percona XtraDB Cluster with config /etc/sysconfig/mysql.bootstrap
   Loaded: loaded (/usr/lib/systemd/system/mysql@.service; disabled; vendor preset: disabled)
   Active: active (running) since 日 2021-12-12 20:17:45 JST; 2h 12min ago
(...snip...)

$ sudo systemctl status mysql
● mysql.service - Percona XtraDB Cluster
   Loaded: loaded (/usr/lib/systemd/system/mysql.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since 日 2021-12-12 20:09:30 JST; 2h 20min ago
(...snip...)

起動している方のサービスを停止します。

$ sudo systemctl stop mysql@bootstrap

起動するときは他のノードと同じように起動すればOKです。

$ sudo systemctl start mysql

mysql.serviceでは既存の存在するクラスタに参加するという動きになるため、そのクラスタを探しにいきますが、クラスタ内の1台目の場合にはクラスタを探す必要がないため、それを行わないmysql@bootstrap.serviceで起動する必要があるというわけですね。長く運用しているとここは間違えそうな気もしますね。。。

更にノードを追加

ノードの追加はとてもかんたんでしたが、そういえば最初にPerconaの設定ファイルにすべてのノードを記載していたのでした。

wsrep_cluster_address=gcomm://192.168.56.21,192.168.56.22,192.168.56.23

さらに別のIPを持った新たなノードを追加する場合はどうすればよいでしょうか?設定変更のためのプロセス再起動が必要な気がしますよね。

結論から言うと、プロセス再起動不要でノードは追加可能なようです。

serverfault.com

Perconaの設定ファイルにあるwsrep_cluster_addressはPerconaの再起動時に必要になるだけで、普通に追加ノードを構築・必要な設定を行ってPerconaを起動すれば、自動的にクラスタに参加します。 なのでノードを追加後に設定ファイルを修正だけしておけばよいみたいですね。

一応試してみましょう。

Vagrantfileでノードを追加して起動します。

(...snip...)
  (1..4).each do |n|
    config.vm.define "node-#{n}" do |c|
      c.vm.hostname = "node-#{n}.internal"
      c.vm.network "private_network", ip: "192.168.56.2#{n}"
(...snip...)
$ vagrant up

あとはノード障害時と同じようにノードにsshして構築していきます。

$ vagrant ssh node-4
# node-4

$ sudo yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
$ sudo yum -y install Percona-XtraDB-Cluster-57
$ sudo vi /etc/percona-xtradb-cluster.conf.d/wsrep.cnf
(...snip...)
wsrep_cluster_address=gcomm://192.168.56.21,192.168.56.22,192.168.56.23,192.168.56.24

(...snip...)

wsrep_node_address=192.168.56.24
wsrep_node_name=node-4.internal

(...snip...)

wsrep_sst_auth="sstuser:SSTのパスワード"

(...snip...)
$ sudo systemctl start mysql

Perconaの状態を見るとちゃんと追加されています。

mysql> show status like 'wsrep%';

(...snip...)
| wsrep_incoming_addresses         | 192.168.56.23:3306,192.168.56.22:3306,192.168.56.24:3306,192.168.56.21:3306 |
(...snip...)

データも同期されていますね。

mysql> SELECT * FROM percona.example;
+---------+-----------+
| node_id | node_name |
+---------+-----------+
|       1 | percona1  |
|       2 | percona2  |
+---------+-----------+
2 rows in set (0.01 sec)

Galera Arbitratorを使う

何度か書いている通り、クラスタには最低3台のノードが必要です。なぜかというとこのあたりが詳しいです。

通信断や故障時などが発生した場合、クラスタ全体のノード数の「過半数」とアクセスができるかどうかで、自ホストがクラスタとして正常かどうかを判断してます。これが2台の場合、1台死んだだけで過半数未満となるため、残りの1台は停止してアクセスできなくなります。2台でクラスタを組む意味はないということですね。

ただ、リソースには限界があります。物理サーバを3台用意できない場合もありえますよね。

Galera Arbitiratorはクラスタにおける疑似ノードとして動作します。これにより実際にデータベースが稼働しているホストが2台しかなくても、コストを抑えて、split brainの可能性を減らす事が可能になります。早速やってみましょう。

まずはノードが2台の状態をつくりましょう。node-3/4のPercona XtraDB Clusterを「安全」に停止して、クラスタから外します。

# node-3

$ sudo systemctl stop mysql

# node-4

$ sudo systemctl stop mysql

node-3/4は不要なのでVagrantで削除します。

$ vagrant destroy -f node-3 node-4

Vagrantfileを修正します。Perconaのホストを2台にして、Galera Arbitirator用のホストを1台追加しました。

(...snip...)
  (1..2).each do |n|                     # 数を2に変更
    config.vm.define "node-#{n}" do |c|
      c.vm.hostname = "node-#{n}.internal"
      c.vm.network "private_network", ip: "192.168.56.2#{n}"
      c.vm.provider "virtualbox" do |v|
        v.gui = false
        v.cpus = 1
        v.memory = 1024
      end
      c.vm.provision "shell", :path => "base-setup.sh"
    end
  end

  # ここから追加
  config.vm.define "garbd" do |c|
    c.vm.hostname = "garbd.internal"
    c.vm.network "private_network", ip: "192.168.56.31"
    c.vm.provider "virtualbox" do |v|
      v.gui = false
      v.cpus = 1
      v.memory = 1024
    end
    c.vm.provision "shell", :path => "base-setup.sh"
  end
  # ここまで
(...snip...)

Galera Arbitirator用ホストを起動してログインします。

$ vagrant up garbd
$ vagrant ssh garbd

Perconaのレポジトリを追加します。

$ sudo yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm

そしてGalera Arbitratorをインストールします。

$ sudo yum -y install Percona-XtraDB-Cluster-garbd-57

では設定を行います。Galera Arbitratorの設定ファイルは/etc/sysconfig/garbです。

$ sudo vi /etc/sysconfig/garb

設定箇所は以下。

# 以下の行は設定後に削除します。
# REMOVE THIS AFTER CONFIGURATION

# wsrep_cluster_addressと同じようにノードのIPを追加します。ポートは4567固定。
GALERA_NODES="192.168.56.21:4567, 192.168.56.22:4567, 192.168.56.31:4567"

# Perconaのクラスタ名を指定します。
# Perconaの設定箇所ではデフォルトのまま使ったので説明してませんでしたが、wsrep_cluster_nameで指定されているクラスタ名を指定します。
# Perconaのデフォルトだとpxc-clusterになっていると思います。
GALERA_GROUP="pxc-cluster"

ではGalera Arbitratorを起動します。

$ sudo systemctl start garb

$ sudo systemctl status garb.service
● garb.service - Galera Arbitrator Daemon
   Loaded: loaded (/usr/lib/systemd/system/garb.service; disabled; vendor preset: disabled)
   Active: active (running) since 月 2021-12-13 00:51:57 JST; 6s ago
(...snip...)

では、node-1かnode-2でPerconaの状態を見てみましょう。

mysql> show status like 'wsrep%';
+----------------------------------+----------------------------------------+
| Variable_name                    | Value                                  |
+----------------------------------+----------------------------------------+
| wsrep_local_state_uuid           | e51d77cf-5b39-11ec-bfac-f61aad5f31eb   |
(...snip...)
| wsrep_local_state                | 4                                      |
| wsrep_local_state_comment        | Synced                                 |
(...snip...)
| wsrep_incoming_addresses         | 192.168.56.22:3306,192.168.56.21:3306 |
(...snip...)
| wsrep_cluster_size               | 3                                      |
| wsrep_cluster_state_uuid         | e51d77cf-5b39-11ec-bfac-f61aad5f31eb   |
| wsrep_cluster_status             | Primary                                |
| wsrep_connected                  | ON                                     |
(...snip...)
| wsrep_ready                      | ON                                     |
+----------------------------------+----------------------------------------+
75 rows in set (0.00 sec)

クラスタのサイズは3になっていますが、待ち受けているノードは2台だけになっています。ちょっと面白いですね。

ではこの状態でnode-1を強制的に止めてみるとどうなるでしょうか?

mysql> show status like 'wsrep%';
+----------------------------------+------------------------------------------------+
| Variable_name                    | Value                                          |
+----------------------------------+------------------------------------------------+
(...snip...)
| wsrep_incoming_addresses         | 192.168.56.22:3306,                            |
(...snip...)
| wsrep_cluster_size               | 2                                              |
(...snip...)
| wsrep_cluster_status             | Primary                                        |
| wsrep_connected                  | ON                                             |
(...snip...)
| wsrep_ready                      | ON                                             |
+----------------------------------+------------------------------------------------+
75 rows in set (0.00 sec)

はい、実際にはDBは1台しかないですが、Galera Arbitratorが生きているために、クラスタ上は2台残ってると認識しててデータベースにもアクセスできますね。ただし、当然ながらGalera Arbitratorはあくまでも擬似的なノードでありデータを持っているわけではないので、そのあたりのリスクを認識した上で採用する必要はあります。

ちなみにこの状態からGalera Arbitratorをkill -KILLすると流石にクラスタは死にます。当然ながら過半数を割っているからですね。

mysql> show status like 'wsrep%';
(...snip...)
| wsrep_cluster_status             | non-Primary                          |
(...snip...)

mysql> SELECT * FROM percona.example;
ERROR 1047 (08S01): WSREP has not yet prepared node for application use

なのでユースケースとしては、

  • 3台のマルチクラスタはリソース的に厳しい。2台が限界。
  • garb自体はそれほどリソースを食わないため、Webサーバなどに同居させておくのがよい。

って感じですかね。

まとめ

やる前は複雑だなーと思ってたんですが、セットアップするだけならそれほどでもないですね。ただし、

  • 実際に起きうる障害パターンを踏まえた復旧
  • ノードのネットワーク的な配置の検討
  • マルチクラスタに対する負荷分散

あたりは実際に色々試しておく必要があるかなと思います。