Master Slave構成のMariaDBを構築しPacemakerで管理する

Master-Slave 構成の MariaDB を構築する手順について解説します。Master-Slave 構成の制御は Pacemaker を使い、自動的に Master-Slave を切り替えられる構成を目指します。

最近のバージョンの Pacemaker Version 2.1系は微妙にコマンドが異なっていたり、MasterがPromoteへ名前も変わっているので、最新の状況を反映してまとめました。

以下の設定の前提で行います。

  • OS: Ubuntu 22.04
  • VIP: 192.168.56.10
  • Host1: host1(192.168.56.21)
  • Host2: host2(192.168.56.21)
  • Replication User: repl
  • replication password: password
  • Test User: monitoring
  • Test Password: password

手順

  1. MariaDB のインストール
  2. MariaDBレプリケーション設定
  3. Pacemaker のインストール
  4. Pacemaker の設定
  5. テスト

MariaDB のインストール

MariaDB Server を2台のサーバにインストールします。

sudo apt install -y mariadb-server

MariaDBの設定

MariaDB の設定ファイルを編集し、レプリケーションの設定を行います。

sudo vi /etc/mysql/mariadb.conf.d/50-server.cnf

50-server.cnf に以下の設定を行います。レプリケーションをするための設定です。 server-id の行はコメントアウトして、2台のサーバにそれぞれ異なる値を設定します。 また、bind-address は、使用するネットワーク環境に合わせ、外部から接続を受けられるネットワークのIPアドレスに変更してください。 以下の設定例は、すべてのネットワークアドレスから接続を受け付ける設定です。

bind-address: 0.0.0.0

# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
#       other settings you may need to change.
server-id              = 1   # この行をコメントアウトし、server idを設定
log_bin                = /var/log/mysql/mysql-bin.log # この行をコメントアウト
expire_logs_days        = 10
max_binlog_size        = 100M

Replication ユーザ/監視ユーザの作成

host1で作業します。mysql コマンドを使い root ユーザでログインして、ユーザを作成します。

replication userの作成。ユーザ名は、"repl@%"、パスワードは、"password"としています。注意として、本番では、このパスワードは破られやすいので使わないほうが良いでしょう。

CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repl'@'%';
CREATE USER 'repl'@'localhost' IDENTIFIED BY 'password';
GRANT SUPER, PROCESS, RELOAD ON *.* TO 'repl'@'localhost';
GRANT SELECT ON performance_schema.* TO 'repl'@'%';

monitoring user の作成。ユーザ名は、"monitoring@%"、パスワードは、"password"としています。

CREATE USER 'monitoring'@'%' IDENTIFIED BY 'password';
GRANT select ON mysql.user TO 'monitoring'@'%';

ユーザ作成後、mysql はブート時に自動起動しないようにし、停止させます。

sudo systemctl disable mariadb
sudo systemctl stop mariadb

データをコピー

レプリケーションをするので、host1 の MariaDB のデータを host2 にコピーします。このとき必ず、MariaDB を停止させた状態で行います。 先ほど作成したユーザも一緒にコピーされます。

sudo tar cfc mysql.tar /var/lib/mysql 

作成された mysql.tar を host2 に持っていき、展開します。展開するときは以下のようにして行います。 mariadb を停止した状態で行います。

cd /
sudo tar xvf mysql.tar 

host2も、MariaDB の設定ファイルの変更と、サービス再起動の無効化設定を忘れないようにしてください。

Pacemaker のインストール

クラスタの管理を行う Pacemaker のインストールを行います。

sudo apt install -y pacemaker pcs haveged resource-agents fence-agents

Corosync の設定

Pacemaker は、内部的に Corosync という管理システムを使っています。その設定を行います。

Corosync の Key を作成

sudo corosync-keygen -l

生成したキーを別ホストにコピー

/etc/corosync/authkey を、もう一台の別ホストの同じディレクトリ、ファイル名でコピーします。

/etc/corosync/corosync.conf の設定

Corosync の設定を行います。Corosync はデフォルトでマルチキャストを使い他のサーバと通信しますが、今回の設定はマルチキャスが使えない環境で使用するため、ユニキャストで使用する場合の設定例となります。

この設定は、2台のホストで同じです。

設定のポイント

  • host1/host2に同じ設定を行う
  • totem-transportにudpuを指定する
  • totem-interface-bindnetaddr に接続するネットワークインターフェイスアドレスに設定
  • nodelist-node の設定を、各ホスト向けに設定
# Please read the corosync.conf.5 manual page
totem {
    version: 2

    # Corosync itself works without a cluster name, but DLM needs one.
    # The cluster name is also written into the VG metadata of newly
    # created shared LVM volume groups, if lvmlockd uses DLM locking.
    # It is also used for computing mcastaddr, unless overridden below.
    cluster_name: ubuntu

    # How long before declaring a token lost (ms)
    token: 3000

    # How many token retransmits before forming a new configuration
    token_retransmits_before_loss_const: 10

    # Limit generated nodeids to 31-bits (positive signed integers)
    clear_node_high_bit: yes

    # crypto_cipher and crypto_hash: Used for mutual node authentication.
    # If you choose to enable this, then do remember to create a shared
    # secret with "corosync-keygen".
    # enabling crypto_cipher, requires also enabling of crypto_hash.
    # crypto_cipher and crypto_hash should be used instead of deprecated
    # secauth parameter.

    # Valid values for crypto_cipher are none (no encryption), aes256, aes192,
    # aes128 and  3des. Enabling crypto_cipher, requires also enabling of
    # crypto_hash.
    crypto_cipher: none

    # Valid values for crypto_hash are  none  (no  authentication),  md5,  sha1,
    # sha256, sha384 and sha512.
    crypto_hash: none

    # Optionally assign a fixed node id (integer)
    # nodeid: 1234

    transport:udpu

    # interface: define at least one interface to communicate
    # over. If you define more than one interface stanza, you must
    # also set rrp_mode.
    interface {
        # Rings must be consecutively numbered, starting at 0.
        ringnumber: 0
        # This is normally the *network* address of the
        # interface to bind to. This ensures that you can use
        # identical instances of this configuration file
        # across all your cluster nodes, without having to
        # modify this option.
        bindnetaddr: 192.168.56.0
                
        # Corosync uses the port you specify here for UDP
        # messaging, and also the immediately preceding
        # port. Thus if you set this to 5405, Corosync sends
        # messages over UDP ports 5405 and 5404.
        mcastport: 5405

        # Time-to-live for cluster communication packets. The
        # number of hops (routers) that this ring will allow
        # itself to pass. Note that multicast routing must be
        # specifically enabled on most network routers.
        ttl: 1
    }
}

nodelist {
         node {
                name: host1
                ring0_addr: 192.168.56.21
                nodeid: 1
         }
         node {
                name: host2
                ring0_addr: 192.168.56.22
                nodeid: 2
         }
}

logging {
    # Log the source file and line where messages are being
    # generated. When in doubt, leave off. Potentially useful for
    # debugging.
    fileline: off
    # Log to standard error. When in doubt, set to no. Useful when
    # running in the foreground (when invoking "corosync -f")
    to_stderr: no
    # Log to a log file. When set to "no", the "logfile" option
    # must not be set.
    to_logfile: no
    #logfile: /var/log/corosync/corosync.log
    # Log to the system log daemon. When in doubt, set to yes.
    to_syslog: yes
    # Log with syslog facility daemon.
    syslog_facility: daemon
    # Log debug messages (very verbose). When in doubt, leave off.
    debug: off
    # Log messages with time stamps. When in doubt, set to on
    # (unless you are only logging to syslog, where double
    # timestamps can be annoying).
    timestamp: on
    logger_subsys {
        subsys: QUORUM
        debug: off
    }
}

quorum {
    # Enable and configure quorum subsystem (default: off)
    # see also corosync.conf.5 and votequorum.5
    provider: corosync_votequorum
    expected_votes: 2
}

設定後、corosyncを再起動します。

sudo systemctl restart corosync

Pacemakerの設定

クラスタ管理設定を行います。

Pacemaker初期化

事前に、haclusterユーザのパスワードを、host1/host2それぞれ設定しておきます。

sudo passwd hacluster

パスワードを設定したら、以降、host1のみで操作を行います。

sudo pcs cluster auth -u hacluster -p <password>

ここまで設定すると、pacemakerの状態は以下のようになります。

vagrant@host1:~$ sudo pcs status
Cluster name: ubuntu

WARNINGS:
No stonith devices and stonith-enabled is not false

Cluster Summary:
  * Stack: corosync
  * Current DC: host2 (version 2.1.2-ada5c3b36e2) - partition with quorum
  * Last updated: Fri Jun 16 01:35:51 2023
  * Last change:  Fri Jun 16 01:32:29 2023 by hacluster via crmd on host2
  * 2 nodes configured
  * 0 resource instances configured

Node List:
  * Online: [ host1 host2 ]

Full List of Resources:
  * No resources

Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

基本設定

以降、Pacemaker 関係の設定は host1 のみで行います。

sudo pcs property set stonith-enabled=false
sudo pcs property set no-quorum-policy=ignore

自動フェイルバックなし

sudo pcs resource defaults update resource-stickiness="INFINITY" migration-threshold="1"

クラスタリソース設定

IP Resource

準備

sudo pcs node standby host2
sudo pcs cluster cib mysql_repl

IPResource作成

sudo pcs -f mysql_repl resource create ClusterIP IPaddr2 \
   ip="192.168.56.10" \
   cidr_netmask="24" \
   op start   timeout="60s" interval="0s"  on-fail="restart" \
   op monitor timeout="60s" interval="10s" on-fail="restart" \
   op stop    timeout="60s" interval="0s"  on-fail="block"
MySQL Resource

MySQL Resourceの作成を行います。 replication_passwd/test_passwdの設定は、replicationユーザ/monitoringのパスワードに変更すること

sudo pcs -f mysql_repl resource create mysql ocf:heartbeat:mysql
sudo pcs -f mysql_repl resource update mysql binary=/usr/bin/mysqld_safe
sudo pcs -f mysql_repl resource update mysql datadir=/var/lib/mysql
sudo pcs -f mysql_repl resource update mysql log=/var/log/mysql/error.log
sudo pcs -f mysql_repl resource update mysql pid=/var/run/mysqld/mysqld.pid
sudo pcs -f mysql_repl resource update mysql socket=/var/run/mysqld/mysqld.sock
sudo pcs -f mysql_repl resource update mysql replication_user=repl
sudo pcs -f mysql_repl resource update mysql replication_passwd=password
sudo pcs -f mysql_repl resource update mysql test_user=monitoring
sudo pcs -f mysql_repl resource update mysql test_passwd=password
sudo pcs -f mysql_repl resource update mysql evict_outdated_slaves=false
sudo pcs -f mysql_repl resource update mysql max_slave_lag=60
sudo pcs -f mysql_repl resource update mysql op start interval=0 timeout=120s
sudo pcs -f mysql_repl resource update mysql op stop interval=0 timeout=120s
sudo pcs -f mysql_repl resource update mysql op monitor interval=20s timeout=30s
sudo pcs -f mysql_repl resource update mysql op monitor interval=5s role=Master OCF_CHECK_LEVEL="1"
sudo pcs -f mysql_repl resource update mysql op monitor interval=2s role=Slave OCF_CHECK_LEVEL="1"
sudo pcs -f mysql_repl resource update mysql op promote interval=0 timeout=60s
sudo pcs -f mysql_repl resource update mysql op demote interval=0 timeout=60s
sudo pcs -f mysql_repl resource update mysql op notify interval=0 timeout=60s

Master-Slave セットを作成し、クラスターリソースを有効にします

sudo pcs -f mysql_repl resource promotable mysql mysql-clone master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true globally-unique="false" target-role="Master" is-managed="true"
sudo pcs -f mysql_repl resource enable mysql-clone
制約の設定

IPアドレスと、MySQL の master は同じホストになるように制約を設定します。

sudo pcs -f mysql_repl constraint colocation add ClusterIP with Master mysql-clone INFINITY
sudo pcs -f mysql_repl constraint order promote mysql-clone then start ClusterIP symmetrical=false score=INFINITY
sudo pcs -f mysql_repl constraint order demote  mysql-clone then stop  ClusterIP symmetrical=false score=0
設定反映
sudo pcs cluster cib-push mysql_repl

host2をunstandby

sudo pcs node unstandby host2
状態表示

host1/host2がOnlineで、host1がPromoted, host2がUnpromotedになります。

vagrant@host1:~$ sudo pcs status
Cluster name: ubuntu
Cluster Summary:
  * Stack: corosync
  * Current DC: host1 (version 2.1.2-ada5c3b36e2) - partition with quorum
  * Last updated: Thu Jun  8 00:23:01 2023
  * Last change:  Thu Jun  8 00:17:20 2023 by root via cibadmin on host1
  * 2 nodes configured
  * 3 resource instances configured

Node List:
  * Online: [ host1 host2 ]

Full List of Resources:
  * ClusterIP   (ocf:heartbeat:IPaddr2):     Started host1
  * Clone Set: mysql-clone [mysql] (promotable):
    * Promoted: [ host1 ]
    * Unpromoted: [ host2 ]

Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

テスト

Host1 を standby にしてみます。

sudo pcs node standby host1

しばらく待つ(1,2分)と、host2にPrimaryが切り替わります。pcsの状態表示では、host2がPromotedになり、host1がStoppedになります。

vagrant@host1:~$ sudo pcs status
Cluster name: ubuntu
Cluster Summary:
  * Stack: corosync
  * Current DC: host2 (version 2.1.2-ada5c3b36e2) - partition with quorum
  * Last updated: Fri Jun 16 01:47:18 2023
  * Last change:  Fri Jun 16 01:47:03 2023 by root via crm_attribute on host2
  * 2 nodes configured
  * 3 resource instances configured

Node List:
  * Node host1: standby
  * Online: [ host2 ]

Full List of Resources:
  * ClusterIP   (ocf:heartbeat:IPaddr2):     Started host2
  * Clone Set: mysql-clone [mysql] (promotable):
    * Promoted: [ host2 ]
    * Stopped: [ host1 ]

Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

Master/Slaveの手動切り替え

host1をstandbyにするには、以下のコマンドを実行します。

sudo pcs node standby host1

しばらく(1、2分)すると、Master/Slaveが切り替わります。 host1はstopped状態になりますが、これは正常です。復活させるには、以下のコマンドを実行します。

sudo pcs node unstandby host1

こうすると、host1のMySQLが起動し、Slaveになります。

テスト書き込みスクリプト

切り替えテストでは、以下のスクリプト実行して書き込み状況を関すると分かりやすいです。

#!/bin/bash
#
MYSQLCRED='-u writeuser -pwrites -h 192.168.56.10'

mysql $MYSQLCRED -e "create database if not exists test;"
mysql $MYSQLCRED -e "create table if not exists writeload (id int not null auto_increment,data char(10), primary key (id)) engine = innodb;" test

while [ 1 ]
do
   mysql $MYSQLCRED -e "insert into writeload values (data) values ('test');" test
   sleep 1
done

参考