介紹
一直以來, 我們并未在線上啟用 masterha_manager 自動切換腳本, 主要因?yàn)樵诰W(wǎng)絡(luò)抖動(網(wǎng)線, 所屬機(jī)柜交換機(jī)不穩(wěn)定)的情況下并不能保證數(shù)據(jù)庫真的不能訪問. 比如重啟檢測腳本所在機(jī)器的網(wǎng)卡并不能說明數(shù)據(jù)庫出了問題, 所以從這方面看我們不能僅通過一個(gè)點(diǎn)的檢測就判斷數(shù)據(jù)庫不可訪問.
幸好可以通過 consul(因?yàn)?consul 提供 dns 接口, 筆者更傾向于使用 consul, 而不是 etcd)集群的特性, 我們增加多點(diǎn)檢測機(jī)制, 在 n 個(gè)集群的環(huán)境中, 有超過半數(shù)的檢測點(diǎn)檢測到數(shù)據(jù)庫有問題, 我們就認(rèn)為數(shù)據(jù)庫不可訪問, 這時(shí)則開始調(diào)用 masterha_manager 腳本進(jìn)行切換, 如下圖所示:
???????<checkmysql>?????????<checkmysql>?????????<checkmysql> ????????????|???????????????????|?????????????????????| ???????+---------+??????????+---------+??????????+---------+ ???????|?consul1?|??????????|?consul2?|??????????|?consul3?| ???????+---------+??????????+---------+??????????+---------+ ???????????????????????????????|???????????????/ ???????????????????????????????|??????????????/ ???????????????????????????????|?????????????/ ???????????????????????????????|????????????/ ?????????????????????+----------------------+ ?????????????????????|???http?api?&&?acl????| ?????????????????????+----------------------+ ????????????????????????????????| ????????????????????????????????| ?????????????????????+----------------------+ ?????????????????????|?consul-template??????|?---->???--->??<mysqlxxx.conf> ?????????????????????+----------------------+ ??????????????????????????????????????????????????????????????????????????????????| ??????????????????????????????????????????????????????????????????????+--------------------------+?? ??????????????????????????????????????????????????????????????????????|?masterha_manager_consul??| ??????????????????????????????????????????????????????????????????????+--------------------------+</mysqlxxx.conf></checkmysql></checkmysql></checkmysql>
?
checkmysql 需要部署到每臺 consul server 中, 這樣我們就實(shí)現(xiàn)了多點(diǎn)檢測 MySQL 是否正常, 如果正常, checkmysql 會設(shè)置一個(gè)值為 1 的鍵: mysql/mysqlxxxx/node-consul, 反之則值為 0, 其中 node-consul 的默認(rèn)值為當(dāng)前主機(jī)的 hostname.
checkmysql 檢測完后, 我們使用 consul-template 工具根據(jù)模板文件 mysqlxxx.tpl 來監(jiān)聽所有 key 的變更, 如果有變化則生成配置 mysqlxxxx.conf, 進(jìn)而調(diào)用 masterha_manager_consul 腳本開始進(jìn)行切換.
我們在 masterha_manager_consul 腳本中重寫了方法 MHA::HealthCheck::wait_until_unreachable, 避免了無限循環(huán)檢測, 如果少于一半的檢測點(diǎn)認(rèn)為數(shù)據(jù)庫異常, 則退出該輪的調(diào)用, 否則啟用子進(jìn)程開始執(zhí)行切換操作.
備注:
masterha_manager_consul 是基于 MHA v0.5.6 修改的, 并且默認(rèn)只在當(dāng)天的21點(diǎn)到第二天的 9 點(diǎn)之間做自動切換, 可以通過 night 選項(xiàng)控制此功能. 另外多臺 consul server 建議部署到不同的交換機(jī)或機(jī)柜中.
使用說明
代碼見 mha_manager_consul 整體結(jié)構(gòu)如下:
mha_manager_consul ├──?bin │???├──?checkmysql │???└──?masterha_manager_consul ├──?conf │???├──?db.cnf │???└──?template-config ├──?consul │???├──?acl │???│???├──?policy.ano │???│???└──?policy.key │???├──?conf │???│???└──?consul.conf │???└──?conf.d │???????└──?server.json ├──?README.md └──?template ????└──?mysql3308.tpl
測試環(huán)境
繼續(xù)使用以往的測試環(huán)境:
ip | os | hostname | version |
---|---|---|---|
10.0.21.5 | centos 6.5 | cz-test1 | consul 0.8v |
10.0.21.7 | centos 6.5 | cz-test2 | consul 0.8v |
10.0.21.17 | centos 6.5 | cz-test3 | consul 0.8v |
下面所有的操作都假設(shè)已經(jīng)安裝好了 consul cluster.
備注
在運(yùn)行 checkmysql 之前, 我們需要設(shè)置好 acl 策略, 以免 consul 的敏感信息被旁人訪問. 下面命令中的 token 參數(shù)即是 consul 主配置文件中的 acl_master_token 選項(xiàng), 文件 policy.ano 則是限制匿名用戶訪問 mysql/* 相關(guān)鍵的策略, policy.key 則是設(shè)置允許訪問 mysql.* 相關(guān)鍵的權(quán)限, 這里生成的 token 則為 dcb5b583-cd36-d39d-2b31-558bebf86502, 大家可以訪問 consul acl 了解更多訪問控制的內(nèi)容.
#curl?-X?PUT?--data?@policy.ano?http://localhost:8500/v1/acl/update?token=e95597e0-4045-11e7-a9ef-b6ba84687927 {"ID":"anonymous"} #curl?-X?PUT?--data?@policy.key?http://localhost:8500/v1/acl/update?token=e95597e0-4045-11e7-a9ef-b6ba84687927 {"ID":"dcb5b583-cd36-d39d-2b31-558bebf86502"}
checkmysql
在每個(gè) consul server 的節(jié)點(diǎn)上運(yùn)行該腳本, 這里的 token 參數(shù)即為上述 acl 的結(jié)果, tag 則是 db.conf 配置里的實(shí)例, 通過以下命令啟動:
perl?checkmysql?--conf?db.cnf?--verbose?--tag?mysql3308?--token?dcb5b583-cd36-d39d-2b31-558bebf86502 [2017-06-08T10:09:14]?mysql/mysql3308/cz-test2?with?value?1?no?change [2017-06-08T10:09:15]?mysql/mysql3308/cz-test2?with?value?1?no?change
cz-test2 表示當(dāng)前的主機(jī)名是 cz-test2, 對應(yīng)上述介紹的 node-consul.
備注
如果你的 MySQL master 是通過 vip 提供服務(wù), db.conf 配置里的 host 選項(xiàng)最好設(shè)置成 vip 的地址.
consul-template
在 checkmysql 更新 consul 的相關(guān) key 之后, 如果有任意一個(gè) checkmysql 變更了key 值, 則 consul-template 根據(jù)模板文件重新生成 mysqlxxx.conf 文件, 隨后開始調(diào)用 masterha_manager_consul 腳本, consul-template 的配置詳見 template-config; 通過以下命令啟動:
#?consul-template?-config?config? 2017/05/25?10:11:13?[DEBUG]?(logging)?enabling?syslog?on?LOCAL5
mysqlxxxx.tpl 模板文件的內(nèi)容如下:
#?node3308 cz-test1:1 cz-test2:1 cz-test3:1
如果少于半數(shù)的監(jiān)測點(diǎn)發(fā)現(xiàn) MySQL 異常, consul-template 打印下面的消息:
[2017-06-08T10:24:15]?status?ok,?skip?switch..
反之則打印 error 信息, 并開始調(diào)用 masterha_manager_consul 腳本:
[2017-05-25T10:24:48]?status?error,?need?switch.. Wed?May?24?10:24:48?2017?-?[info]?Reading?default?configuration?from?/etc/masterha/app_default.cnf.. ... ...
conf.d/server.json
詳見 template-config 配置中的 address = “consul.service.consul:8500” 選項(xiàng); 在網(wǎng)絡(luò)波動的情況下, address 選項(xiàng)如果只配置一個(gè) consul server 的 ip 的話, consul-template 則不能連接到 consul server 中監(jiān)控相應(yīng)的 key 值, 盡管 consul-template 有重試功能, 但是在單 ip 的情況下, 難以確保可以正常獲取相關(guān)的 key 值信息. conf.d/server.json 配置則將各個(gè) consul server 的 ip 作為一個(gè) dns 條目, 如下所示:
#?dig?@10.0.21.5?consul.service.consul ...... ...... ;;?QUESTION?SECTION: ;consul.service.consul.?????IN??A ;;?ANSWER?SECTION: consul.service.consul.??0???IN??A???10.0.21.7 consul.service.consul.??0???IN??A???10.0.21.5 consul.service.consul.??0???IN??A???10.0.21.17
單個(gè) consul server 異常, 會自動跳到正常的 consul-server 中.
主從切換測試
我們簡單關(guān)閉 master 的實(shí)例, 看看各工具間的輸出狀態(tài).
關(guān)閉 master
關(guān)閉 master 后, checkmysql 腳本開始更新狀態(tài), 在超過半數(shù)的情況下調(diào)用 masterha_manager_consul 腳本進(jìn)行主從切換: checkmysql 腳本輸出, 開始將 key 的值更為 0
[2017-06-08T18:16:43]?mysql/mysql3308/cz-test2?with?value?1?no?change DBI?connect('mysql_read_default_file=./db.cnf;mysql_read_default_group=mysql3308','',...)?failed:?Can't?connect?to?MySQL?server?on?'10.0.21.7'?(111)?at?checkmysql?line?56 [2017-06-08T18:16:44]?set?0?with?key?mysql/mysql3308/cz-test2?ok DBI?connect('mysql_read_default_file=./db.cnf;mysql_read_default_group=mysql3308','',...)?failed:?Can't?connect?to?MySQL?server?on?'10.0.21.7'?(111)?at?checkmysql?line?56 [2017-06-08T18:16:45]?mysql/mysql3308/cz-test2?with?value?0?no?change
mysql3308.conf 配置文件變更為如下:
#?node3308 cz-test1:0 cz-test2:0 cz-test3:0
consul-template 則顯示如下:
#?consul-template?-config?config? 2017/06/08?12:11:13?[DEBUG]?(logging)?enabling?syslog?on?LOCAL5 [2017-05-24T12:16:48]?status?error,?need?switch..?#?腳本判定超過半數(shù)認(rèn)為數(shù)據(jù)庫不可訪問 Wed?Jun?08?12:16:48?2017?-?[info]?Reading?default?configuration?from?/etc/masterha/app_default.cnf.. Wed?Jun?08?12:16:48?2017?-?[info]?Reading?application?default?configuration?from?/etc/masterha/app_56.conf.. Wed?Jun?08?12:16:48?2017?-?[info]?Updating?application?default?configuration?from?/usr/bin/init_conf_loads.. ....
如果沒有超過半數(shù), consul-template 則顯示以下:
[2017-06-08T12:24:15]?status?ok,?skip?switch..
MHA 切換日志
mha 切換的日志則包含以下信息, 日志文件則根據(jù) mha 的具體配置而定:
Wed?Jun?08?12:45:37?2017?-?[info]?Starting?master?failover.. Wed?Jun?08?12:45:37?2017?-?[info]? From: 10.0.21.7(10.0.21.7:3308)?(current?master) ?+--10.0.21.17(10.0.21.17:3308) To: 10.0.21.17(10.0.21.17:3308)?(new?master) ... ... Master?failover?to?10.0.21.17(10.0.21.17:3308)?completed?successfully. Wed?Jun?08?12:45:41?2017?-?[info]?Sending?mail..
總結(jié)
整體上而言, 使用 consul 的架構(gòu)相對繁瑣, 沒有單節(jié)點(diǎn)那么簡易方便, 不過對于比較核心的數(shù)據(jù)庫來說, 一致性應(yīng)該放到首位, 多點(diǎn)檢測則很大程度上健壯了切換機(jī)制. 而且原工具自帶的 masterha_manager 腳本本身只是循環(huán)檢測, 超過三次錯(cuò)誤(每次間隔時(shí)間遞增)才會開始切換, 在網(wǎng)絡(luò)波動, 交換機(jī)故障或數(shù)據(jù)庫主機(jī)較繁忙的時(shí)候, 會引起一些意料之外的操作, 所以相對來說, 多點(diǎn)檢測避免了這類不穩(wěn)定的問題, 另外 consul cluster 部署完成后也可以用于其他需要一致性判斷的業(yè)務(wù), 不用太糾結(jié)于繁瑣方面的考慮.