githubが開発しているOrchestoratorについて、
以前の記事で、MariaDBに対応していない?と記載してしまったが、
実際に試してみたところ、MariaDBのGTIDレプリケーションにも対応していたので、
その備忘録を記載します。
なお、検証したバージョンは以下となります。
- CentOS7.5
- MariaDB10.3.11
- Orchestorator3.0.13
1.MariaDBのセットアップ
master、slave×2の準同期レプリケーションを構築します。
構成は以下の通り。
----------------------------------------
master
IP:192.168.35.11
----------------------------------------
| |
|(semi sync) |(semi sync)
| |
-------------------- --------------------
slave slave
IP:192.168.35.12 IP:192.168.35.13
-------------------- --------------------
設定は以下の通り。
# マルチソースをやる際に必要かもしれないので、レプリケーションクラスターで共通の数字
gtid_domain_id=11
# レプリケーションクラスター間で一意の数字(IPアドレスの下2桁など)
server_id={{ server_id }}
# 名前解決ができない環境向けに、自身のノードのIPアドレスを設定しておく
report_host={{ ip_addr }}
# とりあえず0だが、動的に変更する
read_only=0
# 安定のrow
binlog_format=row
# 毎コミットごとにバイナリログに書き出す
sync_binlog=1
# フェイルオーバー時にslaveが昇格しても大丈夫なように
log_slave_updates=1
# レプリケーション安全設定
relay_log_recovery=1
# 大きなリレーログへの対応
slave_max_allowed_packet=1G
# タイムアウト長めに
slave_net_timeout=3600
# slaveのSQLスレッドの並列化
slave_parallel_threads={{ cpu_num }}
# 厳格モード
gtid_strict_mode=1
# 以下、準同期設定(MariaDB10.3では、plugin_load_addは不要)
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1500
rpl_semi_sync_slave_enabled=1
rpl_semi_sync_master_wait_point=AFTER_SYNC
そして、レプリケーションを開始しておく。
2.Orchestoratorの設定
IPアドレス192.168.35.10のOrchestorator専用ノードを立てる。
orchestorator.conf.jsonの内容は以下の通り。
{
"Debug": false,
"EnableSyslog": false,
"ListenAddress": ":3000",
"MySQLTopologyUser": "adminuser",
"MySQLTopologyPassword": "adminpassword",
"BackendDB": "sqlite",
"SQLite3DataFile": "/usr/local/orchestrator/orchestrator.sqlite3",
"DiscoverByShowSlaveHosts": true,
"InstancePollSeconds": 5,
"UnseenInstanceForgetHours": 240,
"SnapshotTopologiesIntervalHours": 0,
"InstanceBulkOperationsWaitTimeoutSeconds": 10,
"HostnameResolveMethod": "default",
"MySQLHostnameResolveMethod": "@@report_host",
"SkipBinlogServerUnresolveCheck": true,
"ExpiryHostnameResolvesMinutes": 60,
"RejectHostnameResolvePattern": "",
"ReasonableReplicationLagSeconds": 10,
"ProblemIgnoreHostnameFilters": [],
"VerifyReplicationFilters": false,
"ReasonableMaintenanceReplicationLagSeconds": 20,
"CandidateInstanceExpireMinutes": 60,
"DetectClusterAliasQuery": "SELECT @@report_host",
"PromotionIgnoreHostnameFilters": [],
"DetectSemiSyncEnforcedQuery": "",
"URLPrefix": "",
"StatusEndpoint": "/api/status",
"StatusSimpleHealth": true,
"StatusOUVerify": false,
"AgentPollMinutes": 60,
"UnseenAgentForgetHours": 6,
"StaleSeedFailMinutes": 60,
"SeedAcceptableBytesDiff": 8192,
"PseudoGTIDPattern": "",
"PseudoGTIDPatternIsFixedSubstring": false,
"PseudoGTIDMonotonicHint": "asc:",
"DetectPseudoGTIDQuery": "",
"BinlogEventsChunkSize": 10000,
"SkipBinlogEventsContaining": [],
"ReduceReplicationAnalysisCount": true,
"FailureDetectionPeriodBlockMinutes": 60,
"RecoveryPeriodBlockSeconds": 3600,
"RecoveryIgnoreHostnameFilters": [],
"RecoverMasterClusterFilters": [
"*"
],
"RecoverIntermediateMasterClusterFilters": [
"*"
],
"OnFailureDetectionProcesses": [],
"PreFailoverProcesses": [],
"PostFailoverProcesses": [
"echo -e 'Failed server is {failedHost}:{failedPort}.\nSuccessed server is {successorHost}:{successorPort}.' | mail -s 'Complete Orchestrator Failover' yourname@sample.com"
],
"PostUnsuccessfulFailoverProcesses": [
"echo -e 'Failed server is {failedHost}:{failedPort}.' | mail -s 'Failed Orchestrator Failover' yourname@sample.com"
],
"PostMasterFailoverProcesses": [
"/usr/local/bin/detect_orchestrator_failover.py -u adminuser -p adminpassword -H {successorHost} -P {successorPort}"
],
"PostIntermediateMasterFailoverProcesses": [],
"CoMasterRecoveryMustPromoteOtherCoMaster": true,
"DetachLostSlavesAfterMasterFailover": true,
"ApplyMySQLPromotionAfterMasterFailover": true,
"MasterFailoverDetachSlaveMasterHost": false,
"MasterFailoverLostInstancesDowntimeMinutes": 0,
"PostponeSlaveRecoveryOnLagMinutes": 0
}
※adminuserは、レプリケーションクラスターに対してアクセス可能なsuperユーザとする。
ここでのポイントは、
"MySQLHostnameResolveMethod": "@@report_host"
"DetectClusterAliasQuery": "SELECT @@report_host"
である。
これにより、Orchestoratorはレプリケーションクラスターの状態取得をIPアドレスで行うことができるようになる。
この後、ひとまずOrechstoratorにレプリケーションクラスターのmasterノードを登録する。masterを登録しておけば、slaveも自動的に発見してくれる。
なお、登録方法は、WebGUIやらAPIなどであるが、ここでは割愛。
3.フェイルオーバー時のMariaDBパラメータの動的設定処理の配備
上記の設定の
"PostMasterFailoverProcesses"
の部分の
/usr/local/bin/detect_orchestrator_failover.py
を以下の感じで実装する。
なお、以下の処理は、masterのフェイルオーバー完了時に呼び出される。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import sys
import traceback
import datetime
import re
import argparse
import MySQLdb
parser = argparse.ArgumentParser(description = "detect orchestrator failover.")
parser.add_argument("-u", type=str, help = "(required) mysql user", required=True)
parser.add_argument("-p", type=str, help = "(required) mysql pass", required=True)
parser.add_argument("-H", type=str, help = "(required) master host", required=True)
parser.add_argument("-P", type=str, help = "(required) master port", required=True)
args = parser.parse_args()
mysql_user = args.u
mysql_pass = args.p
master_host = args.H
master_port = args.P
fp = None
master_conn = None
master_c = None
try:
# log
log_path = '/path_to_your_dir/detect_orchestrator_failover.log'
fp = open(log_path, 'a')
# connect master
master_conn = MySQLdb.connect(
user=mysql_user,
passwd=mysql_pass,
host=master_host,
port=int(master_port),
db='mysql'
)
master_c = master_conn.cursor(MySQLdb.cursors.DictCursor)
fp.write('[{}]new master is {}:{}.\n'.format(datetime.datetime.now(), master_host, master_port))
# set master
master_queries = []
master_queries.append('set global read_only = 0')
for sql in master_queries:
master_c.execute(sql)
fp.write('[{}]new master query is {}.\n'.format(datetime.datetime.now(), sql))
# get slaves
sql = "show slave hosts"
master_c.execute(sql)
rows = master_c.fetchall()
if isinstance(rows, tuple):
for row in rows:
slave_conn = None
slave_c = None
try:
slave_host = row['Host']
slave_port = row['Port']
# connect slave
slave_conn = MySQLdb.connect(
user=mysql_user,
passwd=mysql_pass,
host=slave_host,
port=int(slave_port),
db='mysql'
)
slave_c = slave_conn.cursor(MySQLdb.cursors.DictCursor)
fp.write('[{}]new slave is {}:{}.\n'.format(datetime.datetime.now(), slave_host, slave_port))
# set slave
slave_queries = []
slave_queries.append('set global read_only = 1')
for sql in slave_queries:
slave_c.execute(sql)
fp.write('[{}]new slave query is {}.\n'.format(datetime.datetime.now(), sql))
except:
fp.write('[{}]{}\n'.format(datetime.datetime.now(), traceback.format_exc()))
finally:
if slave_c is not None:
slave_c.close()
if slave_conn is not None:
slave_conn.close()
except:
fp.write('[{}]{}\n'.format(datetime.datetime.now(), traceback.format_exc()))
finally:
if master_c is not None:
master_c.close()
if master_conn is not None:
master_conn.close()
if fp is not None:
fp.close()
ここまでやっておくことにより、
- IPアドレスベースでOrchestorator上からレプリケーションクラスターの認識/操作が行われる
- フェイルオーバー時にslaveのread_onlyを1に変更できる
ということができる。
ちなみに、Orchestoratorでは、
masterのダウンに対する振舞のみがhookとして設定できるようなので、
slaveを追加した場合に自動的にread_onlyを設定するといったことは出来無いように見えます。(たぶん)
マニュアルが細かいので、利用の際はがんばってマニュアルを読んでみてください。
https://github.com/github/orchestrator/tree/master/docs
(参考)
https://qiita.com/rerorero/items/1f06cc8db9c469191289
https://www.s-style.co.jp/blog/2018/11/2875/以上