Keepalived虛擬ip不漂移問題

 

 

Keepalived主要是通過虛擬路由冗餘來實現高可用功能。本文將不對keepalived的基本原理進行闡述,可參考文章Keepalived詳細介紹簡介keepalived vip漂移基本原理及選舉算法。本文記錄了在實踐過程中使用keepalived時,在weight值變化的情況下vip不漂移的問題及解決方法。

場景

3個keepalived節點, vip爲172.31.23.6:

  • devops1a-zoocassa0  172.31.23.22
  • devops1a-zoocassa1  172.31.23.23
  • devops1a-zoocassa2  172.31.23.24

預期

  1. 三個節點初始都設爲BACKUP,按照優先級(priority)選舉MASTER;
  2. 在三個節點上檢查memcached服務狀態,失敗則降低優先級;
  3. 如果MASTER(假設爲devops1a-zoocassa0)上檢查失敗,BACKUP上檢查成功,則優先級高的BACKUP節點(假設爲devops1a-zoocassa1)切換爲MASTER節點;
  4. 之前檢查失敗的MASTER(devops1a-zoocassa0)上的服務恢復時, 之前的BACKUP節點(devops1a-zoocassa1)服務檢查也成功,即使devops1a-zoocassa0優先級恢復到高於devops1a-zoocassa1,也不再成爲MASTER(不搶佔)。

不成功配置範例

# devops1a-zoocassa0

vrrp_script chk_memcached {
    script "killall -0 memcached"    #檢查memcached服務
    interval 5
    weight 3
}

vrrp_instance VI_1 {
    interface eth0
    state BACKUP
    virtual_router_id 55
    nopreempt                        #設置不搶佔
    priority 101

    unicast_src_ip 172.31.23.22
    unicast_peer {
        172.31.23.23
        172.31.23.24
    }
    virtual_ipaddress {
        172.31.23.6                       
    }
    track_script {
        chk_memcached
    }
}
# devops1a-zoocassa1

vrrp_script chk_memcached {
    script "killall -0 memcached"
    interval 5
    weight 3
}

vrrp_instance VI_1 {
    interface eth0
    state BACKUP
    virtual_router_id 55
    nopreempt
    priority 100

    unicast_src_ip 172.31.23.23
    unicast_peer {
        172.31.23.22
        172.31.23.24
    }
    virtual_ipaddress {
        172.31.23.6
    }
    track_script {
        chk_memcached
    }
}
# devops1a-zoocassa2

vrrp_script chk_memcached {
    script "killall -0 memcached"      
    interval 5
    weight 3
}

vrrp_instance VI_1 {
    interface eth0
    state BACKUP
    virtual_router_id 55    
    nopreempt                          
    priority 99                        

    unicast_src_ip 172.31.23.24
    unicast_peer {
        172.31.23.22
        172.31.23.23
    }
    virtual_ipaddress {
        172.31.23.6
    }
    track_script {
        chk_memcached
    }
}

以上述配置文件內容作爲keepalived配置文件/etc/keepalived/keepalived.conf,在三個節點上啓動keepalived:

service keepalived start

會發現存在如下問題:

  1. 優先級高的devops1a-zoocassa0可能沒有成爲MASTER節點(多試幾次,可能每次選舉的MASTER節點都不同),不符合預期中的第1點;
  2. 假設devops1a-zoocassa0成爲了MASTER節點,關掉devops1a-zoocassa0上的memcached服務:
    service memcached stop

    此時運行service keepalived status,發現devops1a-zoocassa0的weight值降低且低於devops1a-zoocassa1,但是devops1a-zoocassa1並沒有成爲MASTER節點,不符合預期中的第3點。

  3. 將配置文件中的nopreempt去掉以後,可以解決上述問題,符合預期中的第1,2,3點,但是當原MASTER節點上服務恢復後,原MASTER會重新成爲MASTER角色,這不符合預期中的第4點(不搶佔);

問題原因:

在網上查閱到的資料中,大都認爲按照上述配置後可以完全符合預期中的4個點,不會出現MASTER節點服務檢查失敗後VIP不漂移的問題。但是實踐是檢驗真理的唯一標準,配置nopreemt後,不僅是會讓原MASTER節點服務恢復後不搶佔,而是會完全的不選舉新MASTER(從頭到尾永遠不切換,除非BACKUP認爲當前集羣中不存在MASTER, 纔會重新選舉),這樣便可以解釋出現的問題1和問題2了:

問題1的原因在於:

  1. 先啓動的節點將自己選舉爲MASTER, 在收到其他節點的vrrp報文後不會按照優先級調整自己的角色;
  2. 後啓動的節點收到了MASTER的vrrp報文,發現已經存在MASTER,由於不搶佔,自動進入BACKUP狀態;

問題2的原因在於:

  1. 設置了nopreempt, 永遠不發生角色切換;

下面是官方文檔中對於nopreempt的解釋:

"nopreempt" allows the lower priority machine to maintain the master role, 
even when a higher priority machine comes back online. 

NOTE: For this to work, the initial state of this entry must be BACKUP.

解決方案

要想同時滿足預期中的效果,其實只要做到兩點:

  1. 當MASTER上的服務檢查失敗時,觸發重新選舉;
  2. 設置不搶佔(已經做到);

那麼如何實現第一點呢?重新選舉意味着:

  1. BACKUP成爲MASTER,要求BACKUP節點認爲當前節點中沒有MASTER節點;
  2. MASTER成爲BACKUP,要求MASTER節點感知到環境中存在別的MASTER節點,從而進入BACKUP狀態;

節點之間通過VRRP報文獲得相互的優先級及狀態信息,因此,可以通過在服務檢查失敗時,配置防火牆,禁止本機的VRRP報文發出即可。這樣,BACKUP節點收不到MASTER節點的VRRP報文,認爲MASTER節點不存在,同時MASTER節點能收到其他節點的VRRP報文,感知到新MASTER的產生,從而進入BACKUP狀態。

配置如下(僅以devops1a-zoocassa0爲例,其他節點類推):

# devops1a-zoocassa0 /etc/keepalived/keepalived.conf

vrrp_script chk_memcached {
    script "/etc/keepalived/check_memcached.sh"
    interval 5
    weight 3
}

vrrp_instance VI_1 {
    interface eth0
    state BACKUP
    virtual_router_id 55
    nopreempt
    priority 101

    unicast_src_ip 172.31.23.22
    unicast_peer {
        172.31.23.23
        172.31.23.24
    }
    virtual_ipaddress {
        172.31.23.6                       
    }
    track_script {
        chk_memcached
    }
}
# devops1a-zoocassa0  /etc/keepalived/chk_memcached.sh

#!/bin/bash
killall -0 memcached                            #檢查memcached服務
if [[ $? == 0 ]];then                           #檢查成功
  /sbin/iptables -L | grep vrrp
  if [[ $? == 0 ]]; then                        #如果iptable中有vrrp的配置,刪除它
    /sbin/iptables -D OUTPUT -p vrrp -j DROP
  fi
  exit 0
else                                            #檢查失敗
  /sbin/iptables -L | grep vrrp
  if [[ $? != 0 ]]; then
    /sbin/iptables -A OUTPUT -p vrrp -j DROP    #如果iptable中沒有vrrp的條目,禁止vrrp發出
  fi
  exit 1
fi

重啓keepalived服務,測試成功。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章