web-dev-qa-db-ja.com

keepalivedを実行している両方のサーバーがマスターになります

ネットワーク障害が発生すると、keepalivedを実行している両方のサーバーがマスターになります。

ネットワークが再確立されると、両方ともMASTER状態を維持します。

何が原因でしょうか?

編集済み:関連する可能性のある別の情報。各サーバーには2つのNICがあります。

仮想インスタンスの構成は次のとおりです。

vrrp_instance VGAPP {
    interface eth0
    virtual_router_id 61
    state BACKUP
    nopreempt
    priority 50
    advert_int 3
    virtual_ipaddress {
        10.26.57.61/24
    }
    track_interface {
       eth0
    }
    track_script {
        jboss_check
        #Tomcat_check
        #interface_check
        #interface_check02
    }
    notify_master "/opt/keepalived/scripts/set_state.sh MASTER"
    notify_backup "/opt/keepalived/scripts/set_state.sh BACKUP"
    notify_fault  "/opt/keepalived/scripts/set_state.sh FAULT"
    notify_stop   "/opt/keepalived/scripts/set_state.sh STOPPED"}
2
pcent

これは実際にはバグを引き起こす可能性があります。自分で直さなければならなかったので知っています。

RFCによると、優先順位が両方のノードで等しい場合。

        If the Priority in the ADVERTISEMENT is equal to the local
        Priority and the primary IP Address of the sender is greater
        than the local primary IP Address, then:

         o Cancel Adver_Timer
         o Set Master_Down_Timer to Master_Down_Interval
         o Transition to the {Backup} state

したがって、最大のIPアドレスを持っている人が勝ちます。

Keepalivedでは、これが行われる方法は基本的に間違っています。この比較を行う場合、エンディアンは適切に考慮されません。

(A)10.1.1.200と(B)10.1.1.201の2つのルーターがあると想像してみてください。

コードは次の比較を実行する必要があります

Aについて:

if (10.1.1.201 > 10.1.1.200) // True
   be_backup();

Bの場合:

if (10.1.1.200 > 10.1.1.201) // False
  be_master();

ただし、エンディアンが誤って処理されないため、代わりに次の比較が行われます。

Aについて:

if (10.1.1.201 > 200.1.1.10) // False
  be_master();

Bの場合:

if (10.1.1.200 > 201.1.1.10) // False
  be_master();

このパッチは動作するはずですが、元のパッチから作り直して、notテストしました。コンパイルすらテストされていません!だから払い戻しはありません!

--- vrrp/vrrp.c.old 2013-10-13 17:39:29.421000176 +0100
+++ vrrp/vrrp.c 2013-10-13 18:07:57.360000966 +0100
@@ -923,7 +923,7 @@
    } else if (vrrp->family == AF_INET) {
        if (hd->priority > vrrp->effective_priority ||
            (hd->priority == vrrp->effective_priority &&
-            ntohl(saddr) > ntohl(VRRP_PKT_SADDR(vrrp)))) {
+            ntohl(saddr) > VRRP_PKT_SADDR(vrrp))) {
            log_message(LOG_INFO, "VRRP_Instance(%s) Received higher prio advert"
                        , vrrp->iname);
            if (proto == IPPROTO_IPSEC_AH) {
3
Matthew Ife

ここに掲載されているソリューションをお試しください。

VRRPマスターが失敗するとマスターにならないようにする

0
Sameer