MHA是一套MySQL高可用管理軟體,除了檢測Master當機後,提升候選Slave為New Master之外(漂虛拟IP),還會自動讓其他Slave與New Master 建立複制關系。MHA Manager可以單獨部署在一台獨立的機器上,并管理多個master-slave叢集。當自動Failover完成後,MHA Manager伺服器上的masterha_manager 程序自動退出。(Currently MHA Manager process does not run as a daemon. If failover completed successfully or the master process was killed by accident, the manager stops working. --官方文檔)
面臨的問題
我們知道開啟MHA Manager監控,當MHA 發生自動漂移時,會将老的主庫的ip将會從配置檔案中移除。那麼怎麼可以自動将原Master 節點自動以Slave角色添加到叢集中來是運維同學面臨的問題。
并且大多數情況下,MHA FailOver 後,MHA Manager 監控程序也會關閉。是以很有必要再開啟一個關于MHA Manager的保護程序。
背景知識
為簡化MHA 配置,測試環境由一主一從一監控構成。

注意:主節點、輔助節點 之間 互相SSH 免密碼登入。MHA Manger 到主、副節點之間 需要滿足免密碼登入(滿足單向即可)
在主節點上虛拟出了 可讀/寫的IP;在從節點上虛拟出隻讀的IP。程式通路使用虛拟IP。
工具包主要功能
工具包 | 功能描述 |
masterha_check_ssh | 檢查MHA的SSH配置狀況 |
masterha_check_repl | 檢查MySQL各節點複制狀态 |
masterha_manger | 開啟 MHA Manager |
masterha_check_status | 檢測目前MHA Manager運作狀态 |
master_ip_failover | 自動切換時管理vip的腳本,主要是VIP的漂移。 |
master_ip_online_change | 手動執行mysql master switchover時執行的切換腳本,含有管理vip的腳本 |
masterha_master_switch | 控制故障轉移(可手動) |
安裝MHA Manager軟體包後,路徑/usr/local/bin上會出現以上工具包。
解決方案探究
腳本主要解決的問題
實作功能的檔案及描述
主要檔案mha_health_check_secondary.sh的處理邏輯
實作代碼
檔案mha_protect.sh的主要代碼
1 ########################################################################
2 # File Name: mha_protect.sh
3 # Excute: nohup sh mha_protect.sh &
4 # Created Time: Thu Jul 12 EST 2018
5 #########################################################################
6 #!/bin/sh
7 while true;
8 do
9 mha_check_result=`masterha_check_status --conf=/etc/masterha/app1.conf | grep "stopped" | wc -l`
10 if [ "$mha_check_result" == "1" ];then
11 echo "$mha_check_result"
12 sh /etc/masterha/mha_health_check_vip.sh > /etc/masterha/mhalog/MHA_Check_`date "+%Y%m%d%H%M%S"`.log 2>&1
13 fi
14
15 sleep 20
16 done
此檔案中,調用MHA的配置檔案的參數為 /etc/masterha/app1.conf。執行mha_health_check_secondary.sh産生的log位于路徑 /etc/masterha/mhalog下面,檔案以MHA_Check_時間命名。
檔案mha_health_check_secondary.sh 中的主要代碼
1 #!/bin/bash
2
3 server1="172.XXX.XXX.XXX" ##此處請輸入Server1的IP
4 server2="172.XXX.XXX.XXX" ##此處請輸入Server2的IP
5 vip="172.XXX.XXX.XXX" ##此處請輸入已配置的VIP
6 mysql_username=使用者 ##此處資料使用者名
7 mysql_password=密碼 ## 此處輸入使用者名相應的密碼
8
9 mha_conf=/etc/masterha/app1.conf
10 # Part:: String SQL
11 sql_change_master=""
12 mysql_status=""
13 slave_status=""
14 master_status=""
15
16 #if has vip , master server ip
17 ipaddr1=`ssh root@"$server1" ip addr | grep "inet 172" | awk -F '[/]' '{print $1}' | awk '{print $2}' | grep "$vip"`
18 ipaddr2=`ssh root@"$server2" ip addr | grep "inet 172" | awk -F '[/]' '{print $1}' | awk '{print $2}' | grep "$vip"`
19
20 ###此處應該添加一個判斷當 ipaddr1 和 ipaddr2 都為 空時,說明,VIP設定有問題,退出需要告知管理者,去檢查
21
22 if [ "$ipaddr1" = "$vip" ];then
23 masterip=$server1
24 echo masterip 在server1 $server1 上
25 fi
26 if [ "$ipaddr2" = "$vip" ];then
27 masterip=$server2
28 echo masterip 在server2 $server2 上
29 fi
30
31 echo "master ip: $masterip"
32
33 ## start ## 檢視app1.conf mha 配置檔案server的資訊
34 conf_server1=`grep "server1" $mha_conf`
35 conf_server2=`grep "server2" $mha_conf`
36
37
38 echo "conf_server1: $conf_server1 conf_server2 :$conf_server2 "
39 ## end ## 檢視app1.conf mha 配置檔案server的資訊
40
41 # 生成master mysql的[change master]SQL指令
42 sql_change_master="CHANGE MASTER TO MASTER_HOST='$masterip', MASTER_USER='$mysql_username', MASTER_PASSWORD='$mysql_password',MASTER_PORT=3306,MASTER_AUTO_POSITION=1;"
43
44 # --------------------------
45 # function
46
47 # 對指定主機執行Linux指令
48 function do_linux_by_ssh() {
49 # variable
50 func_str_ip="$1"
51 func_str_user="$2"
52 func_str_command="$3"
53 # action
54 ssh $func_str_user@$func_str_ip "$func_str_command"
55 }
56
57 function do_sql() {
58 # variable
59 func_str_ip="$1"
60 func_str_sql="$2"
61 # action
62 mysql -u $mysql_username -h $func_str_ip -p"$mysql_password" -e "$func_str_sql" -P3306
63 }
64 function mysql_stop_up() {
65 # 判斷MySQL服務狀态
66 # variable
67 func_str_ip="$1"
68 mysql_status=`do_linux_by_ssh "$func_str_ip" "root" "service mysqld status" | grep -c 'not running'`
69 if [ "$mysql_status" = 1 ] ;then
70 do_linux_by_ssh "$func_str_ip" "root" "service mysqld start" > /dev/null
71 fi
72 sleep 20
73 mysql_status=`do_linux_by_ssh "$func_str_ip" "root" "service mysqld status" | grep -c 'running'`
74 echo ${mysql_status}
75 }
76 function mysql_slave_up() {
77 # variable
78 func_str_ip="$1"
79 slave_status=`do_sql "$func_str_ip" "show slave status \G;" 2> /dev/null | grep "Last_IO_Errno" | wc -l`
80 if [[ $slave_status == 0 ]]
81 then
82 do_sql "$func_str_ip" "set global read_only=1;set global relay_log_purge=0;"
83 do_sql "$func_str_ip" "$sql_change_master"
84 do_sql "$func_str_ip" "start slave;"
85 fi
86 slave_status=`do_sql "$func_str_ip" "show slave status \G;" 2> /dev/null | grep "Last_IO_Errno: 0" | wc -l`
87 echo ${slave_status}
88 }
89
90 ## MHA叢集為2個資料節點,是以下面隻循環判斷server1、server2,同樣如果是三個節點,則copy相關代碼,修改if添加即可。
91
92 #if server1 down
93 if [ "$conf_server1" != "[server1]" ] ;then
94 #if myql status was dead , auto systemctl start mysqld
95 echo "check server1 mysql status start"
96 mysqlstatus=`mysql_stop_up "$server1"`
97 echo "server1 mysql status : $mysqlstatus"
98 if [ "$mysqlstatus" = 1 ] ; then
99 echo "server1 slave up start"
100 slave_status=`mysql_slave_up "$server1"`
101 echo "server1 slave status :$slave_status server1: $server1"
102 if [ "$slave_status" = 1 ] ; then
103 echo "write server1 app1.conf start"
104 echo -e "\n[server1]\nhostname=$server1\nport=3306" >> /etc/masterha/app1.conf
105 fi
106 mha_check_result=`masterha_check_status --conf=/etc/masterha/app1.conf | grep "stopped" | wc -l`
107 if [ "$mha_check_result" = 1 ] ;then
108 nohup masterha_manager --conf=/etc/masterha/app1.conf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/masterha/mhalog/manager.log 2>&1 & > /dev/null
109 fi
110 fi
111 fi
112 conf_server1=`grep "server1" /etc/masterha/app1.conf`
113
114 #if server2 down
115 echo "$conf_server2":"$server2"
116
117 if [ "$conf_server2" != "[server2]" ] ;then
118 #if server2 myql status was dead , auto systemctl start mysqld
119 echo "server2 mysql stop status start"
120 mysqlstatus=`mysql_stop_up "$server2"`
121 echo "server2 ysql_stop_up status: $mysqlstatus"
122 if [ "$mysqlstatus" = 1 ] ; then
123 slave_satus=`mysql_slave_up "$server2"`
124 echo "server2 slave_status is : $slave_satus"
125 if [ "$slave_satus" = 1 ] ; then
126 echo "write server2 in app1.conf start"
127 echo -e "\n[server2]\nhostname=$server2\nport=3306" >> /etc/masterha/app1.conf
128 fi
129 mha_check_result=`masterha_check_status --conf=/etc/masterha/app1.conf | grep "stopped" | wc -l`
130 echo "$mha_check_result"
131 if [ "$mha_check_result" = 1 ] ;then
132 nohup masterha_manager --conf=/etc/masterha/app1.conf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/masterha/mhalog/manager.log 2>&1 & > /dev/null
133 fi
134 fi
135 fi
136 conf_server2=`grep "server2" /etc/masterha/app1.conf`
137
138 mha_check_result=`masterha_check_status --conf=/etc/masterha/app1.conf | grep "stopped" | wc -l`
139 if [ "$conf_server1" = "[server1]" ] && [ "$conf_server2" = "[server2]" ];then
140 if [ "$mha_check_result" = "1" ];then
141 nohup masterha_manager --conf=/etc/masterha/app1.conf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/masterha/mhalog/manager.log 2>&1 & > /dev/null
142 fi
143 fi
此檔案中,調用MHA的配置檔案的參數為 /etc/masterha/app1.conf。
masterha_manager 監控所産生的log存放在 /etc/masterha/mhalog/manager.log 中。
感謝:以上代碼實作主要是由同僚Fly Chen完成。
本文版權歸作者所有,未經作者同意不得轉載,謝謝配合!!!