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/以上
コメントがあればどうぞ