はじめに
皆さんはMySQLの検証を行うときに、SELinux や firewalld をどうしているでしょうか?
本番環境でMySQLを稼働させる場合、セキュリティについても十分に考慮する必要があります。
SELinux および firewalld は、RHEL7(CnetOS7)に標準実装されている優秀なセキュリティソフトです。折角あるのであれば、これを使わない手はありません。
ということで、この記事では両ツールを稼働させながらMySQL8.0のGroup Replication環境を構築する手順について触れたいと思います。
SELinux / firewalld について
これらのセキュリティの詳細については他の詳しい解説記事なども参考にして欲しいですが、本記事内では以下のような認識で問題ありません。
SELinux
サーバ上のファイルなどへのアクセスを制御する。適切に権限が設定されていないと、任意のファイル作成もできない。
firewalld
その名の通りファイヤーウォール。任意のIPアドレスやポート番号を設定し、サーバへのアクセスを許可・拒否できる。
環境について
vagrantで作成した以下のサーバにMySQL8.0をインストールしています。
OSは全て CentOS7.4 です。
hostname | IP address | 役割 |
---|---|---|
server1 | 192.168.100.101 | Node1 |
server2 | 192.168.100.102 | Node2 |
server3 | 192.168.100.103 | Node3 |
環境構築手順
全サーバに、yumコマンドでサクっとMySQL8.0をインストールします。
1 2 |
$ sudo rpm -ivh http://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm $ sudo yum install -y mysql-community-server |
Group Replicationの設定は、公式マニュアルを見ながら進めましょう。
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 |
$ sudo tee /etc/my.cnf << EOT [mysqld] log_error=/var/log/mysqld.log server_id=10 ### server2=20 / server3=30 gtid_mode=ON enforce_gtid_consistency=ON binlog_checksum=NONE log_bin=binlog log_slave_updates=ON binlog_format=ROW master_info_repository=TABLE relay_log_info_repository=TABLE early-plugin-load="group_replication.so" transaction_write_set_extraction=XXHASH64 group_replication_group_name="93d64ef2-ffb0-4498-bd7e-3805c6b80df2" group_replication_start_on_boot=off group_replication_local_address="192.168.100.101:33061" ### server2=192.168.100.102 / server3=192.168.100.103 group_replication_group_seeds= "192.168.100.101:33061,192.168.100.102:33061,192.168.100.103:33061" group_replication_bootstrap_group=off EOT $ sudo systemctl start mysqld $ sudo cat /var/log/mysqld.log | grep temporary 2018-12-11T05:35:53.392832Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: rKhHjns/t8k= $ mysql -u root -p |
1 2 3 4 5 6 7 |
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'MySQL8.0'; mysql> SET SQL_LOG_BIN=0; mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'Replp@ss1'; mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%'; mysql> FLUSH PRIVILEGES; mysql> SET SQL_LOG_BIN=1; mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='Replp@ss1' FOR CHANNEL 'group_replication_recovery'; |
Node1を初期ノードとして、Group Replicationを開始しますと、エラーが発生します。これはSELinuxが有効になっているためです。
1 2 3 |
node1> SET GLOBAL group_replication_bootstrap_group=ON; node1> START GROUP_REPLICATION; ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log. |
一旦ここではSELinuxをOFFにしましょう。
1 2 3 4 |
node1$ sudo setenforce 0 node1> START GROUP_REPLICATION; node1> SET GLOBAL group_replication_bootstrap_group=OFF; |
Node2 / Node3 でもGroup Replicationを開始します。
(ノード間で名前解決ができるよう、/etc/hostsの設定に注意してください)
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 |
node2> RESET MASTER; node2> START GROUP_REPLICATION; node3> RESET MASTER; node3> START GROUP_REPLICATION; node3> SELECT * FROM performance_schema.replication_group_members\G *************************** 1. row *************************** CHANNEL_NAME: group_replication_applier MEMBER_ID: 9ee8ae99-fd06-11e8-a618-525400e67b97 MEMBER_HOST: server2 MEMBER_PORT: 3306 MEMBER_STATE: ONLINE MEMBER_ROLE: SECONDARY MEMBER_VERSION: 8.0.13 *************************** 2. row *************************** CHANNEL_NAME: group_replication_applier MEMBER_ID: 9f083e64-fd06-11e8-a490-5254006d0a45 MEMBER_HOST: server3 MEMBER_PORT: 3306 MEMBER_STATE: ONLINE MEMBER_ROLE: SECONDARY MEMBER_VERSION: 8.0.13 *************************** 3. row *************************** CHANNEL_NAME: group_replication_applier MEMBER_ID: 9f116a05-fd06-11e8-a854-525400d7771a MEMBER_HOST: server1 MEMBER_PORT: 3306 MEMBER_STATE: ONLINE MEMBER_ROLE: PRIMARY MEMBER_VERSION: 8.0.13 3 rows in set (0.00 sec) |
SELinuxの設定方法
では、Group Replicationの通信ができるようSELinuxを設定してみましょう。
手順としては、SELinuxを有効にしたあと、Group Replicationが通信するportを
semanageコマンドを使って手動で開放していきます。具体的には、group_replication_local_address変数で指定しているポートです(今回は33061)
実際にNode3で試してみましょう。
1 2 3 |
node3$ sudo setenforce 1 node3$ sudo yum install -y policycoreutils-python ### semanageコマンドが含まれています node3$ sudo semanage port -a -t mysqld_port_t -p tcp 33061 |
この状態でNode3のGroup_Replicationを再起動します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
node3$ mysql -u root -pMySQL8.0 node3> STOP GROUP_REPLICATION; node3> START GROUP_REPLICATION; mysql> SELECT * FROM performance_schema.replication_group_members WHERE MEMBER_HOST = "server3"\G *************************** 1. row *************************** CHANNEL_NAME: group_replication_applier MEMBER_ID: 9f083e64-fd06-11e8-a490-5254006d0a45 MEMBER_HOST: server3 MEMBER_PORT: 3306 MEMBER_STATE: ONLINE MEMBER_ROLE: SECONDARY MEMBER_VERSION: 8.0.13 1 row in set (0.01 sec) |
問題なく接続ができているようです。
ちなみに semanage で全く別のポートを開放してしまうと、以下のようにSTART GROUP_REPLICATIONができなくなります(その場合は同じくsemanageで設定を削除しましょう)。
1 2 3 4 5 6 7 8 9 |
node2$ sudo semanage port -a -t mysqld_port_t -p tcp 33062 node2> STOP GROUP_REPLICATION; node2> START GROUP_REPLICATION; ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log. node2$ sudo semanage port -l | grep mysqld_port mysqld_port_t tcp 33062, 1186, 3306, 63132-63164 node2$ sudo semanage port -d -t mysqld_port_t -p tcp 33062 |
firewalldの設定方法
次にfirewalldを設定します。こちらも基本的にはSELinuxと同じく、Group Replicationで使用するポート(33061)を開放していく形になります。ただし、firewalldの場合はアクセスが可能なIPアドレスを明示的に指定する必要があります。
早速、Node3で試してみましょう。ここでは、デフォルトの public ゾーンに対して、 rich_rule を使って設定します。
1 2 3 4 5 6 7 8 9 10 11 12 |
node3$ sudo systemctl start firewalld ### node1に対してのみ33061ポートを開放 node3$ sudo firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address=192.168.100.101/32 port protocol=tcp port=33061 accept' --permanent node3$ sudo firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 destination address=192.168.100.101/32 port protocol=tcp port=33061 accept' --permanent ### node2に対してのみ33061ポートを開放 node3$ sudo firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 source address=192.168.100.102/32 port protocol=tcp port=33061 accept' --permanent node3$ sudo firewall-cmd --zone=public --add-rich-rule='rule family=ipv4 destination address=192.168.100.102/32 port protocol=tcp port=33061 accept' --permanent ### firewalldをリロード node3$ sudo firewall-cmd --reload |
この状態でNode3のmysqldを再起動し、GROUP_REPLICATIONを再開しても問題なく接続ができます。
1 2 3 4 5 6 7 8 9 10 11 12 |
node3$ sudo systemctl restart mysqld node3$ mysql -u root -pMySQL8.0 -e "START GROUP_REPLICATION" node3$ mysql -u root -pMySQL8.0 -e "SELECT * FROM performance_schema.replication_group_members WHERE MEMBER_HOST = 'server3'\G" *************************** 1. row *************************** CHANNEL_NAME: group_replication_applier MEMBER_ID: fffaf3f5-fde7-11e8-b33d-5254008046e0 MEMBER_HOST: server3 MEMBER_PORT: 3306 MEMBER_STATE: ONLINE MEMBER_ROLE: SECONDA |
次にNode2では、firewalldを起動した後に33061ポートの開放をスキップして、Group Replicationを再起動します。すると、33061ポートに繋ぐことができずタイムアウトになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
node2$ sudo systemctl start firewalld node2$ mysql -u root -pMySQL8.0 node2> STOP GROUP_REPLICATION; node2> START GROUP_REPLICATION; ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log. node2$ sudo less /var/log/mysqld.log > 2018-12-12T08:58:59.506590Z 12 [ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] Error pushing message into group communication engine.' > 2018-12-12T08:59:00.507147Z 12 [ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] Error pushing message into group communication engine.' ... > 2018-12-12T08:59:55.254522Z 0 [ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] The member was unable to join the group. Local port: 33061' > 2018-12-12T09:00:25.201093Z 20 [ERROR] [MY-011640] [Repl] Plugin group_replication reported: 'Timeout on wait for view after joining group' |
InnoDB Clusterの場合
前回、InnoDB Clusterの記事を書きましたが、実際に本番環境でGroup Replicationを使用される場合は InnoDB Cluster として合わせて構築するケースが多いと思います。その場合は、Group Replicationで使用するポートに加え、MySQL Shellが使用するポートも開放する必要があります(デフォルト:33060)。
まとめ
MySQLの検証などを中心に行っていると、SELinux や firewalld はつい軽視しがちですが、可能な限り検証環境の段階から有効にすることをオススメします。
実際に触ってみると思ったよりも操作は簡単なので、是非お試しください。
おまけ:Galeraの場合
PXCなどのGalera Clusterの場合は、開放するポートが Group_Replication とは異なります。基本的には以下4つのポートを SELinux および firewalld で開放すれば問題ありません。
- 3306 : 通常のMySQL通信用ポート
- 4567 : Galeraレプリケーション(wsrep replication)用ポート
- 4568 : ノード間の差分同期(IST)用ポート
- 4444 : ノード間の完全同期(SST)用ポート
参考サイト
18.9 Frequently Asked Questions
FIREWALL SETTINGS
Lock Down: Enforcing SELinux with Percona XtraDB Cluster