Ctdb Rados(二):多場景斷網高可用

原文地址: https://www.tony-yin.site/201...

ping

以前寫過一篇文章【Ctdb Rados方式致使All Banned的問題】,談到了當ctdbrecovery 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

問題1

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

問題2

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數字什麼的,後來才發現沒有加qq表示安靜模式,不打印任何標準輸出,若是有匹配的內容則當即返回狀態值0。

場景二

「斷網」這個詞不夠具體,在實際生產環境中,一個集羣中,通常都會有多個網絡,就拿本人的ceph集羣環境來講(物理機環境,並不是前文說起的虛擬機開發環境),ceph有個public networkcluster network,而ctdb也有它的node networkpublic networkcephpublicctdbpublic是同一網段,cephcluster是單獨網段,ctdbnode是單獨的網段。因此ctdb master斷網能夠分爲三種狀況:

  • 拔掉ctdb master node網段網線
  • 拔掉ctdb master public網段網線
  • 斷掉ctdb master network服務

當拔掉ctdb master public網段網線,這沒有什麼好說的,ctdb master節點服務還存在,只是master節點上的public address不可用了,會漂移到其餘節點上。

問題1

當拔掉ctdb master node網段網線後,master節點仍然有public網卡,(這裏注意)它仍然能夠獲取其餘ctdb節點的狀態,而其餘節點卻不能夠獲取它的狀態,由於masternode節點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

問題2

因爲如今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
}

問題3

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...
相關文章
相關標籤/搜索