keepalived實現mycat高可用問題排查;道路坎坷,布滿荊棘,定讓你大吃一驚!


前言

  開心一刻

    醫院里,一母親帶着小女孩打針。小女孩:“媽媽我不想打針,疼!”媽媽:“寶貝兒聽話,這里這么多護士阿姨,咱們找個打針不疼的。”小女孩:“那哪個阿姨打針不疼呢?”媽媽:“媽媽也不知道,咱們試試看吧。”小女孩高興的點了點頭。。。

  路漫漫其修遠兮,吾將上下而求索!

  github:https://github.com/youzhibing

  碼雲(gitee):https://gitee.com/youzhibing

問題背景

  Mycat - 實現數據庫的讀寫分離與高可用寫完之后,本以為一兩天就能寫完Mycat - 高可用與負載均衡實現,滿滿的干貨!,可事實是卻用了一個星期;期間雖然產生了一系列的問題,但主要還是卡在了keeplaived實現mycat的高可用,那時候兩台keepalived服務器的keepalived.conf內容如下

  細心的朋友應該已經找到問題了,不管你找沒找到問題,都可以准備好花生、瓜子和啤酒,且看我是如何埋雷和掃雷的 

vip查看問題

  個人一直用ifconfig命令來管理linux的網絡配置,但是keepalived啟動之后通過ifconfig命令卻看不到vip。ifconfig是net-tools中已被廢棄使用的一個命令,許多年前就已經沒有維護了。iproute2套件里提供了許多增強功能的命令,ip命令即是其中之一,大多數Linux發行版已經預裝了iproute2工具,而沒有預裝net-tools,ip命令功能更強大,旨在取代ifconfig。我們可以用ip命令查看vip的綁定情況,具體如下

  這個問題還真卡了我一會,一直以為vip綁定失敗,但是看/var/log/message,又沒發現有什么問題,並且還能ping通vip。我這個無知者是有多無畏、多自信呀!

  更多關於ifconfig、ip的信息,大家可以去網上查閱,這里我就不細講了(其實是不知道,)。

檢測腳本問題

  單獨執行命令是正確的;命令放入檢測腳本中,部分是正確的;檢測腳本結合keepalived,正確的更少了,具體我們往下看

  ps命令查詢mycat進程

    check_pid.sh具體配置如下

#!/bin/bash
count=`ps -ef|grep mycat |grep -v grep | wc -l`
time=$(date "+%Y-%m-%d %H:%M:%S")
if [ $count = 0 ]; then
    echo "$time : count=$count, mycat is not running..." >> /var/log/keepalived_check.log
    exit 1 # 返回1說明腳本非正常執行,mycat不在運行中
else
    echo "$time : count=$count, mycat is running..." >> /var/log/keepalived_check.log
    exit 0 # 返回0說明腳本正常執行,mycat正在運行中
fi
View Code

    ps -ef與ps aux效果一樣,我就只演示一個了,結果如下

    ps命令單獨執行,當mycat沒啟動時,查詢到的mycat進程數是0,當mycat在運行中,查詢到的是2(大於0表示mycat在運行中),很正確,沒毛病;可當ps命令放到check_pid.sh中,執行的結果卻有點不一樣,當mycat沒啟動時,查到的進程數竟然是2,而當mycat在運行中,查到的進程數是4,為什么是這種結果,至今我還沒搞明白,表面上看着像是單獨執行ps命令的翻倍,為什么翻倍,不得而知 。很顯然,check_pid.sh這么寫不行。

  環境變量中mycat命令

    既然ps命令查mycat進程數行不通,我們就用mycat命令(將MyCat配置到環境變量中在Mycat - 實現數據庫的讀寫分離與高可用已講過),check_pid.sh具體配置如下

#!/bin/bash
count=`mycat status|grep "Mycat-server is running" | wc -l`
time=$(date "+%Y-%m-%d %H:%M:%S")
if [ $count = 0 ]; then
    echo "$time : count=$count, mycat is not running..." >> /var/log/keepalived_check.log
    exit 1 # 返回1說明腳本非正常執行,mycat不在運行中
else
    echo "$time : count=$count, mycat is running..." >> /var/log/keepalived_check.log
    exit 0 # 返回0說明腳本正常執行,mycat正在運行中
fi
View Code

    測試結果如下

    單獨執行命令,結果是正確的,單獨執行check_pid.sh,結果也是正確的,可偏偏check_pid.sh結合keepalived卻出錯了,這就難受了

  絕對路徑的mycat命令

    雖然上述兩個問題的原因未知,但我們最終的目的:keepalived結合check_pid.sh正確執行,還是要實現的,我們再換個方式試下,用mycat命令的絕對路勁行不行呢? 具體配置如下

#!/bin/bash
count=`/usr/local/mycat/bin/mycat status |grep 'Mycat-server is running' | wc -l`
time=$(date "+%Y-%m-%d %H:%M:%S")
if [ $count = 0 ]; then
    echo "$time : count=$count, mycat is not running..." >> /var/log/keepalived_check.log
    exit 1 # 返回1說明腳本非正常執行,mycat不在運行中
else
    echo "$time : count=$count, mycat is running..." >> /var/log/keepalived_check.log
    exit 0 # 返回0說明腳本正常執行,mycat正在運行中
fi
View Code

    單獨執行命令與單獨執行check_pid.sh我就不演示了,與上述:環境變量中mycat命令 無差,keepalived結合check_pid.sh測試結果如下

    終於搞對了,就是你了:用絕對路徑的mycat命令!此刻心情真的是

  在check_pid.sh中有兩種做法可以滿足keepalived進行vip轉移的條件

    1、推薦做法,返回mycat檢測結果給keepalived

      如果mycat不在運行中,則返回1,若mycat正在運行中則返回0,注意是使用exit 0或exit 1來返回檢測結果,與我們平時理解的有些不一樣。keepalived會根據這個返回結果相應的增減優先級,keepalived集群會根據各個節點的優先級重新選舉master

      keepalived優先級 = priority + weight * script的結果,腳本執行返回0,script則為true,否則script為false,權重大的搶占到vip,成為master

    2、野蠻做法,直接殺掉keepalived進程

      這是比較野蠻的做法,一旦檢測到mycat進程不存在,則直接killall keepalived,這時候就不需要關注返回值了,相當於將當前keepalived踢出了keepalived集群。這么做有點不太好,就是當我們把mycat修復后,不但要重啟mycat,也需要重啟keepalived。

virtual_router_id問題

  具體日志輸出

    Jan 17 09:53:44 localhost Keepalived_vrrp[1655]: ip address associated with VRID not present in received packet : 192.168.1.200
    Jan 17 09:53:44 localhost Keepalived_vrrp[1655]: one or more VIP associated with VRID mismatch actual MASTER advert
    Jan 17 09:53:44 localhost Keepalived_vrrp[1655]: bogus VRRP packet received on eth0 !!!
    Jan 17 09:53:44 localhost Keepalived_vrrp[1655]: VRRP_Instance(VI_1) Dropping received VRRP packet...

  意思是說virtual_router_id重復了,當時還愣了一下:virtual_router_id不是應該一致嗎?  主從熱備+負載均衡(LVS + keepalived)中配置的就是一致,當時沒去細想,既然日志提示重復了,那就改一個讓其不重復唄,一個virtual_router_id值設置成66,一個virtual_router_id值設置成65,此提示消除,vip能夠正常綁定上,但此時就出現了keepalived“腦裂”問題,兩台keepalived服務器上都出現了vip,如下圖

“腦裂”問題

  何謂腦裂,指在一個高可用(HA)系統中,當聯系着的兩個節點斷開聯系時,本來為一個整體的系統,分裂為兩個獨立節點,這時兩個節點開始爭搶共享資源,結果會導致系統混亂,數據損壞。

  vip出現了多個,我就主觀的認為是keepalived出現了腦裂,上網查資料、提問求助、問好友、換centos系統版本、換keepalived版本、查閱keepalive的官網、等等,嘗試各種方法(就是沒有對比keepalived.conf,一直在copy錯的keepalived.conf,),都沒有找到答案,期間一度想放棄,可我一根筋的性格不允許我這么做;終於皇天不負有心人,無意之中我找到了問題所在,具體排查過程且聽我慢慢道來。

  防火牆是否放行vrrp

    由於是本地測試,我一般都是關了防火牆的,生產環境不能直接關閉防火牆,而是設置防火牆來放行vrrp包;查看vrrp包情況:tcpdump -i eth0|grep VRRP

    tcpdump命令若不存在,則可以執行命令:yum install -y tcpdump進行安裝。如上圖所示,兩台keepalived服務器都是能正常收到彼此的vrrp包

  selinux是否關閉

    /usr/sbin/sestatus -v 查看selinux狀態;/etc/selinux/config文件可以配置selinux開始與關閉,修改之后重啟系統生效。

    兩台keepalived服務的selinux也是關閉的

  keepalived官網查詢信息

    無奈之下我想到了官網,想看看官網中有沒有提到腦裂問題,或者說是哪個版本修復了腦裂問題,changelog中查詢split關鍵字,結果如下

    貌似1.2.9版本有修復腦裂問題,而我的keepalived版本分別是:keepalived-1.2.13-5.el6_6.i686和keepalived-1.3.5-8.el7_6.x86_64,應該不是低版本的問題

  博問求助

    感覺形式越來越不利了,我想到了園子的博問,於是我在博問欄進行了提問:keepalived腦裂,有人瀏覽了,但沒人回答,可能是問的姿勢不對,亦或是未碰見有緣人

  天無絕人之路

    各方面都顯示正確,可結果卻不正確,真的讓人很絕望!!!,此刻我的心情...... 你們懂的

    山重水復疑無路,柳暗花明又一村。眾里尋她千百度,驀然回首,那人卻在燈火闌珊處。撥開雲霧見天日,守得雲開見月明。......實在是裝不下了......

    不知道是上天眷顧,還是自己抽瘋,竟然鬼使神差的去比較keepalived.conf文件,結果發現了驚天大冪冪,不對,是驚天大秘密:

    此刻心情五味雜陳,怎么VIP一開始就配置的不一樣,是不是室友趁我外出動了我代碼?嗯,應該是的。看到vip的不同,讓我看到了一絲曙光,更猶如看到剛出浴的美人一般,我牢牢抓住最后這根救命的稻草,重新展開部署與測試,終於出現了意料中的結果,此時我如釋重負,癱倒在床上思考了一會人生(,你為何如此美?)。keepalived.conf的正確配置,請查看Mycat - 高可用與負載均衡實現,滿滿的干貨!

    這特么簡直就是一個天大的烏龍! 我的這波操作真的是,太特么刺激了......,差點把自己玩死......

最佳實踐

  1、mycat存活檢測腳本中,用絕對路徑的mycat命令,不要用ps查詢mycat進程,也不要用配置好的縮寫mycat命令;當然了,如果我們用lvs實現了mycat的負載均衡,那么mycat檢測腳本就可以省略了;

  2、keepalived.conf寫完之后用比較工具進行代碼比較,可以防止少改、多改以及手抖的情況,避免出現本文的情況(mmp的);

  3、在MASTER節點的 vrrp_instance中配置nopreempt,當它異常恢復后,即使它的priority更高也不會搶占,這樣可以避免正常情況下做無謂的切換;

總結

  1、環境搭建過程中一定要仔細小心,分步驟、環節,保證各個步驟、環節都正確,即使出現了問題,我們也能很快定位到是哪個步驟、環節出了問題,不至於出現類似本文的情況:明明不是腦裂問題,卻死盯着腦裂不放,背道而馳,怎么解決的了?

  2、如果確實是腦裂問題,我們可以從如下幾個方面進行排查

    防火牆是否放行vrrp包,推薦放行vrrp包,而不是野蠻式的關閉防火牆;keepalived配置問題,用文件比較工具比較keepalived.conf,不同之處非常少,很容易比較;selinux設置,這個我沒研究過,也可作為一個排查點。一般而言從這三方面入手,基本能解決腦裂問題,實在是不行,則我們可以自寫腳本,進行第三方仲裁。

  3、虛擬路由編號(virtual_router_id),同集群,主備必須一致,不同集群不能相同;一般而言,我們只會有一個keepalived集群,所以配置成一樣就沒錯,即使報了相關的錯,也應該從其他方面找問題,而不是改動virtual_router_id。

參考

  記一次keepalived腦裂問題查找


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM