こちらはDMM.com #2 Advent Calendar 2017の25日目の記事です。
前日の記事は@tinojiさんのSonarQubeとCircleCIで技術的負債を駆逐せよ!でした。
弊社のアドベントカレンダーのURLはこちら
DMM.com #1 Advent Calendar 2017
DMM.com #2 Advent Calendar 2017
tl;dr
oow 2016で発表されてたInnodb Cluster触ってみた
mysqlshellのバージョンによっては正常に動作しなかった
まえがき
huatoです。
主に各サービスのデータベースの面倒を見ています。
最近は業務改善がメインで、運用負荷の軽減と障害発生時のダウンタイム短縮につながればと
MySQL5.7対応とあわせて各種の動作検証を続けてきました。
インストール中に発生した問題と解決方法についてまとめました。
少しでもお役に立てれば幸いです。
InnoDB Cluster
オラクル社純正のパッケージだけでDBの高可用性構成がとれる製品です。
障害発生時のスレーブの自動切り離し、マスター昇格など
従来は管理者がデータベース運用時に独自実装してたことが機能として兼ね備えられています。
MHAではスクリプトを別で用意してやる必要がありました。
データのコピーはrsyncやxtraBackupで行わずMySQLの機能のみでまかなっている点がPercona XtraDB Clusterと異なります。
現在はシングルプライマリ構成がメインですが将来的にはマルチマスターもサービスレベルで使えるようになる、はず。
Group Replicationについては別記事にしました。
https://qiita.com/huato/items/29714e2ddf72df7009ec
環境
CentOS 7.3 x86_64
MySQL:5.7.20
CPU:2core
RAM:2GB
[mysql-router]
advent-01 192.168.0.100 ipalias 192.168.0.112
advent-02 192.168.0.101 ipalias 192.168.0.110
advent-03 192.168.0.102 ipalias 192.168.0.111
[mysql group replication]
advent-04 192.168.0.103
advent-05 192.168.0.104
advent-06 192.168.0.105
下準備
ポート開放
InnoDB Cluster構成独自のポートを解放します。
13306:Group Replicationのnode間の通信ポート、
33060:mysqlsh接続時のdefaultポート,X Protocolが使用です。
今回は検証ですのでポートまるごと解放してます。
innodb cluster関連ポート解放
firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --add-port=33060/tcp --permanent
firewall-cmd --add-port=13306/tcp --permanent
設定反映
firewall-cmd --reload
設定確認
firewall-cmd --list-all-zones
hosts追記
Group Replicationの各サーバのIP情報をすべてのサーバの/etc/hostsに追記します。
記載例
192.168.0.103 advent-04
192.168.0.104 advent-05
192.168.0.105 advent-06
MySQLインストール方法については割愛します。
rootユーザパスワード変更
mysqlsh経由の操作はパスワードが空の状態だと実行できず
単純なパスワードを設定すると後述するレプリケーション設定時に失敗しました。
https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-19.html
SET SQL_LOG_BIN=0;
ALTER USER 'root'@'localhost' IDENTIFIED BY '英数ランダム+記号';
SET SQL_LOG_BIN=1;
MySQL-Shell
rpmでインストールします。
wget https://dev.mysql.com/get/Downloads/MySQL-Shell/mysql-shell-1.0.11-1.el7.x86_64.rpm
rpm -ivh MySQL-Shell/mysql-shell-1.0.11-1.el7.x86_64.rpm
mysqlsh --uri root@localhost:3306
Creating a Session to 'root@localhost:3306'
Enter password:
ERROR: 1130 (HY000): Host '::1' is not allowed to connect to this MySQL server
/etc/hostsでlocalhost追記
現象変わらず
skip-name-resolve コメントアウトしてmysqld再起動
sed -i 's/skip-name-resolve/#skip-name-resolve/g' /etc/my.cnf
systemctl restart mysqld
再度挑戦し今度はログインできました。
初期設定が要件を満たしているかチェックと修正を実施します。
mysql-js> dba.configureLocalInstance();
Please provide the password for 'root@localhost:3306':
Detecting the configuration file...
Found configuration file at standard location: /etc/my.cnf
Do you want to modify this file? [Y|n]: [Y|n]: y
MySQL user 'root' cannot be verified to have access to other hosts in the network.
1) Create root@% with necessary grants
2) Create account with different name
3) Continue without creating account
4) Cancel
Please select an option [1]: 1
Password for new account:
Confirm password:
Validating instance...
The instance 'localhost:3306' is valid for Cluster usage
You can now use it in an InnoDB Cluster.
{
"status": "ok"
}
クラスターの作成
var cluster = dba.createCluster('myCluster', {ipWhitelist:'192.168.0.0/22,127.0.0.1/8'});
エラー
Creating InnoDB cluster 'myCluster' on 'root@localhost:3306'...
Dba.createCluster: To add an instance to the cluster, please use a valid, non-local hostname or IP. localhost can only be used with sandbox MySQL instances. (RuntimeError)
localhostではなくIPアドレス直指定で再度接続してねということでやり直し。
[root@advent-06 ~]# mysqlsh --uri root@192.168.0.103:3306
mysql-js> var cluster = dba.createCluster('myCluster', {ipWhitelist:'192.168.0.0/22,127.0.0.1/8'});
A new InnoDB cluster will be created on instance 'root@192.168.0.103:3306'.
Creating InnoDB cluster 'myCluster' on 'root@192.168.0.103:3306'...
Adding Seed Instance...
Cluster successfully created. Use Cluster.addInstance() to add MySQL instances.
At least 3 instances are needed for the cluster to be able to withstand up to
one server failure.
クラスタの作成に成功しました。
statusがONLINEであれば正常です。
mysql-js> var cluster = dba.getCluster();
mysql-js> cluster.status();
{
"clusterName": "myCluster",
"defaultReplicaSet": {
"name": "default",
"primary": "192.168.0.103:3306",
"status": "OK_NO_TOLERANCE",
"statusText": "Cluster is NOT tolerant to any failures.",
"topology": {
"192.168.0.103:3306": {
"address": "192.168.0.103:3306",
"mode": "R/W",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
}
}
}
}
残り2台のnodeをクラスタに登録します。
cluster.addInstance('root@192.168.0.104:3306', {ipWhitelist:'192.168.0.0/22,127.0.0.1/8'});
cluster.addInstance('root@192.168.0.105:3306', {ipWhitelist:'192.168.0.0/22,127.0.0.1/8'});
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 26330a88-e6c3-11e7-9899-9ca3ba26309e | advent-04 | 3306 | ONLINE |
| group_replication_applier | 95177de6-e6c4-11e7-8a41-9ca3ba2e60c5 | advent-05 | 3306 | RECOVERING |
| group_replication_applier | d43cd4f2-e6c3-11e7-bc93-9ca3ba295d10 | advent-06 | 3306 | RECOVERING |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
2017-12-22T10:17:44.788713+09:00 0 [ERROR] Plugin group_replication reported: '[GCS] The member was unable to join the group. Local port: 13306'
13306ポートの通信許可設定がされてないと失敗します。
GTID関係のエラーが出力された場合はreste masterしてGTIDをリセットしたところ解消されました。
2017-12-22T11:20:18.076317+09:00 0 [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: 0aa0ba56-e6be-11e7-beb4-9ca3ba2e60c5:1-124 > Group transactions: 87c6cc6c-e6b5-11e7-907c-9ca3ba26309e:1-41,
b4a208ce-e414-11e7-a6d2-9ca3ba26309e:1-16'
2017-12-22T11:20:18.076374+09:00 0 [ERROR] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.'
2017-12-22T11:20:18.076383+09:00 0 [Note] Plugin group_replication reported: 'To force this member into the group you can use the group_replication_allow_local_disjoint_gtids_join option'
Cluster.addInstance: WARNING: Not running locally on the server and can not access its error log.
さらにrootのパスワード強度が弱い場合も自分の時は失敗しました。
無効化したはずだったんですが。。
mysql> SHOW VARIABLES LIKE 'validate_password%';
Empty set (0.00 sec)
release noteにそれらしきものが記載されていましたのでパスワードを記号含む英数ランダム8文字以上に変更しました。
Replication: When first starting the MySQL server following an installation from RPM,
passwword validation plugin is activated by default (true only for RPM installations).
If binary logging was already enabled at this time, the activation was logged, even though plugin activations should not be recorded in the binary log. (Bug #25672750)
ここまでの対応をしてもRECOVERINGからONLINEにMEMBER_STATEが変更されません。
ログを見ると、マスター候補の環境のバイナリログを先頭から実施しようとしてmysqlデータベースがすでに存在することでエラーになっていました。
2017-12-22T13:05:14.914542+09:00 61 [Warning] Slave: Can't create database 'mysql'; database exists Error_code: 1007
内部処理でCHANGE MASTER実施時にmaster_log_posが不要に見受けられるのですが、解消できそうなオプションなどは見当たりませんでしたので
mysql-shell-1.0.8-0.1にダウングレードしたところ解消されました。
20180310追記
上記間違いでした。
追加対象のnode上から実行することで問題解消しました。
https://dev.mysql.com/doc/refman/5.7/en/mysql-innodb-cluster-production-deployment.html
Use the cluster.addInstance(instance) function to add more instances to the cluster, where instance is a URI type string to connect to the local instance.
各node環境にログインしてcluster.addInstanceする必要があります。
MySQL Router
Master環境でユーザを作成します。
WITH GRANT OPTIONはmysql-routerにレプリケーショングループを登録時に専用のユーザが自動作成されるために必要です。
create user 'srepl'@'192.168.0.101' identified by '英数ランダム+記号';
create user 'srepl'@'192.168.0.102' identified by '英数ランダム+記号';
create user 'srepl'@'192.168.0.100' identified by '英数ランダム+記号';
GRANT RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO 'srepl'@'192.168.0.101' WITH GRANT OPTION;
GRANT SELECT, INSERT, UPDATE, DELETE ON `mysql`.* TO 'srepl'@'192.168.0.101' WITH GRANT OPTION;
GRANT SELECT ON `performance_schema`.* TO 'srepl'@'192.168.0.101' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON `mysql_innodb_cluster_metadata`.* TO 'srepl'@'192.168.0.101' WITH GRANT OPTION;
GRANT RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO 'srepl'@'192.168.0.102' WITH GRANT OPTION;
GRANT SELECT, INSERT, UPDATE, DELETE ON `mysql`.* TO 'srepl'@'192.168.0.102' WITH GRANT OPTION;
GRANT SELECT ON `performance_schema`.* TO 'srepl'@'192.168.0.102' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON `mysql_innodb_cluster_metadata`.* TO 'srepl'@'192.168.0.102' WITH GRANT OPTION;
GRANT RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO 'srepl'@'192.168.0.100' WITH GRANT OPTION;
GRANT SELECT, INSERT, UPDATE, DELETE ON `mysql`.* TO 'srepl'@'192.168.0.100' WITH GRANT OPTION;
GRANT SELECT ON `performance_schema`.* TO 'srepl'@'192.168.0.100' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON `mysql_innodb_cluster_metadata`.* TO 'srepl'@'192.168.0.100' WITH GRANT OPTION;
yumでさくっとインストールします。
wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
yum --enablerepo=mysql57-community --disablerepo=mysql56-community --disablerepo=epel install mysql-community-client mysql-router
mysql-router各環境それぞれで既存のレプリケーショングループを登録します。
登録時にDBにユーザが自動生成されます。
[root@advent-02 src]#mysqlrouter --bootstrap srepl@advent-04 --user=mysqlrouter
Please enter MySQL password for srepl:
WARNING: The MySQL server does not have SSL configured and metadata used by the router may be transmitted unencrypted.
Bootstrapping system MySQL Router instance...
MySQL Router has now been configured for the InnoDB cluster 'myCluster'.
The following connection information can be used to connect to the cluster.
Classic MySQL protocol connections to cluster 'myCluster':
- Read/Write Connections: localhost:6446
- Read/Only Connections: localhost:6447
X protocol connections to cluster 'myCluster':
- Read/Write Connections: localhost:64460
- Read/Only Connections: localhost:64470
Existing configurations backed up to /etc/mysqlrouter/mysqlrouter.conf.bak
nmtuiでIP付与
[root@advent-02 mysqlrouter]# systemctl status mysqlrouter
* mysqlrouter.service - MySQL Router
Loaded: loaded (/usr/lib/systemd/system/mysqlrouter.service; disabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Sat 2017-12-23 07:35:29 JST; 7s ago
Process: 4049 ExecStart=/usr/bin/mysqlrouter -c /etc/mysqlrouter/mysqlrouter.conf (code=exited, status=1/FAILURE)
Main PID: 4049 (code=exited, status=1/FAILURE)
Dec 23 07:35:29 advent-02 systemd[1]: Started MySQL Router.
Dec 23 07:35:29 advent-02 systemd[1]: Starting MySQL Router...
Dec 23 07:35:29 advent-02 mysqlrouter[4049]: Error: stat() failed (/var/lib/mysqlrouter/keyring): Permission denied
Dec 23 07:35:29 advent-02 systemd[1]: mysqlrouter.service: main process exited, code=exited, status=1/FAILURE
Dec 23 07:35:29 advent-02 systemd[1]: Unit mysqlrouter.service entered failed state.
Dec 23 07:35:29 advent-02 systemd[1]: mysqlrouter.service failed.
ファイルの権限が足りていません。
実行ユーザに権限を変更して対処しました。
cd /var/lib
chown -R mysqlrouter:mysqlrouter mysqlrouter
configの設定を書き換えます。
マニュアルに記載はありませんでしたが
bind_addressでreadとwriteの向け先をコントールできそうです。
cat /etc/mysqlrouter/mysqlrouter.conf
# File automatically generated during MySQL Router bootstrap
[DEFAULT]
name=system
user=mysqlrouter
keyring_path=/var/lib/mysqlrouter/keyring
master_key_path=/etc/mysqlrouter/mysqlrouter.key
logging_folder=/var/log/mysqlrouter
[logger]
level = INFO
[metadata_cache:myCluster]
router_id=1
bootstrap_server_addresses=mysql://192.168.0.103:3306,mysql://192.168.0.104:3306,mysql://192.168.0.105:3306
user=mysql_router1_5npdqnkckv4u
metadata_cluster=myCluster
ttl=10
[routing:myCluster_default_rw]
bind_address=192.168.0.101
bind_port=3306
destinations=metadata-cache://myCluster/default?role=PRIMARY
mode=read-write
protocol=classic
max_connect_errors=2048
max_connections=1024
[routing:myCluster_default_ro]
bind_address=192.168.0.110
bind_port=3306
destinations=metadata-cache://myCluster/default?role=SECONDARY
mode=read-only
protocol=classic
max_connect_errors=2048
max_connections=1024
まずはマスターへの接続を試してみます。
何度実行してもマスターにしか接続が割り振られません。
[root@advent-01 mysqlrouter]# mysql -uroot -p -h 192.168.0.102
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8667
Server version: 5.7.20-log MySQL Community Server (GPL)
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
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> show variables like 'hostname';
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| hostname | advent-04 |
+---------------+-----------+
1 row in set (0.01 sec)
次はスレーブに接続を試みます。
実行ごとにRound Robinで接続先の環境が切り替わりました。
[root@advent-01 mysqlrouter]# mysql -uroot -p -h 192.168.0.111
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 5.7.20-log MySQL Community Server (GPL)
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
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> show variables like 'hostname';
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| hostname | advent-06 |
+---------------+-----------+
1 row in set (0.00 sec)
まとめ
アプリケーションからの接続のコントロールをInnoDB Clusterにまかせることで
従来の運用と比べて運用負荷が下がりそうです。
本番運用を想定した負荷試験の結果などはまた機会があればどこかに記事を書きたいと思います。
参考URL
https://dev.mysql.com/doc/dev/mysqlsh-api-javascript/1.0/classmysqlsh_1_1dba_1_1_dba.html#a60dfedbd2784ba132879a21a7b13ae4b
https://mysqlserverteam.com/innodb-cluster-in-opc/
https://mysqlserverteam.com/innodb-cluster-in-opc-part2/
https://dev.mysql.com/doc/mysql-router/2.1/en/mysql-router-conf-options.html
https://dev.mysql.com/doc/refman/5.7/en/mysql-innodb-cluster-production-deployment.html
https://www.slideshare.net/ShinyaSugiyama/mysql-innodb-clusterdb-tech-showcase-2017