EC2(amazon linux 2023)でのGalera Cluster利用

この記事は、ケーシーエスキャロット [Advent Calendar 2023](https://qiita.com/advent-calendar/2023/kcscarrot)の24日目の記事です。:champagne:

# 最初に

業務にてGalera ClusterによるDB同期に携わる機会があり、
簡単に実験できる環境をと思い、環境構築してみる事にしました。
※ その際の手順を備忘録としてまとめました。

# MariaDB Galera Clusterとは

MariaDBを同期する為のマルチマスタークラスターです。
Linuxのみで利用可能で、XtraDB/InnoDbエンジンでサポートされています。

簡単に言えば、
複数のMariaDBサーバーをマルチマスターモードで情報を同期してくれる優れものです。

詳しくは以下公式サイト参照ください。

https://mariadb.com/kb/en/galera-cluster/

# AWS構築環境

今回、「Amazon Linux 2023」でEC2インスタンスを2つ用意して、
それぞれにMariaDB/Galeraをインストール後、同期処理を試してみました。

![AWS-Galera.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528499/7c6c5ae0-2e4b-834e-67d2-cba793c0b44b.png)


# MariaDB/Galeraインストール

MariaDB/Galeraのインストール手順です。

instance1/instance2共に同じ手順になります。

## OS確認

OSは以下になります。

```
% cat /etc/os-release 
NAME="Amazon Linux"
VERSION="2023"
ID="amzn"
ID_LIKE="fedora"
VERSION_ID="2023"
PLATFORM_ID="platform:al2023"
PRETTY_NAME="Amazon Linux 2023"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2023"
HOME_URL="https://aws.amazon.com/linux/"
BUG_REPORT_URL="https://github.com/amazonlinux/amazon-linux-2023"
SUPPORT_END="2028-03-15"
```
## セキュリティグループ

instance1/instance2で共通のセキュリティグループを利用し、
インバウンドにて、
両方のプライベートIPで以下のポートでのアクセス許可を追加しておきます。

| ポート | 内容 |
|:-----------|:-----------|
| 3306 | MySQL クライアント接続およびバックアップに使用 |
| 4567 | Galera Cluster Replicationトラフィック |
| 4568 | IST : Incremental State Transfer |
| 4444 | SST : State Snapshot Transfer |

## MariaDBインストール

dnfにてインストールする為、.repoファイルを準備。

/etc/yum.repos.d/mariadb.repoを作成し、
以下内容を記載。

```
[mariadb]
name = MariaDB
baseurl = https://rpm.mariadb.org/10.5/rhel/9/$basearch
gpgkey = https://rpm.mariadb.org/RPM-GPG-KEY-MariaDB
enabled=1
gpgcheck = 1
```

dnfにてインストール

```
dnf install MariaDB galera-4
```

これでMWのインストールは完了です。

# Galera設定

GaleraでのDB同期を実現する為、mariadbの設定ファイル(/etc/my.cnf.d/server.cnf)にて、
設定値を追記します。

仮にinstance1のPrivateIPを11.11.11.11、
instance2のPrivateIPを22.22.22.22とします。

## instance1

```
[galera]
wsrep_on=ON
wsrep_provider=/usr/lib64/galera-4/libgalera_smm.so
wsrep_cluster_name="galera_cluster"
wsrep_cluster_address = 'gcomm://11.11.11.11,22.22.22.22'
wsrep_node_name='db1'
wsrep_node_address='11.11.11.11'
wsrep_sst_method=rsync
wsrep_sst_donor_rejects_queries=ON
wsrep_slave_threads=1
innodb_autoinc_lock_mode=2
# auto incrementの排他制御を停止する場合はOFF
#wsrep_auto_increment_control='ON'
wsrep_auto_increment_control='OFF'
wsrep_drupal_282555_workaround='ON'
wsrep_retry_autocommit=10
auto_increment_increment=1
binlog_format=ROW
```

## instance2

```
[galera]
wsrep_on=ON
wsrep_provider=/usr/lib64/galera-4/libgalera_smm.so
wsrep_cluster_name="galera_cluster"
wsrep_cluster_address = 'gcomm://11.11.11.11,22.22.22.22'
wsrep_node_name='db2'
wsrep_node_address='22.22.22.22'
wsrep_sst_method=rsync
wsrep_sst_donor_rejects_queries=ON
wsrep_slave_threads=1
innodb_autoinc_lock_mode=2
# auto incrementの排他制御を停止する場合はOFF
#wsrep_auto_increment_control='ON'
wsrep_auto_increment_control='OFF'
wsrep_drupal_282555_workaround='ON'
wsrep_retry_autocommit=10
auto_increment_increment=1
binlog_format=ROW
```
## 設定値の簡単な説明

| 設定項目 | 内容 |
|:-----------|:-----------|
| wsrep_on | wsrepレプリケーションの有効/無効 |
| wsrep_provider | wsrepライブラリのパス |
| wsrep_cluster_name | クラスター名称 |
| wsrep_cluster_address | クラスターノードのアドレス |
| wsrep_node_name | ノード名称 |
| wsrep_node_address | 自分自身のノードのアドレス |
| wsrep_sst_method | SST(State Snapshot Transfer)の実行方法 |
| wsrep_sst_donor_rejects_queries | mysqldump/rsync等の状態スナップショット転送(SST)でドナーとして機能している際、ノード上のブロッキングセッションを拒否するかどうかを定義 |
| wsrep_slave_threads | 同期実行に利用されるスレッド数 |
| innodb_autoinc_lock_mode | 自動増分のロックモード |
| wsrep_auto_increment_control | auto_incrementの排他制御有効/無効 |
| wsrep_drupal_282555_workaround | バグ( https://www.drupal.org/node/282555 )回避オプション |
| wsrep_retry_autocommit | クラスター全体の競合によって、エラーが発生した際に、コミットをリトライする回数 |
| auto_increment_increment | 指定した数値分だけAUTO_INCREMENTが増加 |
| binlog_format | バイナリログ形式 |

# MariaDB起動

## instance1

初回(1台も起動していない状態)で、1台目として起動する場合は、以下コマンドでmariadbを起動する。

```
% galera_new_cluster
```

mysqlでログインして、クラスター内のノード数を確認する。

```
% mysql -h localhost -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 10.5.23-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

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

MariaDB [(none)]> show status like 'wsrep_cluster_size';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| wsrep_cluster_size | 1     |
+--------------------+-------+
1 row in set (0.001 sec)
```

まずは1台になっています。

* 補足
すでにinstance1/instance2で同期されている状態で、
両方のmariadbを停止し、
再度同期する為にmariadbを再起動する場合は、
/var/lib/mysql/grastate.datに記載されている「safe_to_bootstrap」が1の方で、
galera_new_clusterを実行する。

## instance2

2台名以降は、単純にsystemctlで起動

```
% systemctl start mariadb.service
```

mysqlでログインして、クラスター内のノード数を確認する

```
mysql -h localhost -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 10.5.23-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

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

MariaDB [(none)]> show status like 'wsrep_cluster_size';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| wsrep_cluster_size | 2     |
+--------------------+-------+
1 row in set (0.001 sec)
```
2台になりました。

以上でinstance1/instance2で起動したmariadbがgaleraにより同期されました。 

# レコード同期確認

## instance1

DB/Table/Recordを作成

```
MariaDB [(none)]> create database galera_test;
Query OK, 1 row affected (0.004 sec

MariaDB [(none)]> use galera_test;
Database changed

MariaDB [galera_test]> create table address (id int, address varchar(10));
Query OK, 0 rows affected (0.011 sec)

MariaDB [galera_test]> insert into address value (1, 'tokyo');
Query OK, 1 row affected (0.002 sec)

MariaDB [galera_test]> insert into address value (2, 'hiroshima');
Query OK, 1 row affected (0.003 sec)

MariaDB [galera_test]> select * from address;
+------+-----------+
| id   | address   |
+------+-----------+
|    1 | tokyo     |
|    2 | hiroshima |
+------+-----------+
2 rows in set (0.000 sec)
```

## instance2

```
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| galera_test        |
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.001 sec)

MariaDB [(none)]> use galera_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [galera_test]> show tables;
+-----------------------+
| Tables_in_galera_test |
+-----------------------+
| address               |
+-----------------------+
1 row in set (0.000 sec)
MariaDB [galera_test]> select * from address;
+------+-----------+
| id   | address   |
+------+-----------+
|    1 | tokyo     |
|    2 | hiroshima |
+------+-----------+
2 rows in set (0.000 sec)
```

DB/Table/Recordが同期されている事が確認出来ました。

他にもっと良い案あるかもしれませんが、とりあえず実験環境完了という事で。