原文地址: https://www.tony-yin.site/201...
以前寫過一篇文章【Ctdb Rados方式致使All Banned的問題】,談到了當ctdb
將recovery lock
設置成rados
的方式後,斷網master
節點會形成全部ctdb
節點All Banned
,主要緣由是master
意外斷網沒有釋放鎖,其餘節點沒法獲取到鎖,當時的解決方案是每5
分鐘檢查一次ctdb
狀態,若是連續兩次發生了All Banned
的狀況,則手動刪除lock
,這種作法在最近的測試中遇到了一些問題,本文對這些問題進行剖析並對相應的解決方案進行分享。node
完整代碼地址: https://github.com/tony-yin/C...
若是基於原來的作法,ctdb
發生All Banned
的狀況,須要十分鐘的監控時間加上兩分鐘左右的recovery
時間,也就是說大概須要十二分鐘才能恢復ctdb
服務,這樣看來高可用有點名實其副了,這個也會明顯地影響存儲業務的正常運行。後來,咱們討論出新的方案:每5s
檢查一次ctdb
的狀態,All Banned
的次數累計到5
次才肯定爲該故障場景,而後手動刪除lock
,最終要保證ctdb
可以在2min
內完成恢復。git
cron tab
最短週期只支持分鐘級別,因此如何5s
檢查一次即是一個問題。github
代碼是死的,人是活的,雖然cron tab
只支持分鐘級別,可是咱們能夠每分鐘調用一個腳本,而後在這個腳本中遍歷12
次,每次調用ctdb monitor
腳本,而後sleep 5s
,這樣就能夠達到每5s
檢查一次ctdb
的效果了。shell
# ctdb_monitor * * * * * root /etc/ctdb/cron-seconds # cron-seconds #!/bin/bash for((i=1;i<=12;i++));do ../monitor_ctdb sleep 5 done
這樣檢查到ctdb
發生All Banned
狀況,只須要花費25s
,剩下的就是recovery
的時間了。bash
當ctdb master
節點的network
服務斷掉,其餘兩個節點(個人開發環境是三節點的虛擬機環境)便會選舉一個爲master
節點,而後去獲取lock
,由於原master
沒有釋放鎖,致使全部節點All Banned
,即便咱們手動刪除了鎖,可是這時候其餘兩個節點仍然處於Banned
的狀況,須要等到Ban Timeout
纔會再次嘗試獲取鎖並開始恢復過程,這個timeout
的時間是300s
,即5min
,這顯然是咱們不能接受的,因此咱們要在刪除lock
後,重啓全部節點的ctdb
服務。網絡
不過該如何觸發該重啓操做呢?測試
咱們在刪除lock
後將ctdb
全部節點的ip
做爲對象存進rados
中,而後在每5s
監控的腳本中,查看rados
中是否存在本節點的ip
對象,若是有,則嘗試重啓ctdb
操做,重啓後便刪除該對象。spa
function save_nodes_ip() { nodes=$(ctdb listnodes) for node in $nodes; do echo "$node" > $node rados -p rbd put $node $node rm -f $node done } function get_current_node_ips() { ips=$(/usr/sbin/ip addr | grep "inet " | awk '{print $2}') echo $ips } function monitor_nodes_ip_in_rados() { ips=$(get_current_node_ips) for ipinfo in $ips; do ip=${ipinfo%/*} if $(timeout 10 rados -p rbd ls | grep "$ip" -qw); then systemctl restart ctdb rados -p rbd rm $ip fi done }
至於爲何三個節點的ip
都要存入rados
,這個是由於原master
節點恢復網絡後,ctdb
服務的狀態爲failed
,一樣須要重啓ctdb
服務才能正常恢復原master
節點。 命令行
注意:rest
這邊有兩個問題,當時浪費了我很多時間,問題不是多麼深奧,可是不易發現。。。
第一個問題即是ips=$(/usr/sbin/ip addr | grep "inet " | awk '{print $2}')
這行代碼,原來的寫法是ips=$(ip addr | grep "inet " | awk '{print $2}')
,當時發現ip
老是獲取不到,而後不管是命令行仍是腳本運行均可以正常獲取到,後來仍是同事提醒才發如今crontab
腳本中,shell
命令默認是/usr/bin/
下的,而ip
命令則是/usr/sbin/
下,因此這裏的命令咱們須要全路徑。(這個須要格外注意!!!被坑的不要不要的。。。)
第二個問題即是rados -p rbd ls | grep "$ip" -qw
這行代碼,當時沒注意寫成了rados -p rbd ls | grep "$ip" -w
,發現if
判斷時常有問題,一開始還覺得不能grep
數字什麼的,後來才發現沒有加q
,q
表示安靜模式,不打印任何標準輸出,若是有匹配的內容則當即返回狀態值0。
「斷網」這個詞不夠具體,在實際生產環境中,一個集羣中,通常都會有多個網絡,就拿本人的ceph
集羣環境來講(物理機環境,並不是前文說起的虛擬機開發環境),ceph
有個public network
和cluster network
,而ctdb
也有它的node network
和public network
,ceph
的public
和ctdb
的public
是同一網段,ceph
的cluster
是單獨網段,ctdb
的node
是單獨的網段。因此ctdb master
斷網能夠分爲三種狀況:
ctdb master node
網段網線ctdb master public
網段網線ctdb master network
服務當拔掉ctdb master public
網段網線,這沒有什麼好說的,ctdb master
節點服務還存在,只是master
節點上的public address
不可用了,會漂移到其餘節點上。
當拔掉ctdb master node
網段網線後,master
節點仍然有public
網卡,(這裏注意)它仍然能夠獲取其餘ctdb
節點的狀態,而其餘節點卻不能夠獲取它的狀態,由於master
的node
節點ip
不存在。因此形成的結果就是原master
節點還默認本身是master
節點,而其餘的節點卻又選舉出了新的master
,咱們的腳本由於All Banned
手動刪除了lock
,這時候其餘節點能夠正常恢復ctdb
服務,可是當ctdb master
節點斷網再恢復後,它還覺得本身是master
,會不斷去獲取鎖,而原來的鎖已經被咱們手動刪除,這時候新的鎖被新的master
掌握,因此此時產生腦裂,咱們要犧牲原master
節點,也就是斷網節點,因此須要重啓它。這個重啓觸發機制咱們是經過在每次刪除lock
以後在rados
中存入ctdb
全部節點的ip
做爲object
(這就是爲何要存入全部節點的ip
),而後只要發現有這個object
便執行ctdb
重啓操做,而後便刪除這個對象。至於爲何要存全部對象是由於除了原master
須要重啓以外,另外兩個正常節點發生All Banned
的狀況,默認timeout
時間是300s
(這個上面也提到過),咱們爲了減小恢復時間,直接在刪除lock
後重啓ctdb
;
因爲如今ctdb
的鎖是放在rados
中,而不是之前的cephfs
的方式了。因此當master
斷網再恢復時,它會不斷地去rados
獲取他原來的鎖,這是獲取鎖的進程愈來愈多,會阻塞住rados
服務,咱們能夠經過ps -ef | grep rados_helper
看到進程不斷變多,那麼rados
服務不能正常讀寫就影響到咱們上一條的機制,不能讀rados
中是否含有本節點ip
的對象,就沒辦法進行重啓操做,那麼這樣它就會不斷地繼續獲取lock
,因此咱們在這裏又加了一個機制,若是ps -ef | grep rados_helper
的數目超過6
個,就默認啓動重啓ctdb
服務。
function monitor_get_lock_timeout() { count=$(ps -ef | grep rados_helper | wc -l) if [ $count -ge $RADOS_HELPER_PROCESS_MAX ]; then systemctl restart ctdb update_last_ctdb_restart_time fi }
ctdb
目前重啓的機制有點多,有自身自帶的故障重啓,也有咱們監控腳本的異常狀況,很容易發生重複重啓,還有可能rados_helper
堆積的進程不少,好比20
個,咱們的腳本是5s
一次,也許20
個的時候重啓了,過5s
,進程釋放也須要時間,可能此時還有10
個,那麼大於咱們規定的6
個,就會繼續重啓,這種重複重啓沒有必要,因此咱們要加上ctdb
重啓的週期限定2min
。
function get_ctdb_restart_interval() { last_time=$(get_ctdb_restart_last_time) if [ -z "$last_time" ]; then interval=$(expr $RESTART_CTDB_INTERVAL_MAX + 1) else current_time=$(date +%s) interval=$(expr $current_time - $last_time) fi echo $interval }
考慮並解決以上提到的問題,基本上能夠覆蓋以上三種斷網的場景了,在監控和管理ctdb
的過程當中,必定要當心,不能影響到業務正常運行。
生產環境網絡結構錯綜複雜,每每在虛擬機上開發的功能當時好好的,到了物理機上面測試會發生各類問題,此時,咱們首先要搞清楚網絡拓撲結構,熟悉硬件配置,各網段的做用和相互之間的關聯,這樣遇到問題咱們能夠順藤摸瓜,一樣ctdb
的原理也須要掌握才能瞭解它各類行爲的觸發機制,才能更好的定製化監控和管理。以後我會花點時間好好地研究一下ctdb
,而後再單獨作分享。
完整代碼地址: https://github.com/tony-yin/C...