LoginSignup
32
36

More than 1 year has passed since last update.

MySQL8.0のインストールと初期セットアップ

Last updated at Posted at 2019-01-24

CentOS7上でMySQL8.0のセットアップを行ってみた。色々と問題が発生したが、ナウでホットな話題のせいか、トラブルシュートが分散してたのでここでまとめてみる。

前提条件

検証環境

  • CentOS: 7.7.1908/x86_647.6.1810
  • SELinux: enforcingモードで運用1
  • MySQL:  8.0.188.0.198.0.228.0.148.0.17

メモ

  • ※ここで紹介するMySQL8.0のインストール手順(環境)は8.0.X(Xはパッチバージョン)を追いかけるものであるため、本記述とは違う(新しい)バージョンになっている場合がある。
  • ここに書いてある基本的な部分について、改訂は無いと思われるが、バージョンが違う場合はリリースノートを注意深く確認すること。
  • バージョンアップにともなう細かいオペレーション(手動更新作業)についてはここでは記載しない。あくまで新規セットアップのみ記述する。
  • またCentOS7のインストールについては、既に基本的な設定2がなされているものとする。
  • 久々にセットアップ(8.0.19)したら、グループレプリケーションの設定ルールが変更になったので、手順を変更する。
  • この手順が旧バージョンでも有効かは未確認。
  • また、SELinuxの振る舞いが7.6と7.7で若干違うこともあり、有効化は未確認。

構築目標

  • 「一台」以上のグループレプリケーションを構成する。
  • デフォルトの認証プラグインはmysql_native_passwordとするが、それ以外では可能な限り新しい認証プラグイン(caching_sha2_password)を使用する。
  • 直後にサービス提供可能なよう、文字コードとタイムゾーンを設定しておく。
  • SELinuxが有効(エンフォースモード)な環境でも稼働させることを目指す。
  • ただし上記検証リストのうち、古い環境では動かなかったケースがある。最新の環境では上手くいったので有効を前提に記述する。

想定ネットワーク構成

サーバーは下記のようなネットワーク内に設置されているものとする

192.168.100.0/24
--------+---------------------------+--------------------
        |                           |
    eth0| 192.168.100.11        eth0| 192.168.100.12
+-------+--------+          +-------+--------+
| gr1.example.jp |          | gr2.example.jp |  ・・・
+-------+--------+          +-------+--------+
    eth1| 192.168.200.11        eth1| 192.168.200.12
        |                           |
--------+---------------------------+--------------------
192.168.200.0/24
  • 自環境で使用する場合は、上記構成を参考に読み替えたし。
  • ファイアウォールのゾーン分け(説明がめんどくさいので)をしないので、各インターフェース毎に振る舞いは変わらないモノとする。

インストール

MySQL YUMリポジトリのセットアップ

sudo yum install https://repo.mysql.com/yum/mysql-8.0-community/el/7/x86_64/mysql80-community-release-el7-3.noarch.rpm

デフォルトでmysql80-communityリポジトリが有効になっているので、今回はそのまま利用する。

MySQL互換ライブラリのアップデート

sudo yum -y update

この時、OS標準で提供される mariadb-libs-5.5.60-1(ないしはmariadb-libs-5.5.64-1)がmysql-community-libs-compat-8.0.X-1はパッチバージョン)に置き換わる。

MySQL8.0サーバーのインストール

sudo yum -y install mysql-community-server

この時クライアントツール(mysqlmysqladmin等)もインストールされる。

SELinuxとファイアウォールの一時無効化

SELinuxとファイアウォールの稼働に考慮した設定を行っているため enforcing モードでのセットアップは可能である。
セットアップに自信が無い場合は、一時的に無効化しておく。セットアップに慣れて、これらが有効な状態でも、問題無くできることを確認してから、有効にすること。

sudo setenforce 0
sudo systemctl stop firewalld
  • SELinuxの無効化はdisabled(再起動が必要)かpermissive(オンザフライで変更可能)となるが、いつでも有効・無効化ができるようpermissiveにしておく。
  • 自分はSELinuxの有効利用を推奨いたします(ポリコレ棍棒)。
  • SELinuxの永続的な変更については/etc/selinux/configファイルのSELINUX=行の設定を変更すること。

初期設定

/etc/hosts

自ホストのエイリアスのみethnを加えるものとする。

下記のようなホスト構成がなされているものとする。
またこれを設定せず、全てIPアドレスで指定することは問題ない。
その場合、都度置き換えて解釈すること。

一台目

192.168.200.11    gr1.example.jp  eth1
192.168.100.11    gr1.example.jp  eth0
192.168.200.12    gr2.example.jp
192.168.100.12    gr2.example.jp
192.168.200.13    gr3.example.jp
192.168.100.13    gr3.example.jp

二台目

192.168.200.11    gr1.example.jp
192.168.100.11    gr1.example.jp
192.168.200.12    gr2.example.jp  eth1
192.168.100.12    gr2.example.jp  eth0
192.168.200.13    gr3.example.jp
192.168.100.13    gr3.example.jp

/etc/my.cnf

設定は基本/etc/my.cnfで設定するのでなく、/etc/my.cnf.d/ディレクトリ以下に置いた.cnfファイルを作成することで対応するものとする。

--- /etc/my.cnf.orig    2018-10-07 09:24:13.000000000 +0000
+++ /etc/my.cnf 2018-12-27 07:44:08.831076978 +0000
@@ -29,3 +29,5 @@

 log-error=/var/log/mysqld.log
 pid-file=/var/run/mysqld/mysqld.pid
+
+!includedir /etc/my.cnf.d

/etc/my.cnf.d/authentication.cnf

[mysqld]
default-authentication-plugin   = mysql_native_password
default-password-lifetime       = 0

authentication.cnf についての設定メモ

  • 悪名高いdefault-password-lifetime=360問題を意識するため、明示的に0に設定する。
  • ここで、バリデートパスワード機能の設定を行いたいところであるが、直近の変更(8.0.4以降)により、プラグインからコンポーネントに再実装された関係で、設定ファイルでは設定できなくなったため、ここでは設定しない(重要なので二回言った)。

/etc/my.cnf.d/charset.cnf

[mysqld]
character-set-server            = utf8mb4
collation-server                = utf8mb4_bin

[client]
loose-default-character-set     = utf8mb4

charset.cnf についての設定メモ

  • 8.0.1にて、デフォルト文字コードがutf8mb4になったとのことだが、各々の環境でどうしているかはこういう形で明示すべきと考えている。
  • またコレーション(照合順序)も重要な要素であるため、データベース運用前に何を選択すべきか、よく話し合った上で明示すること。
  • コレーション設定が utf8mb4_bin とあるのは、照合順序を無秩序(文字コードそのもので判定)とするためで、特にソート順がめちゃくちゃになる点に注意。
  • クライアント(client)の中には default-character-set が設定されているとエラーになるケースがあるので、loose- プレフィックスを付与して、そのようなクライアントでも問題無いよう保護(オプションを無視させる)する。

/etc/my.cnf.d/max-connections.cnf

[mysqld]
open-files-limit                = 65536
max-connections                 = 10000
table-open-cache                = 2000

max-connections.cnf についての設定メモ

  • データベースのリソース不足によくある一つに「ファイルディスクリプタ数」がある。
  • Linux(大抵のOSはそうだが)自体は極めて大量のソケットやファイルを開くことができるが、デフォルトでかなり控えめ(4096)に制限されている。
  • この制限の解放方法については後述するが、少メモリ環境でも「開けるだけなら」1万ファイルをオープンすることは余裕なので、ここではそこそこの値を設定してみる。
  • より大規模な環境ではメモリ搭載量と合わせて大きく設定することになる(100万オーダーとか)。
  • なお後述する/etc/systemd/system/mysqld.service.d/override.confの設定を合わせて実施しておくこと。

/etc/my.cnf.d/mysqlx.cnf

[mysqld]
mysqlx                          = OFF

Xプラグイン機能を使用する(デフォルト)と、専用にポート(33060/TCP)を開くので、使用しない場合は無効にしておくことをお勧めする。

※この設定を行わないと、SELinux(の設定)により、MySQLサーバーが立ち上がらない現象が発生する。SELinux有効化の時に、上記ポート番号の設定を実施する(こちらも後述)。

/etc/sysconfig/mysql

久々にMySQLサーバーをセットアップしていて、8.0.22でこの設定が機能していないとことを確認した。
起動時オプションの指定で無効化できたのを確認したので、上記設定の代わりに指定するのもありかもしれない。マニュアル読み直しても、設定ファイル中で指定可能に見えるので、バグかも知れない。
取り急ぎのワークアラウンドというやつで。

MYSQLD_OPTS="--skip-mysqlx"

愚痴

一応 enforcing モードでセットアップしてたのだけど、SELinux的には監査に引っかからずに無事起動。
ログを精査している時に気がついた。semanage port -l | grep mysqld_port_t 的(後述)にはひっかかるはずなんだが…。
まったく、SELinuxは魔窟だぜ!!

/etc/my.cnf.d/network.cnf

[mysqld]
bind-address                    = eth1
port                            = 3306

ここで言うeth1は /etc/hosts で設定したものとなる。

/etc/my.cnf.d/replication.cnf

[mysqld]
server-id                               = サーバーID
gtid-mode                               = ON
enforce-gtid-consistency                = ON
binlog-checksum                         = NONE
relay-log                               = mysql-relay-bin
loose-group-replication-group-name              = "グループレプリケーションUUID"
loose-group-replication-single-primary-mode     = ON
loose-group-replication-recovery-use-ssl        = ON
loose-group-replication-recovery-public-key-path = /etc/my.cnf.d/server_public_keys.pem
loose-group-replication-start-on-boot           = OFF                           #NOTE: Operating change by SET PERSIST :NOTE#
loose-group-replication-bootstrap-group         = OFF                           #NOTE: Operating change by SET PERSIST :NOTE#
loose-group-replication-local-address           = "自身のホスト名またはIP:33061"
loose-group-replication-group-seeds             = "1台目のホスト名またはIP:33061,2台目以降のホスト名またはIP:33061,..."

※MySQLサーバー立ち上げ前にグループレプリケーションプラグインのインストールが不可能なため、loose- プレフィックスを付けて後々有効化させる。

replication.cnf についての設定メモ

  • 「サーバーID」はレプリケーションするサーバー間でユニークとなるよう数字を割り振る。
  • 本例ではサーバー名を、gr1gr2、…と振ってることもあり12、…と設定しまうのが楽と思われ。
  • 「グループレプリケーションUUID」はグループレプリケーションを構成する1つの集合に対する名前(UUID)である。
  • よって、同一グループレプリケーションに所属する全てのサーバーで同じUUIDを指定(共有)する。
  • またUUIDはuuidgenコマンド3を使用してテキトーに決める。
  • 「自身のホスト名またはIP」という表現であるが、どうも個々で指定したホスト名(IP)が重複してないかチェックしているようでeth1を指定して共通化することができなかった。 orz
  • よってここでは丁寧にgr1.example.jp:33061のような形で指定する。
  • 「1台目の~」「2台目の~」はグループレプリケーションを運用している主要なサーバーを指定しするもので、全てのサーバーを指定しなくてよい。
  • 例えば初期に2台セットアップして、後日もう1台追加、という時でも、2台のまま設定変更しなくてもよい。
  • その代わりここで指定されたサーバーが「全台」落ちることがないように注意すること。全台落ちた場合の復旧は手動で回復することになる。

一台目のMySQLサーバーのreplication.cnfの設定例

[mysqld]
server-id                               = 1
gtid-mode                               = ON
enforce-gtid-consistency                = ON
binlog-checksum                         = NONE
relay-log                               = mysql-relay-bin
loose-group-replication-group-name              = "4ea57fa3-76a1-4a4e-b119-759459629287"
loose-group-replication-single-primary-mode     = ON
loose-group-replication-recovery-use-ssl        = ON
loose-group-replication-recovery-public-key-path = /etc/my.cnf.d/server_public_keys.pem
loose-group-replication-start-on-boot           = OFF                           #NOTE: Operating change by SET PERSIST :NOTE#
loose-group-replication-bootstrap-group         = OFF                           #NOTE: Operating change by SET PERSIST :NOTE#
loose-group-replication-local-address           = "gr1.example.jp:33061"
loose-group-replication-group-seeds             = "gr2.example.jp:33061,gr3.example.jp:33061"

二台目のMySQLサーバーのreplication.cnfの設定例

[mysqld]
server-id                               = 2
gtid-mode                               = ON
enforce-gtid-consistency                = ON
binlog-checksum                         = NONE
relay-log                               = mysql-relay-bin
loose-group-replication-group-name              = "4ea57fa3-76a1-4a4e-b119-759459629287"
loose-group-replication-single-primary-mode     = ON
loose-group-replication-recovery-use-ssl        = ON
loose-group-replication-recovery-public-key-path = /etc/my.cnf.d/server_public_keys.pem
loose-group-replication-start-on-boot           = OFF                           #NOTE: Operating change by SET PERSIST :NOTE#
loose-group-replication-bootstrap-group         = OFF                           #NOTE: Operating change by SET PERSIST :NOTE#
loose-group-replication-local-address           = "gr2.example.jp:33061"
loose-group-replication-group-seeds             = "gr1.example.jp:33061,gr3.example.jp:33061"

/etc/my.cnf.d/storage.cnf

[mysqld]
default-storage-engine          = InnoDB
innodb-dedicated-server         = TRUE

ここではInnoDB関連のパラメータについては議論しない。

innodb-log-file-in-group        = 2

が、一点。極めて特異なメモリ搭載量(2GB以上3GB未満)のサーバーだけで起きる現象対策として、innodb-log-file-in-groupを設定しておく必要があったが、8.0.19で検証するとエラーで止まる。

このパラメータは8.0.14以降で自動的に調整されるパラメータとなったが、当該メモリのサーバーでは起動しなくなる現象が発生する。詳しくは後述。

なおこのサイズのメモリを搭載するサーバー上で稼働させる予定が無ければ設定しない方がいいです。というわけで、設定できなくなったのでちょっと回避が難しい。

/etc/systemd/system/mysqld.service.d/override.conf

sudo systemctl edit mysqld

上記コマンド実行後に下記内容を記述して保存すること。

[Service]
LimitNOFILE=1048576

本設定はファイルディスクリプタ数の制限(4096)を緩和(1048576まで)する設定となる。

SELinux関連設定

semanage コマンドは policycoreutils-python パッケージに含まれるコマンドである。このコマンドを呼び出せない場合は yum -y install policycoreutils-python を実行しておくこと。

sudo restorecon -RFv /etc/my.cnf /etc/my.cnf.d /etc/systemd

sudo semanage port -a -t mysqld_port_t -p tcp 33061

MySQLサーバーで(デフォルトで許可され)使用できるポート番号は以下の通りである。

$ semanage port -l | grep mysqld_port_t
mysqld_port_t                  tcp      1186, 3306, 63132-63164

よって今回使用する33061番ポートの追加設定を実施する。またXプラグインを使用する場合は、同じ手順で33060番ポートの追加設定を実施する。

ファイアウォール関連設定

sudo firewall-cmd --service=mysql --add-port=33061/tcp --permanent
sudo firewall-cmd --add-service=mysql --permanent
sudo firewall-cmd --reload

MySQLサーバーで(デフォルトで許可され)通信できるポート番号は以下の通りである。

$ firewall-cmd --info-service mysql
mysql
  ports: 3306/tcp
  protocols:
  source-ports:
  modules:
  destination:

よって今回使用する33061番ポートの追加設定を実施する。またXプラグインを使用する場合は、同じく33060番ポートの追加設定を実施する。

データベースサーバーの初期セットアップ(共通)

MySQLサーバーの起動および一時パスワードの保存

sudo systemctl start mysqld
awk '/temporary password/{ print $13 }' /var/log/mysqld.log

この時表示されるキーワード(一時パスワード)を以下のコマンド実行後に入力する。

mysql_config_editor set --login-path=root --user=root --password

一時パスワードに「#」が含まれているとこの設定が有効に機能してくれない(mysqlコマンドでパスワード省略)問題を確認してるので、その場合は

  • /var/lib/mysql/ディレクトリをクリアしてから再度立ち上げ直してみる。
  • パスワード入力時に「'」(シングルクォート)でくくってやる。ただしパスワード中に「'」(シングルクォート)が存在した場合などの扱いがまた面倒。
  • 実は「\」の扱いも面倒、なので、最初の提案に戻ったりする。

また本作業はカジュアルにパスワードを見なくても済むようにするためのもので、下記のコマンドを実行することで、容易にパスワードを確認できる点に注意。

my_print_defaults --login-path=root --show client

MySQLサーバーの初期セットアップ

以後SQL文実行の際は下記コマンドを実行してから入力するモノとする。

mysql --login-path=root

root パスワードの設定

SET SQL_LOG_BIN=0;
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '一時パスワード';
SET SQL_LOG_BIN=1;
  • SQL_LOG_BIN=1(デフォルト)状態で root パスワードを設定すると、「同時期に」設定する他のサーバーにレプリケーションできなくなるので注意。
  • 「同時期」かどうかはBINLOGが最初から残っているかどうかで、ここではその詳細は問わない4
  • またここでは'root'@'localhost'の認証プラグインとしてcaching_sha2_passwordを明示したが、アプリケーションによってはmysql_native_passwordである必要があるので、どちらを使用すべきか確認すること。

バッチ的に設定するなら下記の通りでもよい。

mysql --login-path=root --connect-expired-password -e "SET SQL_LOG_BIN=0; ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '$(awk '/temporary password/{ print $13 }' /var/log/mysqld.log)'; SET SQL_LOG_BIN=1"

バリデートパスワードコンポーネントの規制緩和

SET PERSIST validate_password.policy=LOW;
SET PERSIST validate_password.length=12;

/etc/my.cnf.d/server_public_keys.pem の収集と配布

  • このファイルは先に設定したloose-group-replication-group-seedsで指定されたサーバーのSSL証明書(PEMファイル)を連結したファイルである。
  • 具体的には全てのサーバーの /var/lib/mysql/server-cert.pem ファイルの内容を/etc/my.cnf.d/server_public_keys.pemファイルに連結する。
-----BEGIN CERTIFICATE-----
~
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
~
-----END CERTIFICATE-----
  :
  • このファイル作成後にrestoreconコマンドを実行しておくこと。
restorecon -Fv /etc/my.cnf.d/server_public_keys.pem
  • 最後にこのファイルを全てのレプリケーショングループのサーバーに配布(更新)する。
  • 具体的にSCPコマンド使う、コピペする、など手段は問わない。また配布先サーバーで restorecon コマンドを実行しておくこと。
  • 重要なのでまとめると、
    • loose-group-replication-group-seedsで指定されたサーバーの/var/lib/mysql/server-cert.pemを連結したものを/etc/my.cnf.d/server_public_keys.pemとして用意する。【SSLサーバー】
    • 先に用意された/etc/my.cnf.d/server_public_keys.pemファイルを、全てのレプリケーショングループサーバーで共有する。【SSLクライアント】
  • なお本ファイル(=loose-group-replication-group-seeds設定)の更新を行っても再起動は不要である。

グループレプリケーションの設定

SET SQL_LOG_BIN=0;
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
CREATE USER 'replication'@'%' IDENTIFIED WITH caching_sha2_password BY 'パスワード';
GRANT REPLICATION SLAVE ON *.* TO replication@'%';
SET SQL_LOG_BIN=1;

CHANGE MASTER TO MASTER_USER='replication', MASTER_PASSWORD='パスワード' FOR CHANNEL 'group_replication_recovery';

ここで指定するパスワードは全台共通でかつ、パスワードジェネレータを使用して生成した文字列(12文字以上で)を設定する。

またユーザー名は取り急ぎreplicationとしている。

MySQLサーバーの初期セットアップ(1台目)

SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;

先の設定に引き続き、上記SQLを実行する。稼働状態については下記SQL文により確認できる。

SELECT * FROM performance_schema.replication_group_members;

以下実行結果例:

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST       | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1afe7555-1fc4-11e9-8959-005056a18228 | gr1.example.jp    |        3306 | ONLINE       | PRIMARY     | 8.0.19         |
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+

MySQLサーバーの初期セットアップ(2台目以降)

START GROUP_REPLICATION;

group-replication-group-seeds で指定されたサーバー(1台目など)のサーバーが生きてる状態で実行する。稼働状態については下記SQL文により確認できる。

SELECT * FROM performance_schema.replication_group_members;

以下実行結果例:

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST       | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1ac6f26d-1fc4-11e9-b5d9-005056a190c6 | gr2.example.jp    |        3306 | ONLINE       | SECONDARY   | 8.0.19         |
| group_replication_applier | 1afe7555-1fc4-11e9-8959-005056a18228 | gr1.example.jp    |        3306 | ONLINE       | PRIMARY     | 8.0.19         |
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+

もちろんどのサーバーで実行しても同じ状態が確認できれば問題無い。

タイムゾーンのインストール(マスターサーバーでのみ実行)

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql --login-path=root mysql

デフォルトタイムゾーンの設定(全てのサーバーで実行)

SET PERSIST time_zone = 'Asia/Tokyo';

グループレプリケーションの自動起動(シングル構成の場合)

SET PERSIST group_replication_bootstrap_group=ON;
SET PERSIST group_replication_start_on_boot=ON;

グループレプリケーションの自動起動(複数台構成の場合・全てのサーバーで実行)

SET PERSIST group_replication_start_on_boot=ON;

この時、group-replication-group-seeds で指定された、他のサーバーが生きている場合、自動でレプリケーションが始まる。

その前提が成り立ってない場合、手動で再立ち上げすることになるが、それはもうトラブルシュートの話となる。

SELinuxとファイアウォールの有効化

以上で基本的なセットアップは完了したが、SELinuxやファイアウォールが有効化することでサービスインできる体制が整う。

その前に/var/log/audit/audit.logを確認すること。

type=AVC msg=audit(1548327681.726:594): avc:  denied  { name_connect } for  pid=10846 comm="mysqld" dest=39062 scontext=system_u:system_r:mysqld_t:s0 tcontext=system_u:object_r:ephemeral_port_t:s0 tclass=tcp_socket permissive=1

上記のように tcontext=system_u:object_r:ephemeral_port_t:s0 と表示される場合は、semanage の設定が有効になっていない。

$ sudo semanage port -lC
SELinux Port Type              Proto    Port Number
mysqld_port_t                  tcp      33061

自分が検証した(ちょっと古い)環境では、上記のように設定を確認しても本現象が出ることがありました。
最新の環境ではそこまでチェックできてれば問題無く動くので、今はエンフォース運用に移行しています。
なお、ファイアウォールサイドでは問題になっていません。

上記問題が解決したならば、下記コマンドを実行するようにしましょう。

sudo setenforce 1
sudo systemctl start firewalld

動作検証

以下の手順で再起動を実施、無事レプリケーションが回復することを確認する。

一台ずつ止めて立ち上げる

systemctl stop mysqld
mysql --login-path=root -e "SELECT * FROM performance_schema.replication_group_members"
systemctl start mysqld

一台ずつ再起動する

systemctl reboot
mysql --login-path=root -e "SELECT * FROM performance_schema.replication_group_members"

よくある質問とその答え

Q.mysql_secure_installationコマンドは実行しなくていいのですか?

A.Securing the MySQL Installation (for MySQL 5.6 only)によれば、実行不要とのこと(Do not run mysql_secure_installtionのくだり)。

Q.mysqld_safeコマンドで立ち上げなくていいの?

A.不要です。
最近のRHELのパッケージシステムでは mysqld_safe がインストールされません。

Q.mysqladmin passwordコマンドでrootパスワードを変更しないのですか?

A.mysqlコマンドにある--connect-expired-passwordオプションがmysqladminに無いため、最初の接続ができません。

またレプリケーション実施前にSET SQL_LOG_BIN=0;SET SQL_LOG_BIN=1;でカバーしない変更は、レプリケーションログ(BINLOG)がパラレルワールド化されるので、2台目以降のレプリケーションに失敗します(同期できない)。

長らくDeploying Instances for Group Replicationの手順を参考にセットアップを行っていたのですが、どうにも上手くいかず。また一時パスワードを変更しないと、何もできないことから、これをしないで済む方法を試行錯誤の結果、先の保護が必要だ、という結論に達しました。

Q.バリデートパスワード機能を無効化するとはふてぇ野郎だ。何のつもりだ?

【ポリティカルコレクトネス的要請により手順を無効化から設定を緩くする方向に変更】

A.おっしゃる通り、自分はvalidate_password.policy=LOWにしたかっただけだったのですが、マニュアルによると、従来のやり方(プラグイン・my.cnfに設定可能)と新しいやり方(コンポーネント・SQL文を実行しないと行けない)が

  • 同時に書いてある、
  • 設定してる内容は同じ、

でも機能しない(エラーになる)というトラブルを抱え込んで、解決するまでに時間がかかった結果、気がついた瞬間にキレて無効にしたというものです:-)。

Q.下記のメッセージが表示されてサーバーが起動しません!

[ERROR] [MY-012961] [InnoDB] Only one log file found
[ERROR] [MY-012930] [InnoDB] Plugin initialization aborted with error not found.
[ERROR] [MY-010334] [Server] Failed to initialize DD Storage Engine
[ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
[ERROR] [MY-010119] [Server] Aborting

8.0.14以降で innodb-dedicated-server = TRUE の時、搭載メモリが2GB以上3GB未満のサーバーでこの問題が起きます。

上記条件のサーバーでは innodb-buffer-pool-size が1GB以上1.5GB未満に設定されるのですが、この結果を受けて innodb-log-files-in-group1に設定されます5

最小値である2であるべきですが、処理上、この訂正がなされないため起動しません。

このバグですが、プルリクしたのですが、バグレポートアカウント無いと受け付けてくれないみたいなので、修正されていません。誰かフィードバックよろしく。

Q.下記のメッセージが表示されてレプリケーションが始まり(RECOVERING状態のまま変化しない)ません!

[ERROR] [MY-010584] [Repl] Slave I/O for channel 'group_replication_recovery': error connecting to master 'replication@マスターサーバー:3306' - retry-time: 60  retries: 1, Error_code: MY-002061
[ERROR] [MY-011582] [Repl] Plugin group_replication reported: 'There was an error when connecting to the donor server. Please check that group_replication_recovery channel credentials and all MEMBER_HOST column values of performance_schema.replication_group_members table are correct and DNS resolvable.'
[ERROR] [MY-011583] [Repl] Plugin group_replication reported: 'For details please check performance_schema.replication_connection_status table and error log messages of Slave I/O for channel group_replication_recovery.'
mysql> SELECT * FROM  performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST       | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1afe7555-1fc4-11e9-8959-005056a18228 | gr1.example.jp    |        3306 | ONLINE       | PRIMARY     | 8.0.14         |
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+

本ケースを参考に丹念にセットアップを行った場合は問題ありません。
既に過去の手順ではありますが、わざと group-replication-recovery-get-public-key=OFF(デフォルト設定)、group-replication-recovery-use-ssl=OFF(デフォルト設定)とした場合に発生しえます。

これは caching_sha2_password の場合、認証フェーズにおいてサーバーの公開鍵を必要としますが、SSL通信の場合はSSL証明書から、非SSL通信の場合はサーバーが持つ公開鍵を別途必要とします。

よって「正規の」解決方法は

  • ★レプリケーション時の通信をSSL化するか
  • サーバーの公開鍵を取得・保存の上、指定するか
  • そもそも mysql_native_password にするか
  • サーバーから公開鍵をもらう6

の4択になります。

mysql_native_passwordは敗北なのと、サーバーの公開鍵を取得・保存の方法はわからなかったので、SSL通信することで回避します7
詳細は Using Group Replication and the Caching SHA-2 User Credentials Plugin に書いてあるのですが、全てのサーバーで、全てのサーバーの公開鍵の取得が必要なんじゃあ…とか、取得したらどうファイルに入れ込むのか…といった点が理解できず、解決には時間がかかりました。

Q.下記のメッセージが表示されてレプリケーションが始まりません!

[ERROR] [MY-011526] [Repl] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: 1afe7555-1fc4-11e9-8959-005056a18228:1 > Group transactions: 1ac6f26d-1fc4-11e9-b5d9-005056a190c6:1,
[ERROR] [MY-011522] [Repl] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.'

A.SET SQL_LOG_BIN=0;せずにrootのパスワードを変更すると発生します。このエラーからBINLOGの不一致を疑っています。ただし詳細は追いかけていません。

Q.下記のメッセージが表示されてレプリケーションが回復(RECOVERINGのまま)しません!

[ERROR] [MY-010584] [Repl] Slave I/O for channel 'group_replication_recovery': error connecting to master 'replication@その時のマスターサーバー:3306' - retry-time: 60  retries: 1, Error_code: MY-001045
[ERROR] [MY-011582] [Repl] Plugin group_replication reported: 'There was an error when connecting to the donor server. Please check that group_replication_recovery channel credentials and all MEMBER_HOST column values of performance_schema.replication_group_members table are correct and DNS resolvable.'
mysql> SELECT * FROM  performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST       | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1ac6f26d-1fc4-11e9-b5d9-005056a190c6 | gr2.example.jp    |        3306 | RECOVERING   | SECONDARY   | 8.0.14         |
| group_replication_applier | 1afe7555-1fc4-11e9-8959-005056a18228 | gr1.example.jp    |        3306 | ONLINE       | PRIMARY     | 8.0.14         |
+---------------------------+--------------------------------------+-------------------+-------------+--------------+-------------+----------------+

A.諦めろん。マスターとスレーブでズレが発生しました。マスターからダンプしてスレーブを設定し直しましょう。

検証した限りでは、設定のバックエンドがDB(ユーザーやコンポーネント、プラグイン等)で、サーバー固有の設定(INSTALL COMPONENT 等)を行うと、BINLOGがパラレルワールド化してしまうのではないかと想像しています。ただし詳細は追いかけていないです。

Q.下記の警告がでますが大丈夫ですか?

[Warning] [MY-013168] [InnoDB] Cannot upgrade server earlier than 5.7 to 8.0 Option innodb_dedicated_server is ignored for innodb_log_files_in_group because innodb_log_files_in_group=2 is specified explicitly.
[Warning] [MY-010897] [Repl] Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.

A.とりあえず「大丈夫だ、問題無い」ことにしておく。

  • 前者は innodb-log-files-in-group 指定をしないと起動しないので諦めるしか。
  • 後者は厳密にはパスワードレスな認証の仕組みを導入する必要があるが、SSL通信化で今は問題発生しないと思う。

Q.グループレプリケーションサーバーを追加しようと思ってるのですが、「replication」ユーザーのパスワードを忘れてしまいました。どうすればいいのでしょうか。

A.「replication」ユーザーのパスワードは忘れてしまってかまわないのですが、その場合、全てのサーバーでパスワード変更(ALTER USER)の上、CHANGE MASTER TO 文を発行する必要がある。

SET SQL_LOG_BIN=0;
ALTER USER 'replication'@'%' IDENTIFIED WITH caching_sha2_password BY '新しいパスワード';
SET SQL_LOG_BIN=1;
CHANGE MASTER TO MASTER_USER='replication', MASTER_PASSWORD='新しいパスワード' FOR CHANNEL 'group_replication_recovery';

上記実行自体はレプリケーション中の「レプリケーション動作」に影響受けないが、再接続時および追加予定のサーバーでは本設定が参照(認証)される。

Q.SSL証明書関連のくだりが面倒なのですが。

A.Systemdスクリプトの内容を追っていくと、/usr/bin/mysqld_pre_systemd にてMySQLを初期化(--initialize)してるので、その内容を自前で解決する作戦に出る手はあります。
Managing MySQL Server with systemd を読むと実はそう難しくないのかな、と思いつつ、未検証で。

参考文献


  1. enforcingモードでうまく行かない場合はpermissiveモードで運用する。 

  2. ネットワーク設定や時刻同期設定など。 

  3. uuidgenutil-linuxパッケージに収納されている。 

  4. 本手順では、まとめてサーバーセットアップする前提の手順のため。 

  5. マニュアルにある「GB単位のバッファプールサイズのROUND」とは、ROUND(1.0)ないしはROUND(1.5未満)の計算という意味になりますが、小数点以下を四捨五入するため、1になります。 

  6. 当然セキュリティ的なトレードオフがあります。マニュアルによればMITMに弱いです。 

  7. 初期セットアップ時に作成されるSSL証明書は自己署名証明書になります。 

32
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
36