orchestrator+vip實(shí)現(xiàn)高可用
環(huán)境
系統(tǒng):CentOS 7.6
服務(wù)器
192.168.20.101 node1
192.168.20.102 node2
192.168.20.103 node3數(shù)據(jù)庫版本: MySQL 5.7.27 均已安裝
GTID 已開啟
log-slave-updates = ON
report_host最好配置上orchestrator 版本 : v3.1.4
MySQL主從配置略...肺魁,需注意設(shè)置主從時添加參數(shù)如下旅挤,優(yōu)化發(fā)現(xiàn)切換時間
change master to
master_host='192.168.20.101',
master_port=3306,
master_user='rpl',
master_password='123456',
master_auto_position=1,
MASTER_HEARTBEAT_PERIOD=2,
MASTER_CONNECT_RETRY=1,
MASTER_RETRY_COUNT=86400;
set global slave_net_timeout=8;
set global read_only=1;
set global super_read_only=1;
1-基礎(chǔ)配置
1.1-hosts配置
每臺機(jī)器分別添加hosts
echo '192.168.20.101 node1' >> /etc/hosts
echo '192.168.20.102 node2' >> /etc/hosts
echo '192.168.20.103 node3' >> /etc/hosts
1.2-配置ssh免密
所有機(jī)器執(zhí)行:
# 一路回車
ssh-keygen
ssh-copy-id node1
ssh-copy-id node2
ssh-copy-id node3
2-部署 orchestrator
2.1-下載
下載路徑:https://github.com/openark/orchestrator/releases
wget https://github.com/openark/orchestrator/releases/download/v3.1.4/orchestrator-3.1.4-1.x86_64.rpm
wget https://github.com/openark/orchestrator/releases/download/v3.1.4/orchestrator-client-3.1.4-1.x86_64.rpm
2.2-安裝
三臺機(jī)器都安裝 orchestrator的服務(wù)端和客戶端
# 安裝依賴
yum -y install jq
# 安裝
[root@node1 ~]# rpm -ivh orchestrator-3.1.4-1.x86_64.rpm
Preparing... ################################# [100%]
Updating / installing...
1:orchestrator-1:3.1.4-1 ################################# [100%]
[root@node1 ~]# rpm -ivh orchestrator-client-3.1.4-1.x86_64.rpm
Preparing... ################################# [100%]
Updating / installing...
1:orchestrator-client-1:3.1.4-1 ################################# [100%]
2.3-創(chuàng)建orchestrator管理用戶
# mysql 主庫上操作
mysql> CREATE USER 'orchestrator'@'192.168.20.%' IDENTIFIED BY '123456';
mysql> GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD ON *.* TO 'orchestrator'@'192.168.20.%';
mysql> GRANT SELECT ON mysql.slave_master_info TO 'orchestrator'@'192.168.20.%';
2.4-設(shè)置配置文件
cp /usr/local/orchestrator/orchestrator-sample-sqlite.conf.json /etc/orchestrator.conf.json
vi /etc/orchestrator.conf.json
修改如下幾個參數(shù):
- MySQLTopologyUser/MySQLTopologyPassword
檢測MySQL集群的用戶名/密碼 - SQLite3DataFile
SQLite庫存放路徑语稠,需要有寫的權(quán)限 - DefaultInstancePort
mysql 實(shí)例端口 - FailureDetectionPeriodBlockMinutes
在該時間內(nèi)再次出現(xiàn)故障,不會被多次發(fā)現(xiàn)扔仓。 - coveryPeriodBlockSeconds
在該時間內(nèi)再次出現(xiàn)故障蚕泽,不會進(jìn)行遷移冤寿,避免出現(xiàn)并發(fā)恢復(fù)和不穩(wěn)定哼鬓。 - RecoverMasterClusterFilters
只對匹配這些正則表達(dá)式模式的集群進(jìn)行主恢復(fù)(“*”模式匹配所有)。 - RecoverIntermediateMasterClusterFilters
只對匹配這些正則表達(dá)式模式的集群進(jìn)行主恢復(fù)(“*”模式匹配所有)博秫。 - PostFailoverProcesses
修改為腳本實(shí)際的存放路徑 - 添加Raft相關(guān)
Raft相關(guān)用于做orchestrator高可用 - RaftBind
修改為本機(jī)IP
{
"Debug": true,
"EnableSyslog": false,
"ListenAddress": ":3000",
"MySQLTopologyUser": "orchestrator",
"MySQLTopologyPassword": "123456",
"MySQLTopologyCredentialsConfigFile": "",
"MySQLTopologySSLPrivateKeyFile": "",
"MySQLTopologySSLCertFile": "",
"MySQLTopologySSLCAFile": "",
"MySQLTopologySSLSkipVerify": true,
"MySQLTopologyUseMutualTLS": false,
"BackendDB": "sqlite",
"SQLite3DataFile": "/usr/local/orchestrator/orchestrator.db",
"MySQLConnectTimeoutSeconds": 1,
"DefaultInstancePort": 3306,
"DiscoverByShowSlaveHosts": true,
"InstancePollSeconds": 5,
"DiscoveryIgnoreReplicaHostnameFilters": [
"a_host_i_want_to_ignore[.]example[.]com",
".*[.]ignore_all_hosts_from_this_domain[.]example[.]com",
"a_host_with_extra_port_i_want_to_ignore[.]example[.]com:3307"
],
"UnseenInstanceForgetHours": 240,
"SnapshotTopologiesIntervalHours": 0,
"InstanceBulkOperationsWaitTimeoutSeconds": 10,
"HostnameResolveMethod": "default",
"MySQLHostnameResolveMethod": "@@hostname",
"SkipBinlogServerUnresolveCheck": true,
"ExpiryHostnameResolvesMinutes": 60,
"RejectHostnameResolvePattern": "",
"ReasonableReplicationLagSeconds": 10,
"ProblemIgnoreHostnameFilters": [],
"VerifyReplicationFilters": false,
"ReasonableMaintenanceReplicationLagSeconds": 20,
"CandidateInstanceExpireMinutes": 60,
"AuditLogFile": "",
"AuditToSyslog": false,
"RemoveTextFromHostnameDisplay": ".mydomain.com:3306",
"ReadOnly": false,
"AuthenticationMethod": "",
"HTTPAuthUser": "",
"HTTPAuthPassword": "",
"AuthUserHeader": "",
"PowerAuthUsers": [
"*"
],
"ClusterNameToAlias": {
"127.0.0.1": "test suite"
},
"ReplicationLagQuery": "",
"DetectClusterAliasQuery": "SELECT SUBSTRING_INDEX(@@hostname, '.', 1)",
"DetectClusterDomainQuery": "",
"DetectInstanceAliasQuery": "",
"DetectPromotionRuleQuery": "",
"DataCenterPattern": "[.]([^.]+)[.][^.]+[.]mydomain[.]com",
"PhysicalEnvironmentPattern": "[.]([^.]+[.][^.]+)[.]mydomain[.]com",
"PromotionIgnoreHostnameFilters": [],
"DetectSemiSyncEnforcedQuery": "",
"ServeAgentsHttp": false,
"AgentsServerPort": ":3001",
"AgentsUseSSL": false,
"AgentsUseMutualTLS": false,
"AgentSSLSkipVerify": false,
"AgentSSLPrivateKeyFile": "",
"AgentSSLCertFile": "",
"AgentSSLCAFile": "",
"AgentSSLValidOUs": [],
"UseSSL": false,
"UseMutualTLS": false,
"SSLSkipVerify": false,
"SSLPrivateKeyFile": "",
"SSLCertFile": "",
"SSLCAFile": "",
"SSLValidOUs": [],
"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": 5,
"RecoveryPeriodBlockSeconds": 30,
"RecoveryIgnoreHostnameFilters": [],
"RecoverMasterClusterFilters": [
"*"
],
"RecoverIntermediateMasterClusterFilters": [
"*"
],
"OnFailureDetectionProcesses": [
"echo '`date +'%Y-%m-%d %T'` Detected {failureType} on {failureCluster}. Affected replicas: {countSlaves}' >> /tmp/recovery.log"
],
"PreGracefulTakeoverProcesses": [
"echo '`date +'%Y-%m-%d %T'` Planned takeover about to take place on {failureCluster}. Master will switch to read_only' >> /tmp/recovery.log"
],
"PreFailoverProcesses": [
"echo '`date +'%Y-%m-%d %T'` Will recover from {failureType} on {failureCluster}' >> /tmp/recovery.log"
],
"PostFailoverProcesses": [
"echo '`date +'%Y-%m-%d %T'` (for all types) Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}; failureClusterAlias:{failureClusterAlias}' >> /tmp/recovery.log",
"/usr/local/orchestrator/orch_hook.sh {failureType} {failureClusterAlias} {failedHost} {successorHost} >> /tmp/orch.log"
],
"PostUnsuccessfulFailoverProcesses": [ "echo '`date +'%Y-%m-%d %T'` Unsuccessful Failover ' >> /tmp/recovery.log"],
"PostMasterFailoverProcesses": [
"echo '`date +'%Y-%m-%d %T'` Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Promoted: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostIntermediateMasterFailoverProcesses": [
"echo '`date +'%Y-%m-%d %T'` Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostGracefulTakeoverProcesses": [
"echo '`date +'%Y-%m-%d %T'` Planned takeover complete' >> /tmp/recovery.log"
],
"CoMasterRecoveryMustPromoteOtherCoMaster": true,
"DetachLostSlavesAfterMasterFailover": true,
"ApplyMySQLPromotionAfterMasterFailover": true,
"PreventCrossDataCenterMasterFailover": false,
"PreventCrossRegionMasterFailover": false,
"MasterFailoverDetachReplicaMasterHost": false,
"MasterFailoverLostInstancesDowntimeMinutes": 0,
"PostponeReplicaRecoveryOnLagMinutes": 0,
"OSCIgnoreHostnameFilters": [],
"GraphiteAddr": "",
"GraphitePath": "",
"GraphiteConvertHostnameDotsToUnderscores": true,
"ConsulAddress": "",
"ConsulAclToken": "",
"RaftEnabled":true,
"RaftDataDir":"/usr/local/orchestrator",
"RaftBind":"192.168.20.101",
"DefaultRaftPort":10008,
"RaftNodes":[
"192.168.20.101",
"192.168.20.102",
"192.168.20.103"
]
}
2.5-配置文件復(fù)制到其他機(jī)器上去
scp /etc/orchestrator.conf.json root@node2:/etc/orchestrator.conf.json
scp /etc/orchestrator.conf.json root@node3:/etc/orchestrator.conf.json
修改最后的 "RaftBind":"192.168.20.101",
的地址為本機(jī)地址
2.6-VIP切換腳本創(chuàng)建
所有服務(wù)器均創(chuàng)建潦牛,建議創(chuàng)建一個后復(fù)制過去改下
/usr/local/orchestrator/orch_hook.sh
/usr/local/orchestrator/orch_vip.sh
orch_hook.sh
可能需要修改:
- 注意腳本路徑當(dāng)前為:/usr/local/orchestrator/orch_vip.sh
- array=( ens32 "192.168.20.111" root "192.168.20.101")
對應(yīng)值為: 網(wǎng)卡名稱 VIP地址 ssh用戶名 本機(jī)IP - MYSQL_PWD 忽略
[root@node1 orchestrator]# cat orch_hook.sh
#!/bin/bash
isitdead=$1
cluster=$2
oldmaster=$3
newmaster=$4
mysqluser="orchestrator"
export MYSQL_PWD="xxxpassxxx"
logfile="/var/log/orch_hook.log"
# list of clusternames
#clusternames=(rep blea lajos)
# clustername=( interface IP user Inter_IP)
#rep=( ens32 "192.168.56.121" root "192.168.56.125")
if [[ $isitdead == "DeadMaster" ]]; then
array=( ens32 "192.168.20.111" root "192.168.20.101")
interface=${array[0]}
IP=${array[1]}
user=${array[2]}
if [ ! -z ${IP} ] ; then
echo $(date)
echo "Revocering from: $isitdead"
echo "New master is: $newmaster"
echo "/usr/local/orchestrator/orch_vip.sh -d 1 -n $newmaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster" | tee $logfile
/usr/local/orchestrator/orch_vip.sh -d 1 -n $newmaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster
#mysql -h$newmaster -u$mysqluser < /usr/local/bin/orch_event.sql
else
echo "Cluster does not exist!" | tee $logfile
fi
elif [[ $isitdead == "DeadIntermediateMasterWithSingleSlaveFailingToConnect" ]]; then
array=( ens32 "192.168.20.111" root "192.168.20.101")
interface=${array[0]}
IP=${array[3]}
user=${array[2]}
slavehost=`echo $5 | cut -d":" -f1`
echo $(date)
echo "Revocering from: $isitdead"
echo "New intermediate master is: $slavehost"
echo "/usr/local/orchestrator/orch_vip.sh -d 1 -n $slavehost -i ${interface} -I ${IP} -u ${user} -o $oldmaster" | tee $logfile
/usr/local/orchestrator/orch_vip.sh -d 1 -n $slavehost -i ${interface} -I ${IP} -u ${user} -o $oldmaster
elif [[ $isitdead == "DeadIntermediateMaster" ]]; then
array=( ens32 "192.168.20.111" root "192.168.20.101")
interface=${array[0]}
IP=${array[3]}
user=${array[2]}
slavehost=`echo $5 | sed -E "s/:[0-9]+//g" | sed -E "s/,/ /g"`
showslave=`mysql -h$newmaster -u$mysqluser -sN -e "SHOW SLAVE HOSTS;" | awk '{print $2}'`
newintermediatemaster=`echo $slavehost $showslave | tr ' ' '\n' | sort | uniq -d`
echo $(date)
echo "Revocering from: $isitdead"
echo "New intermediate master is: $newintermediatemaster"
echo "/usr/local/orchestrator/orch_vip.sh -d 1 -n $newintermediatemaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster" | tee $logfile
/usr/local/orchestrator/orch_vip.sh -d 1 -n $newintermediatemaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster
fi
orch_vip.sh
需要發(fā)郵件可以修改emailaddress
的地址,并將 sendmail
改為 1
[root@node1 orchestrator]# cat orch_vip.sh
#!/bin/bash
emailaddress="email@example.com"
sendmail=0
function usage {
cat << EOF
usage: $0 [-h] [-d master is dead] [-o old master ] [-s ssh options] [-n new master] [-i interface] [-I] [-u SSH user]
OPTIONS:
-h Show this message
-o string Old master hostname or IP address
-d int If master is dead should be 1 otherweise it is 0
-s string SSH options
-n string New master hostname or IP address
-i string Interface exmple eth0:1
-I string Virtual IP
-u string SSH user
EOF
}
while getopts ho:d:s:n:i:I:u: flag; do
case $flag in
o)
orig_master="$OPTARG";
;;
d)
isitdead="${OPTARG}";
;;
s)
ssh_options="${OPTARG}";
;;
n)
new_master="$OPTARG";
;;
i)
interface="$OPTARG";
;;
I)
vip="$OPTARG";
;;
u)
ssh_user="$OPTARG";
;;
h)
usage;
exit 0;
;;
*)
usage;
exit 1;
;;
esac
done
if [ $OPTIND -eq 1 ]; then
echo "No options were passed";
usage;
fi
shift $(( OPTIND - 1 ));
# discover commands from our path
ssh=$(which ssh)
arping=$(which arping)
ip2util=$(which ip)
# command for adding our vip
cmd_vip_add="sudo -n $ip2util address add ${vip} dev ${interface}"
# command for deleting our vip
cmd_vip_del="sudo -n $ip2util address del ${vip}/32 dev ${interface}"
# command for discovering if our vip is enabled
cmd_vip_chk="sudo -n $ip2util address show dev ${interface} to ${vip%/*}/32"
# command for sending gratuitous arp to announce ip move
cmd_arp_fix="sudo -n $arping -c 1 -I ${interface} ${vip%/*} "
# command for sending gratuitous arp to announce ip move on current server
cmd_local_arp_fix="sudo -n $arping -c 1 -I ${interface} ${vip%/*} "
vip_stop() {
rc=0
# ensure the vip is removed
$ssh ${ssh_options} -tt ${ssh_user}@${orig_master} \
"[ -n \"\$(${cmd_vip_chk})\" ] && ${cmd_vip_del} && sudo ${ip2util} route flush cache || [ -z \"\$(${cmd_vip_chk})\" ]"
rc=$?
return $rc
}
vip_start() {
rc=0
# ensure the vip is added
# this command should exit with failure if we are unable to add the vip
# if the vip already exists always exit 0 (whether or not we added it)
$ssh ${ssh_options} -tt ${ssh_user}@${new_master} \
"[ -z \"\$(${cmd_vip_chk})\" ] && ${cmd_vip_add} && ${cmd_arp_fix} || [ -n \"\$(${cmd_vip_chk})\" ]"
rc=$?
$cmd_local_arp_fix
return $rc
}
vip_status() {
$arping -c 1 -I ${interface} ${vip%/*}
if ping -c 1 -W 1 "$vip"; then
return 0
else
return 1
fi
}
if [[ $isitdead == 0 ]]; then
echo "Online failover"
if vip_stop; then
if vip_start; then
echo "$vip is moved to $new_master."
if [ $sendmail -eq 1 ]; then mail -s "$vip is moved to $new_master." "$emailaddress" < /dev/null &> /dev/null ; fi
else
echo "Can't add $vip on $new_master!"
if [ $sendmail -eq 1 ]; then mail -s "Can't add $vip on $new_master!" "$emailaddress" < /dev/null &> /dev/null ; fi
exit 1
fi
else
echo $rc
echo "Can't remove the $vip from orig_master!"
if [ $sendmail -eq 1 ]; then mail -s "Can't remove the $vip from orig_master!" "$emailaddress" < /dev/null &> /dev/null ; fi
exit 1
fi
elif [[ $isitdead == 1 ]]; then
echo "Master is dead, failover"
# make sure the vip is not available
if vip_status; then
if vip_stop; then
if [ $sendmail -eq 1 ]; then mail -s "$vip is removed from orig_master." "$emailaddress" < /dev/null &> /dev/null ; fi
else
if [ $sendmail -eq 1 ]; then mail -s "Couldn't remove $vip from orig_master." "$emailaddress" < /dev/null &> /dev/null ; fi
exit 1
fi
fi
if vip_start; then
echo "$vip is moved to $new_master."
if [ $sendmail -eq 1 ]; then mail -s "$vip is moved to $new_master." "$emailaddress" < /dev/null &> /dev/null ; fi
else
echo "Can't add $vip on $new_master!"
if [ $sendmail -eq 1 ]; then mail -s "Can't add $vip on $new_master!" "$emailaddress" < /dev/null &> /dev/null ; fi
exit 1
fi
else
echo "Wrong argument, the master is dead or live?"
fi
2.7-設(shè)置VIP
僅在master節(jié)點(diǎn)上創(chuàng)建VIP
ip addr add 192.168.20.111 dev ens32
# 刪除 ip addr del 192.168.20.111 dev ens32
2.8-啟動orchestrator
所有機(jī)器啟動
cd /usr/local/orchestrator && nohup ./orchestrator --config=/etc/orchestrator.conf.json http &
2.9-設(shè)置環(huán)境變量
因?yàn)榕渲昧薘aft挡育,有多個Orchestrator巴碗,所以需要ORCHESTRATOR_API的環(huán)境變量,orchestrator-client會自動選擇leader即寒。
所有機(jī)器執(zhí)行 vi /etc/profile
# 在最后添加
export ORCHESTRATOR_API="node1:3000/api node2:3000/api node3:3000/api"
# 添加完成后source生效
source /etc/profile
2.10-發(fā)現(xiàn)拓?fù)?/h3>
# 任意服務(wù)器上執(zhí)行橡淆,發(fā)現(xiàn)leader在哪
[root@node2 ~]# orchestrator-client -c which-api
node1:3000/api
# 在任意服務(wù)器上執(zhí)行
[root@node2 ~]# orchestrator-client -c discover -i 192.168.20.101:3306
node1:3306
image.png
# 任意服務(wù)器上執(zhí)行橡淆,發(fā)現(xiàn)leader在哪
[root@node2 ~]# orchestrator-client -c which-api
node1:3000/api
# 在任意服務(wù)器上執(zhí)行
[root@node2 ~]# orchestrator-client -c discover -i 192.168.20.101:3306
node1:3306
展開
3-測試
3.1-kill或關(guān)閉mysql
結(jié)果會自動進(jìn)行切換召噩,IP自動漂移
3.2-直接poweroff掉master服務(wù)器
結(jié)果會自動進(jìn)行切換,IP自動漂移
3.3-恢復(fù)
change master to master_host='192.168.20.101',master_port=3306,master_user='orchestrator',master_password='123456',master_auto_position=1,MASTER_HEARTBEAT_PERIOD=2,MASTER_CONNECT_RETRY=1,MASTER_RETRY_COUNT=86400;
set global slave_net_timeout=8;
start slave;
show slave status\G
4.1-查看拓?fù)?/h3>
# 任意一個節(jié)點(diǎn)
[root@node1 orchestrator]# orchestrator-client -c topology -i node2
node1:3306 [0s,ok,5.7.27-log,rw,ROW,>>,GTID]
+ node2:3306 [0s,ok,5.7.27-log,ro,ROW,>>,GTID]
+ node3:3306 [0s,ok,5.7.27-log,ro,ROW,>>,GTID]
4.2-設(shè)置為只讀模式/讀寫模式
# 設(shè)置node2為只讀模式
orchestrator-client -c set-read-only -i node2
# 設(shè)置node2為讀寫模式
orchestrator-client -c set-writeable -i node2
4.3-優(yōu)雅的進(jìn)行主和指定從切換
# 提升node2為master逸爵,原主node1需要手動去執(zhí)行 start slave
orchestrator-client -c graceful-master-takeover -a node1:3306 -d node2:3306
原結(jié)構(gòu):
node1:3306 [0s,ok,5.7.27-log,rw,ROW,>>,GTID]
+ node2:3306 [0s,ok,5.7.27-log,ro,ROW,>>,GTID]
+ node3:3306 [0s,ok,5.7.27-log,ro,ROW,>>,GTID]
變更后結(jié)構(gòu):
node2:3306 [0s,ok,5.7.27-log,rw,ROW,>>,GTID]
- node1:3306 [null,nonreplicating,5.7.27-log,ro,ROW,>>,GTID,downtimed] # 需要手動啟動slave
+ node3:3306 [0s,ok,5.7.27-log,ro,ROW,>>,GTID]
參考:
# 任意一個節(jié)點(diǎn)
[root@node1 orchestrator]# orchestrator-client -c topology -i node2
node1:3306 [0s,ok,5.7.27-log,rw,ROW,>>,GTID]
+ node2:3306 [0s,ok,5.7.27-log,ro,ROW,>>,GTID]
+ node3:3306 [0s,ok,5.7.27-log,ro,ROW,>>,GTID]
# 設(shè)置node2為只讀模式
orchestrator-client -c set-read-only -i node2
# 設(shè)置node2為讀寫模式
orchestrator-client -c set-writeable -i node2
# 提升node2為master逸爵,原主node1需要手動去執(zhí)行 start slave
orchestrator-client -c graceful-master-takeover -a node1:3306 -d node2:3306
原結(jié)構(gòu):
node1:3306 [0s,ok,5.7.27-log,rw,ROW,>>,GTID]
+ node2:3306 [0s,ok,5.7.27-log,ro,ROW,>>,GTID]
+ node3:3306 [0s,ok,5.7.27-log,ro,ROW,>>,GTID]
變更后結(jié)構(gòu):
node2:3306 [0s,ok,5.7.27-log,rw,ROW,>>,GTID]
- node1:3306 [null,nonreplicating,5.7.27-log,ro,ROW,>>,GTID,downtimed] # 需要手動啟動slave
+ node3:3306 [0s,ok,5.7.27-log,ro,ROW,>>,GTID]
https://www.cnblogs.com/zhoujinyi/p/10394389.html
https://github.com/openark/orchestrator
https://github.com/theTibi/orchestrator_vip
附錄參數(shù)注釋:
{
"Debug": true, #debug模式具滴,輸出詳細(xì)信息
"EnableSyslog": false, #是否輸出到系統(tǒng)日志里
"ListenAddress": ":3000", #orch監(jiān)聽的端口,web端口
"MySQLTopologyUser": "orchestrator", #后端被管理的集群賬號:所有實(shí)例都要有
"MySQLTopologyPassword": "123456", #后端被管理的集群密碼
"MySQLTopologyCredentialsConfigFile": "", #后端集群的用戶密碼配置文件师倔,賬號密碼可以直接寫入文件构韵,讀取
"MySQLTopologySSLPrivateKeyFile": "", #SSL相關(guān)
"MySQLTopologySSLCertFile": "",
"MySQLTopologySSLCAFile": "", #證書相關(guān)
"MySQLTopologySSLSkipVerify": true, #跳過SSL驗(yàn)證
"MySQLTopologyUseMutualTLS": false, #是否使用TLS驗(yàn)證
"BackendDB": "sqlite", # 后臺庫類型
"SQLite3DataFile": "/usr/local/orchestrator/orchestrator.db", # 數(shù)據(jù)文件存放路徑
"MySQLConnectTimeoutSeconds": 1, #orch連接MySQL超時秒數(shù)
"DefaultInstancePort": 3306, #mysql 集群實(shí)例端口
"DiscoverByShowSlaveHosts": true, #是否使用show slave hosts自動發(fā)現(xiàn)集群
"InstancePollSeconds": 5, #使用show slave hosts 探測間隔秒數(shù)
"DiscoveryIgnoreReplicaHostnameFilters": [
"a_host_i_want_to_ignore[.]example[.]com",
".*[.]ignore_all_hosts_from_this_domain[.]example[.]com",
"a_host_with_extra_port_i_want_to_ignore[.]example[.]com:3307"
],
"UnseenInstanceForgetHours": 240, #忽略不可見的實(shí)例的小時數(shù)
"SnapshotTopologiesIntervalHours": 0, #快照拓?fù)湔{(diào)用之間的小時間隔。默認(rèn):0(表示禁用)
"InstanceBulkOperationsWaitTimeoutSeconds": 10, #執(zhí)行批量操作時趋艘,在單個實(shí)例上等待的時間
"HostnameResolveMethod": "default", #解析主機(jī)名疲恢,默認(rèn)使用主機(jī)名:default;不解析為none瓷胧,直接用IP
"MySQLHostnameResolveMethod": "@@hostname", #解析主機(jī)名显拳,發(fā)出select @@hostname或發(fā)出select @@report_host(需要配置report_host);不解析用""搓萧,直接用IP杂数。
"SkipBinlogServerUnresolveCheck": true, #跳過檢查 將未解析的主機(jī)名解析為和binlog服務(wù)器相同的主機(jī)名
"ExpiryHostnameResolvesMinutes": 60, #域名檢測過期周期(分鐘)
"RejectHostnameResolvePattern": "", #禁止使用正則表達(dá)式表示域名
"ReasonableReplicationLagSeconds": 10, #復(fù)制延遲高于10S表示異常
"ProblemIgnoreHostnameFilters": [], #將主機(jī)做正則匹配篩選成最小化
"VerifyReplicationFilters": false, #在拓?fù)渲貥?gòu)之前檢查復(fù)制篩選器
"ReasonableMaintenanceReplicationLagSeconds": 20, #復(fù)制延遲高于該值會上下移動調(diào)整MySQL拓?fù)? "CandidateInstanceExpireMinutes": 60, #該時間之后,使用實(shí)例作為候選從庫(在主故障轉(zhuǎn)移時提升)的建議到期
"AuditLogFile": "", #審計日志矛绘,空的時候禁用
"AuditToSyslog": false, #審計日志是否寫入到系統(tǒng)日志
"RemoveTextFromHostnameDisplay": ".mydomain.com:3306", #去除集群的文本
"ReadOnly": false, #全局只讀
"AuthenticationMethod": "", #身份驗(yàn)證類型
"HTTPAuthUser": "", #http驗(yàn)證用戶名
"HTTPAuthPassword": "",
"AuthUserHeader": "",
"PowerAuthUsers": [
"*"
],
"ClusterNameToAlias": { #正則表達(dá)式匹配集群名稱和別名之間的映射
"127.0.0.1": "test suite"
},
"ReplicationLagQuery": "",
"DetectClusterAliasQuery": "SELECT SUBSTRING_INDEX(@@hostname, '.', 1)", #查詢集群別名
"DetectClusterDomainQuery": "", #可選查詢耍休,返回集群主服務(wù)器的VIP/別名/域名刃永。
"DetectInstanceAliasQuery": "", #可選查詢货矮,返回實(shí)例的別名
"DetectPromotionRuleQuery": "", #可選查詢,返回實(shí)例的提升規(guī)則
"DataCenterPattern": "[.]([^.]+)[.][^.]+[.]mydomain[.]com", #從主機(jī)名稱中提取數(shù)據(jù)中心名稱
"PhysicalEnvironmentPattern": "[.]([^.]+[.][^.]+)[.]mydomain[.]com", #從主機(jī)名中提取物理環(huán)境信息
"PromotionIgnoreHostnameFilters": [], #不使用主機(jī)名匹配模式來提升副本
"DetectSemiSyncEnforcedQuery": "", #檢測是否強(qiáng)制半同步
"ServeAgentsHttp": false, #產(chǎn)生一個專用于orche-client的HTTP端口
"AgentsServerPort": ":3001", #可選斯够,對于raft設(shè)置囚玫,此節(jié)點(diǎn)將向其他節(jié)點(diǎn)通告HTTP的地址
"AgentsUseSSL": false, #當(dāng)為true時,orch將使用SSL偵聽代理端口已經(jīng)通過SSL連接的代理
"AgentsUseMutualTLS": false, #當(dāng)為true時读规,使用TLS服務(wù)器與代理通信
"AgentSSLSkipVerify": false, #為代理使用SSL
"AgentSSLPrivateKeyFile": "",
"AgentSSLCertFile": "",
"AgentSSLCAFile": "",
"AgentSSLValidOUs": [],
"UseSSL": false, #在服務(wù)器WEB端口上使用SSL
"UseMutualTLS": false, #true時使用TLS作為服務(wù)器的WEB和API連接
"SSLSkipVerify": false,
"SSLPrivateKeyFile": "",
"SSLCertFile": "",
"SSLCAFile": "",
"SSLValidOUs": [],
"URLPrefix": "", #在非跟web路徑上運(yùn)行orch的URL前綴
"StatusEndpoint": "/api/status", #狀態(tài)查看
"StatusSimpleHealth": true,
"StatusOUVerify": false,
"AgentPollMinutes": 60, #代理之間輪詢的分鐘數(shù)
"UnseenAgentForgetHours": 6, #忘記不可見代理的小時數(shù)
"StaleSeedFailMinutes": 60, #無進(jìn)展60分鐘后被認(rèn)為失敗
"SeedAcceptableBytesDiff": 8192, #種子源和目標(biāo)源數(shù)據(jù)大小的字節(jié)差異仍被視為成功復(fù)制
"PseudoGTIDPattern": "", #為空時抓督,禁用基于偽GTID的重構(gòu)
"PseudoGTIDPatternIsFixedSubstring": false, #如為TRUE,則上個參數(shù)不被視為正則表達(dá)式而被視為固定子字符串
"PseudoGTIDMonotonicHint": "asc:",
"DetectPseudoGTIDQuery": "", #可選查詢束亏,用于決定是否在實(shí)例上啟用偽GTID
"BinlogEventsChunkSize": 10000, #show binlog events 塊的大小铃在。較小意味著更少的鎖定和工作要做
"SkipBinlogEventsContaining": [], #掃描/比較Pseudo-GTID的binlog 時,跳過包含給定文本的條目碍遍。這些不是正則表達(dá)式(掃描binlog時會消耗太多的CPU)定铜,只需查找子字符串
"ReduceReplicationAnalysisCount": true, #如果為true,則復(fù)制分析將報告可能首先處理問題的可能性的實(shí)例怕敬。 如果為false揣炕,則為每個已知實(shí)例提供一個條目
"FailureDetectionPeriodBlockMinutes": 10, #在該時間內(nèi)再次出現(xiàn)故障,不會被再次發(fā)現(xiàn)
"RecoveryPeriodBlockSeconds": 30, #在該時間內(nèi)再次出現(xiàn)故障东跪,不會進(jìn)行failover畸陡,避免出現(xiàn)并發(fā)恢復(fù)和不穩(wěn)定
"RecoveryIgnoreHostnameFilters": [], #恢復(fù)會忽略的主機(jī)
"RecoverMasterClusterFilters": [ #只對能匹配這些正則表達(dá)式模式的集群進(jìn)行主故障恢復(fù)
"*"
],
"RecoverIntermediateMasterClusterFilters": [ #只對能匹配這些正則表達(dá)式模式的集群進(jìn)行主故障恢復(fù)(“*”模式匹配所有)
"*"
],
"OnFailureDetectionProcesses": [ #檢測到主故障時執(zhí)行的命令和腳本
"echo 'Detected {failureType} on {failureCluster}. Affected replicas: {countSlaves}' >> /tmp/recovery.log"
],
"PreGracefulTakeoverProcesses": [ #在執(zhí)行故障轉(zhuǎn)移之前執(zhí)行的命令和腳本
"echo 'Planned takeover about to take place on {failureCluster}. Master will switch to read_only' >> /tmp/recovery.log"
],
"PreFailoverProcesses": [ #執(zhí)行恢復(fù)操作前執(zhí)行
"echo 'Will recover from {failureType} on {failureCluster}' >> /tmp/recovery.log"
],
"PostFailoverProcesses": [ #在failover全部成功后執(zhí)行
"echo '(for all types) Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostUnsuccessfulFailoverProcesses": [], #在failover失敗后執(zhí)行
"PostMasterFailoverProcesses": [ #在主恢復(fù)成功結(jié)束時執(zhí)行
"echo 'Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Promoted: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostIntermediateMasterFailoverProcesses": [ #在中間主成功恢復(fù)結(jié)束時執(zhí)行
"echo 'Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostGracefulTakeoverProcesses": [ #在新主晉升之后執(zhí)行
"echo 'Planned takeover complete' >> /tmp/recovery.log"
],
"CoMasterRecoveryMustPromoteOtherCoMaster": true, #當(dāng)false時鹰溜,任何實(shí)例都可以得到提升;當(dāng)true時丁恭,將提升共同主人曹动,否則失敗
"DetachLostSlavesAfterMasterFailover": true, #恢復(fù)過程中可能會丟失一些副本。如果為true牲览,將通過detach-replica命令強(qiáng)制中斷其復(fù)制仁期,并認(rèn)為它們不正常運(yùn)行。
"ApplyMySQLPromotionAfterMasterFailover": true, #在主上執(zhí)行reset slave all竭恬,并設(shè)置read_only=0
"PreventCrossDataCenterMasterFailover": false, #如果為true(默認(rèn)值:false)跛蛋,則不允許跨DC主故障轉(zhuǎn)移,orchestrator將盡其所能僅在同一DC內(nèi)進(jìn)行故障轉(zhuǎn)移痊硕,否則不進(jìn)行故障轉(zhuǎn)移赊级。
"PreventCrossRegionMasterFailover": false,
"MasterFailoverDetachReplicaMasterHost": false,
"MasterFailoverLostInstancesDowntimeMinutes": 0, #主故障轉(zhuǎn)移后丟失的服務(wù)器停機(jī)的分鐘數(shù)(包括失敗的主和丟失的從)。0表示禁用
"PostponeReplicaRecoveryOnLagMinutes": 0, #在崩潰恢復(fù)時岔绸,延遲超過給定分鐘的從庫在主被選出后才復(fù)活理逊。 值為0將禁用此功能。
"OSCIgnoreHostnameFilters": [],
"GraphiteAddr": "",
"GraphitePath": "",
"GraphiteConvertHostnameDotsToUnderscores": true,
"ConsulAddress": "",
"ConsulAclToken": "", # 這里的逗號需要注意
# 在最后添加上盒揉,此配置用于高可用晋被,注意上面一行要加上逗號
"RaftEnabled":true,
"RaftDataDir":"/usr/local/orchestrator",
"RaftBind":"192.168.20.101", # 根據(jù)本機(jī)IP更改
"DefaultRaftPort":10008, # 端口所有機(jī)器上得保持一致
"RaftNodes":[
"192.168.20.101",
"192.168.20.102",
"192.168.20.103"
]