keepalived 實現LVS DR 模型的高可用

LVS的工作類型:

   lvs-nat

    Network Address Translation

   lvs-dr

    Direct Routing

   lvs-tun

    Tunneling

   nat類型的特性:

    1、RS應用使用私有地址;RS的網關必須指向DIP;

    2、請求和響應都要經過Director;高負載場景中,Director易成爲性能瓶頸;

    3、支持端口映射;

    4、RS可以使用任意OS;

附: 傳說這樣的工作特性不好,只能帶動10臺左右的RS,所以生產環境幾乎不用.

   dr類型的特性:

    1、保證前端路由將目標地址爲VIP的報文統統發往Directory,而不能是RS;

     解決方案:

      (1) 靜態地址綁定:在前端路由器上操作

       問題:未必有路由操作權限

      (2) aprtables

      (3) 修改RS上內核參數,將RS上的VIP配置在lo接口的別名上,並限制其不能響應對VIP地址解析請求;

    2、RS可以使用私有地址;但也可以使用公網地址,此時可通過互聯網通過RIP對其直接訪問;

    3、RS跟Directory必須在同一物理網絡中 [容災功能不好,比如地震,火災什麼的];

    4、請求報文經由Director,但響應報文必須不能經過Director[否則和nat的工作類型有什麼區別呢],

            所以得是由 RS直接響應給客戶端.

    5、不支持端口映射;

    6、RS可以是大多數常見的OS;

    7、RS的網關絕不允許指向DIP;

   tun類型的特性:

    1、RIP、VIP、DIP全部是公網地址;

    2、RS的網關不會也不可能指向DIP;

    3、請求報文經由Director,但響應報文必須不能經過Director;

    4、不支持端口映射;

    5、RS的OS必須支持隧道功能;

# grep -i 'VS' /boot/config-VERSION

  靜態方法:僅根據調度算法本身進行調度

   rr: round robin,輪流,輪詢,輪叫 . 工作時rs節點遂一輪換,做到起點公平,缺點 , 有些服務器性能差,一個任務還沒完成,下一個又來了,而有的服務器性能好,一個任務一會處理好,積累到一定時間

    性能差的服務器抗不住了,性能好的服務器還閒得慌.

   wrr: weighted round robin, 加權輪詢 , 比rr有進步,但是還是不怎麼靠譜,缺點和rr類似, 好不到哪去.

   sh: source hashing,源地址hash,表示來源於同一個CIP的請求將始終被定向至同一個RS;SESSION保持;  每一個客戶端訪問時都會由服務端發一個cookie的標識,下次這個客戶端發起訪問時

還是會由同一臺服務器進行響應,除非是這臺服務器真的忙不過來時,才勉爲其難的分發到別的服務器上去.

   dh: destination hashing, 目標地址hash,

  動態方法:根據算法及各RS當前的負載狀況進行調度 . 是一種結果公平的調度算法

   lc: least connection,最少連接 ,  根據權重計算公式,看誰的計算值最小,下一個處理任務就會分發過來,可問題是一開始,每一個RS都沒有任務,計算結果都是0, 來了個業務,很可能會發給性能最差的服務器

    Overhead=Active*256+Inactive

   wlc: weighted lc

    Overhead=(Active*256+Inactive)/weight   ==>根據算法的公式可知, 性能差,權重低的,仍然可能是第一個分配處理任務的

    A: 1,

    B: 5,

   sed: shortest expection delay                 ==>很有可能權重高,性能好的服務器都處理了好些任務,而權重低的一個任務都沒接

    Overhead=(Active+1)*256/weight

    1: B

    2: B

    3: B

    4: B

   nq: Never Queue  ==>永不排除的調度方法, 一開始從權重最高的服務器開始,依次每臺服務器分發處理請求,保證了每臺服務器都有事可做

   lblc: Locality-Based Least Connection 本地最小連接數的

   lblcr:Replicated lblc    帶複製功能的lblc

在這裏,我們選用 dr模型來實現,拓普圖如下

clipboard

需要注意以下幾點.

1、禁止RealServer響應對VIP的ARP請求;

2、在RealServer上隱藏VIP,以使得它們無法獲知網絡上的ARP請求;

3、基於“透明代理(Transparent Proxy)”或者“fwmark (firewall mark)”;

4、禁止ARP請求發往RealServers;

傳統認爲,解決ARP問題可以基於網絡接口,也可以基於主機來實現。Linux採用了基於主機的方式,因爲其可以在大多場景中工作良好,但LVS卻並不屬於這些場景之一,

因此,過去實現此功能相當麻煩。現在可以通過設置arp_ignore和arp_announce,這變得相對簡單的多了。

Linux 2.2和2.4(2.4.26之前的版本)的內核解決“ARP問題”的方法各不相同,且比較麻煩。幸運的是,2.4.26和2.6的內核中引入了兩個新的調整ARP棧的標誌(device flags):

arp_announce和arp_ignore。基於此,在DR/TUN的環境中,所有IPVS相關的設定均可使用arp_announce=2和arp_ignore=1/2/3來解決“ARP問題”了。

官方文檔的參數解釋如下

arp_annouce:Define different restriction levels for announcing the local source IP address from IP packets in ARP requests sent on interface;

0 - (default) Use any local address, configured on any interface.

1 - Try to avoid local addresses that are not in the target's subnet for this interface.

2 - Always use the best local address for this target.

arp_ignore: Define different modes for sending replies in response to received ARP requests that resolve local target IP address.

0 - (default): reply for any local target IP address, configured on any interface.

1 - reply only if the target IP address is local address configured on the incoming interface.

2 - reply only if the target IP address is local address configured on the incoming interface and both with the sender's IP address are part from same subnet on this interface.

3 - do not reply for local address configured with scope host, only resolutions for golbal and link addresses are replied.

4-7 - reserved

8 - do not reply for all local addresses

中文翻譯如下

arp_announce :對網絡接口上,本地IP地址的發出的,ARP迴應,作出相應級別的限制: 確定不同程度的限制,宣佈對來自本地源IP地址發出Arp請求的接口

0 - (默認) 在任意網絡接口(eth0,eth1,lo)上的任何本地地址

1 -儘量避免不在該網絡接口子網段的本地地址做出arp迴應. 當發起ARP請求的源IP地址是被設置應該經由路由達到此網絡接口的時候很有用.此時會檢查來訪IP是否爲所有接口上的子網段內ip之一.如果改來訪IP不屬於各個網絡接口上的子網段內,那麼將採用級別2的方式來進行處理.

2 - 對查詢目標使用最適當的本地地址.在此模式下將忽略這個IP數據包的源地址並嘗試選擇與能與該地址通信的本地地址.首要是選擇所有的網絡接口的子網中外出訪問子網中包含該目標IP地址的本地地址. 如果沒有合適的地址被發現,將選擇當前的發送網絡接口或其他的有可能接受到該ARP迴應的網絡接口來進行發送.

arp_ignore:定義對目標地址爲本地IP的ARP詢問不同的應答模式0

0 - (默認值): 迴應任何網絡接口上對任何本地IP地址的arp查詢請求

1 - 只回答目標IP地址是來訪網絡接口本地地址的ARP查詢請求

2 -只回答目標IP地址是來訪網絡接口本地地址的ARP查詢請求,且來訪IP必須在該網絡接口的子網段內

3 - 不迴應該網絡界面的arp請求,而只對設置的唯一和連接地址做出迴應

4-7 - 保留未使用

8 -不迴應所有(本地地址)的arp查詢

按以上的內容來看,滿足我們需要的是 將 arp_announce  參數設置爲 2 , arp_ignore 參數設置爲1.

# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore    
# echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore    
# echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce    
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce    這是臨時生效的,要想永久有效,得改配置文件

介紹完了keepalived ,現在來討論keepalived .  因爲keepalived可以在配置文件中實現對lvs的配置

所以無需使用 ipvsadm -A 的方式來定義lvs集羣,所以ipvsadm工具,不安裝也行, 但是如果想查看由keepalived

生成的ipvs規則,但裝也無妨

# yum install ipvsadm -y

keepalived 實現的是一個虛擬容餘路由的功能.

vrrp: virtual redundent routing protocol 

  生成路由:

   靜態路由

   動態路由:OSPF, RIP2

LAN客戶端判定哪個路由器應該爲其到達目標主機的下一跳網關的方式有動態及靜態決策兩種方式,其中,常見的動態路由發現方式有如下幾種:

1、Proxy ARP —— 客戶端使用ARP協議獲取其想要到達的目標,而後,由某路由以其MAC地址響應此ARP請求;

2、Routing Protocol —— 客戶端監聽動態路由更新(如通過RIP或OSPF協議)並以之重建自己的路由表;

3、ICMP IRDP (Router Discovery Protocol) 客戶端 —— 客戶端主機運行一個ICMP路由發現客戶端程序;

動態路由發現協議的不足之處在於它會導致在客戶端引起一定的配置和處理方面的開銷,並且,如果路由器故障,切換至其它路由器的過程會比較慢。

解決此類問題的一個方案是爲客戶端靜態配置默認路由設備,這大大簡化了客戶端的處理過程,但也會帶來單點故障類的問題。默認網關故障時,

LAN客戶端僅能實現本地通信。VRRP可以通過在一組路由器(一個VRRP組)之間共享一個虛擬IP(VIP)解決靜態配置的問題,此時僅需要客戶端以VIP作爲其默認網關即可。

VRRP的優勢:

冗餘:可以使用多個路由器設備作爲LAN客戶端的默認網關,大大降低了默認網關成爲單點故障的可能性;

負載共享:允許來自LAN客戶端的流量由多個路由器設備所共享;

多VRRP組:在一個路由器物理接口上可配置多達255個VRRP組;

多IP地址:基於接口別名在同一個物理接口上配置多個IP地址,從而支持在同一個物理接口上接入多個子網;

搶佔:在master故障時允許優先級更高的backup成爲master;

通告協議:使用IANA所指定的組播地址224.0.0.18進行VRRP通告;

VRRP追蹤:基於接口狀態來改變其VRRP優先級來確定最佳的VRRP路由器成爲master;

IP地址擁有者(IP Address Owner):如果一個VRRP設備將虛擬路由器IP地址作爲真實的接口地址,則該設備被稱爲IP地址擁有者。

如果IP地址擁有者是可用的,通常它將成爲Master。

介紹完keepalived,我們開始小試牛刀, 在172.16.26.6,和172.16.26.11節點上配置keepalived 高可用

yum install keepalived -y

[root@localhost ~]# rpm -ql keepalived         =>查看安裝keepalived生成的配置文件  
/etc/keepalived    
/etc/keepalived/keepalived.conf    
/etc/rc.d/init.d/keepalived    
/etc/sysconfig/keepalived    
/usr/bin/genhash    
/usr/sbin/keepalived

編輯 /etc/keepalived/keepalived.conf 配置文件

172.16.26.6   主機上的設置

global_defs {   notification_email {    [email protected]  發生改變時通知的郵件地址    }    notification_email_from root
smtp_server 127.0.0.1          =>郵件服務器定義
smtp_connect_timeout 30 =>郵件服務器連接超時時長設置
router_id LVS_DEVEL          =>設置路由節點id
}   vrrp_instance VI_1 {     =>定義策略一 
    state MASTER    =>設置爲該節點的主服務器
    interface eth0    =>網絡接口爲網卡eth0
    virtual_router_id 11    =>定義虛擬路由id
    priority 100            =>權重設定爲100
    advert_int 1            =>每隔一秒檢測一次
    authentication {
        auth_type PASS    =>認證帳戶
        auth_pass 1111    =>認證口令
    }
    virtual_ipaddress {
        172.16.26.100/16    =>設定ipvs 規則的虛擬ip
    }
}
virtual_server 172.16.26.100 80 {    =>設定ipvs 虛擬ip中的屬性
    delay_loop 6   
    lb_algo rr                    =>輪詢的算法
    lb_kind DR                    =>使用ipvs的 DR模型
    nat_mask 255.255.0.0    =>網關掩碼
    persistence_timeout 50    =>超時時長
    protocol TCP    =>定義工作模式
sorry_server 127.0.0.1 80    =>如果虛擬節點都無法正常訪問,所指向的sorry_server
    real_server 172.16.26.1 80 {    =>ipvs 的節點
        weight 1
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 1
        }
    }
    real_server 172.16.26.5 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 1
        }
}
#下面的 第二條規則 , 語法定義解釋參照上面的條目
vrrp_instance VI_2 {
    state BACKUP
    interface eth0
    virtual_router_id 12
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.16.26.101/16
    }
}
virtual_server 172.16.26.101 80 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    nat_mask 255.255.0.0
    persistence_timeout 50
    protocol TCP
sorry_server 127.0.0.1 80
    real_server 172.16.26.1 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 1
        }
    }
    real_server 172.16.26.5 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 1
        }
}

172.16.26.11   主機上的設置

! Configuration File for keepalived   
global_defs {    
notification_email {    
[email protected]
    
}    
notification_email_from root    
smtp_server 127.0.0.1    
smtp_connect_timeout 30    
router_id LVS_DEVEL    
}    
vrrp_instance VI_1 {    
state BACKUP    
interface eth0    
virtual_router_id 11    
priority 99    
advert_int 1    
authentication {    
auth_type PASS    
auth_pass 1111    
}    
virtual_ipaddress {    
172.16.26.100/16    
}    
}    
virtual_server 172.16.26.100 80 {    
delay_loop 6    
lb_algo rr    
lb_kind DR    
nat_mask 255.255.0.0    
persistence_timeout 50    
protocol TCP    
sorry_server 127.0.0.1 80    
real_server 172.16.26.1 80 {    
weight 1    
HTTP_GET {    
url {    
path /    
status_code 200    
}    
connect_timeout 3    
nb_get_retry 3    
delay_before_retry 1    
}    
}    
real_server 172.16.26.5 80 {    
weight 1    
HTTP_GET {    
url {    
path /    
status_code 200    
}    
connect_timeout 3    
nb_get_retry 3    
delay_before_retry 1    
}    
}    
vrrp_instance VI_2 {    
state MASTER    
interface eth0    
virtual_router_id 12    
priority 100    
advert_int 1    
authentication {    
auth_type PASS    
auth_pass 1111    
}    
virtual_ipaddress {    
172.16.26.101/16    
}    
}    
virtual_server 172.16.26.101 80 {    
delay_loop 6    
lb_algo rr    
lb_kind DR    
nat_mask 255.255.0.0    
persistence_timeout 50    
protocol TCP    
sorry_server 127.0.0.1 80    
real_server 172.16.26.1 80 {    
weight 1    
HTTP_GET {    
url {    
path /    
status_code 200    
}    
connect_timeout 3    
nb_get_retry 3    
delay_before_retry 1    
}    
}    
real_server 172.16.26.5 80 {    
weight 1    
HTTP_GET {    
url {    
path /    
status_code 200    
}    
connect_timeout 3    
nb_get_retry 3    
delay_before_retry 1    
}    
}

此時,我們先啓動 172.16.26.11節點的keepalived的服務

[root@mode_11 keepalived]# tail /var/log/messages             =>查看日誌文件    
Sep 21 21:11:06 mode_11 Keepalived_vrrp[7736]: VRRP_Instance(VI_2) Entering MASTER STATE    
Sep 21 21:11:06 mode_11 Keepalived_vrrp[7736]: VRRP_Instance(VI_2) setting protocol VIPs.    
Sep 21 21:11:06 mode_11 Keepalived_vrrp[7736]: VRRP_Instance(VI_2) Sending gratuitous ARPs on eth0 for 172.16.26.101    
Sep 21 21:11:06 mode_11 Keepalived_healthcheckers[7735]: Netlink reflector reports IP 172.16.26.101 added    
Sep 21 21:11:07 mode_11 Keepalived_vrrp[7736]: VRRP_Instance(VI_1) Transition to MASTER STATE    
Sep 21 21:11:08 mode_11 Keepalived_vrrp[7736]: VRRP_Instance(VI_1) Entering MASTER STATE    
Sep 21 21:11:08 mode_11 Keepalived_vrrp[7736]: VRRP_Instance(VI_1) setting protocol VIPs.    
Sep 21 21:11:08 mode_11 Keepalived_healthcheckers[7735]: Netlink reflector reports IP 172.16.26.100 added                         
Sep 21 21:11:08 mode_11 Keepalived_vrrp[7736]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.16.26.100    
Sep 21 21:11:11 mode_11 Keepalived_vrrp[7736]: VRRP_Instance(VI_2) Sending gratuitous ARPs on eth0 for 172.16.26.101

=>因爲只有它自己一個keepalived節點啓動, 把172.16.26.100,172.16.26.100都配置到自己的網卡上了

clipboard[1]    
[root@mode_11 keepalived]# ipvsadm -Ln     =>查看一下集羣條目    
IP Virtual Server version 1.2.1 (size=4096)    
Prot LocalAddress:Port Scheduler Flags    
-> RemoteAddress:Port Forward Weight ActiveConn InActConn    
TCP 172.16.26.100:80 rr persistent 50    
-> 172.16.26.1:80 Route 1 0 0    
-> 172.16.26.5:80 Route 1 0 0    
TCP 172.16.26.101:80 rr persistent 50    
-> 172.16.26.1:80 Route 1 0 0    
-> 172.16.26.5:80 Route 1 0 0        =>集羣已然在列

現在啓動 172.16.26.6節點上的 keepalived服務

[root@php5_6 keepalived]# service keepalived start

clipboard[2]

此時,因爲上面配置的該節點擁有172.16.26.100 ip的權重高,所以它就把這個ip配置到自己的網卡上了

172.16.26.1和172.16.26.5上都進行如下操作

# ifconfig lo:0 172.16.26.100 netmask 255.255.255.255 broadcast 172.16.26.100 up     =>給lo 起兩別名, 添加兩個虛擬地址  
# ifconfig lo:1 172.16.26.101 netmask 255.255.255.255 broadcast 172.16.26.101 up  
# route add -host 172.16.26.100 dev lo    而且必須是訪問 lo口上擁有的ip才能允許報文進來    
# route add -host 172.16.26.101 dev lo

# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce     只通告本接口擁有的ip地址

# echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce  
# echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore =>只響應目標IP地址是來訪網絡接口本地地址的ARP查詢請求    
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore

clipboard[3]

clipboard[4]

訪問兩個 virtual ip 都能解析到後端主機上,實驗OK

# service keepalived stop =>我們停掉一個節點,測試一下兩個vip的訪問都是否正常

clipboard[5]

clipboard[6]

OK,實驗完成,實現了高可用.

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