基於LVS的Linux負載均衡技術實現(第二篇:基本NAT和DR結構的LVS集群構建)

火星人 @ 2014-03-04 , reply:0


下面是第一個實際的LVS配置的例子,整個的結構是基於NAT操作。在該例子中的結構比較簡單:

上面的例子中,我暫時沒有添加備份LVS Router,而只是通過一個主LVS Router來充當調度器。
配置步驟如下:
首先配置網路參數:
在LVS Router上的基本參數:
# ifconfig | grep inet
          inet addr:192.168.1.10  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe08:a162/64 Scope:Link
          inet addr:10.0.0.10  Bcast:10.0.255.255  Mask:255.255.0.0
          inet6 addr: fe80::20c:29ff:fe08:a16c/64 Scope:Link
# sysctl -a | grep ip_forward
net.ipv4.ip_forward = 1
# sysctl –p

在Real Server上的基本參數:
第一台:
# cat /etc/sysconfig/network-scripts/ifcfg-eth0
# Advanced Micro Devices 79c970
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static
HWADDR=00:0c:29:b2:60:a5
IPADDR=10.0.0.100
NETMASK=255.255.0.0
GATEWAY=10.0.0.254
第二台:
# cat /etc/sysconfig/network-scripts/ifcfg-eth0
# Advanced Micro Devices 79c970
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static
HWADDR=00:0c:29:b2:60:a5
IPADDR=10.0.0.200
NETMASK=255.255.0.0
GATEWAY=10.0.0.254

然後在LVS Router上安裝piranha工具:
# rpm -ihv ipvsadm-1.24.8.1.i386.rpm
# rpm -ihv piranha-0.8.4-7.el5.i386.rpm
完成之後為piranha-gui設置密碼並啟動服務:
# /usr/sbin/piranha-passwd
New Password:
Verify:
Updating password for user piranha

# service piranha-gui restart
Shutting down piranha-gui: [  OK  ]
Starting piranha-gui: [  OK  ]
# chkconfig piranha-gui on

完成之後進入圖形界面並在瀏覽器中輸入:http://localhost:3636,輸入用戶名:piranha和剛才定義的密碼,即可進入piranha configuration tool的配置界面:
在該界面中第一個要設置的地方是CONTROL/MONITORING,在該界面中將MONITOR中的選項:
Auto update勾選上,Update Interval將自動定義為10s,在服務沒有啟動之前LVS ROUTING TABLE和LVS PROCESS都不可見。完成之後選擇Update information now。

在該界面的第二個要設置的地方是GLOBAL SETTINGS,在該界面中:
Primary server public IP:192.168.1.10                (真實外部地址)
Primary server private IP:10.0.0.10                   (真實內部地址)
Use network type:          NAT                          (LVS方式)
NAT Router IP:               10.0.0.254                 (內部浮動IP)
NAT Router MASK:          255.255.0.0               (內部浮動掩碼)
NAT Router Device:          eth1:1                     (運行浮動IP的設備)
選擇接受配置
        
在該界面的第三個要設置的地方是REDUNDANCY,在該界面中:
由於沒有在這個結構中加入冗餘配置,所以可以將其DISABLE掉或者將其設置為ENABLE但是保持配置為空。在該例子中我的配置為空:
Redundant server public IP:                0.0.0.0
Redundant server private IP:
Heartbeat Interval (seconds):          6
Assume dead after (seconds):         18
Heartbeat runs on port:                     539
Monitor NIC links for failure:               不勾選
選擇接受配置

在該界面的第四個要設置的地方是VIRTUAL SERVERS:
每一個Virtual Servers代表所提供的一種服務,由於目前只有一種服務HTTP,所以選擇ADD在提示中輸入下面的信息:
Name:                                        HTTP
Application port:                          80
Protocal:                                    TCP
Virtual Server Address:                 192.168.1.250
Virtual IP Network Mask:               255.255.255.0
Firewall Mark:                        
Device:                                      eth0:1
Re-entry Time:                            15
Service Timeout:                          6
Quiesce:                                     No
Load Monitor Tool:                        none
Scheduling:                                 Weighted least-connections                        --加權最小連接法(默認)
Persistence:                                
Persistence Network Mask:             Unused
選擇接受,並開啟服務

在該界面的第五個要設置的地方是REAL SERVERS:
Name:                                        localhost.localdomain
Address:                                    10.0.0.100
Weighted:                                  1
Name:                                       localhost.localdomain
Address:                                    10.0.0.200
Weighted:                                  1
選擇接受,並開啟服務

在該界面的第六個要設置的地方是MONITORING SCRIPTS,保持默認即可

完成之後確認所有的配置都已經保存,這個LVS基本上就配置完成。最後的工作是在LVS的Router上啟動主服務:
# service pulse start
# chkconfig pulse on
這個時候可以看到eth0:1和eth1:1已經自動建立:
# ifconfig
eth0:1    Link encap:Ethernet  HWaddr 00:0C:29:08:A1:62  
          inet addr:192.168.1.250  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
eth1:1    Link encap:Ethernet  HWaddr 00:0C:29:08:A1:6C  
          inet addr:10.0.0.254  Bcast:10.0.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:19 Base address:0x2080
並且相關服務也開啟了:
# service ipvsadm status
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.1.250:80 wlc
  -> 10.0.0.200:80                Masq    1      0          0         
  -> 10.0.0.100:80                Masq    1      0          15        
# ps -ef | grep nanny
root      3614  3596  0 23:09 ?        00:00:03 /usr/sbin/nanny -c -h 10.0.0.100 -p 80 -s GET /
HTTP/1.0\r\n\r\n -x HTTP -a 15 -I /sbin/ipvsadm -t 6 -w 1 -V 192.168.1.250 -M m -U none --lvs
root      3615  3596  0 23:09 ?        00:00:03 /usr/sbin/nanny -c -h 10.0.0.200 -p 80 -s GET /
HTTP/1.0\r\n\r\n -x HTTP -a 15 -I /sbin/ipvsadm -t 6 -w 1 -V 192.168.1.250 -M m -U none --lvs
root      4078  3632  0 23:56 pts/1    00:00:00 grep nanny

同時開啟兩台真實伺服器上的http服務,並在兩台主機上的服務目錄中分別建立同樣的測試頁面。
# chkconfig httpd on
# service httpd start

現在通過在客戶端上訪問LVS伺服器進行測試:http://192.168.1.250,可以看到real server給出了頁面。

這個時候piranha configuration tool界面刷新之後看到的當前ROUTER TABLE信息已經發生了改變:
CURRENT LVS ROUTING TABLE
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 wlc
-> 10.0.0.200:80 Masq 1 0 0
-> 10.0.0.100:80 Masq 1 0 0
而在當前LVS進程列表中也出現了內容:
CURRENT LVS PROCESSES
root 3678 0.0 0.1 1880 332 ? Ss 22:09 0:00 pulse
root 3702 0.0 0.2 1872 596 ? Ss 22:10 0:00 /usr/sbin/lvsd --nofork -c /etc/sysconfig/ha/lvs.cf
root 3720 0.0 0.2 1852 628 ? Ss 22:10 0:00 /usr/sbin/nanny -c -h 10.0.0.100 -p 80 -s GET / HTTP/1.0\r\n\r\n
-x HTTP -a 15 -I /sbin/ipvsadm -t 6 -w 1 -V 192.168.1.250 -M m -U none --lvs
root 3721 0.0 0.2 1852 628 ? Ss 22:10 0:00 /usr/sbin/nanny -c -h 10.0.0.200 -p 80 -s GET / HTTP/1.0\r\n\r\n
-x HTTP -a 15 -I /sbin/ipvsadm -t 6 -w 1 -V 192.168.1.250 -M m -U none --lvs

而在數次刷新頁面之後就可以看到CURRENT LVS ROUTING TABLE的內容有所更新:
# cat lvs
CURRENT LVS ROUTING TABLE
IP Virtual Server version 1.2.1 (size=4096)
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 wlc
-> 10.0.0.200:80 Masq 1 0 7
-> 10.0.0.100:80 Masq 1 0 6

也就是說訪問量被平均分配到了兩台主機上,如果我們找另外一個客戶端做簡單的壓力測試:
命令:# ab -c 1000 -n 100000 http://192.168.1.250/index.html
獲得的LVS ROUTING TABLE如下:
# cat Desktop/lvs
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.250:80 wlc
-> 10.0.0.200:80 Masq 1 0 317
-> 10.0.0.100:80 Masq 1 0 1007

由於採用的是加權最小連接演演算法,所以負載不可能均分到兩台伺服器上。
此時配置文件的內容:
# cat /etc/sysconfig/ha/lvs.cf
serial_no = 67
primary = 192.168.1.10
primary_private = 10.0.0.10
service = lvs
backup_active = 1
backup = 0.0.0.0
heartbeat = 1
heartbeat_port = 539
keepalive = 6
deadtime = 18
network = nat
nat_router = 10.0.0.254 eth1:1
nat_nmask = 255.255.0.0
debug_level = NONE
monitor_links = 0
virtual HTTP {
     active = 1
     address = 192.168.1.250 eth0:1
     vip_nmask = 255.255.255.0
     port = 80
     send = "GET / HTTP/1.0\r\n\r\n"
     expect = "HTTP"
     use_regex = 0
     load_monitor = none
     scheduler = wlc
     protocol = tcp
     timeout = 6
     reentry = 15
     quiesce_server = 0
     server localhost.localdomain {
         address = 10.0.0.100
         active = 1
         weight = 1
     }
     server localhost.localdomain {
         address = 10.0.0.200
         active = 1
         weight = 1
     }
}
實驗到此成功。

現在我將這個實驗的結構稍微做一下擴展,按照紅帽所推薦的方案在結構中加入一備份 LVS ruoter,該備份LVS router的真實外網IP地址是192.168.1.20,真實內網IP是10.0.0.20。
按照上述的結構完成基本的網路配置:
# ifconfig | grep inet
          inet addr:192.168.1.20  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fecb:dd0b/64 Scope:Link
          inet addr:10.0.0.20  Bcast:10.0.255.255  Mask:255.255.0.0
          inet6 addr: fe80::20c:29ff:fecb:dd15/64 Scope:Link
開啟IP轉發:
        # sysctl -a | grep ip_forward
net.ipv4.ip_forward = 1

安裝lvs相關軟體包並進行基本配置:
# rpm -ihv ipvsadm-1.24.8.1.i386.rpm
# rpm -ihv piranha-0.8.4-7.el5.i386.rpm
完成之後為piranha-gui設置密碼並啟動服務:
# /usr/sbin/piranha-passwd
New Password:
Verify:
Updating password for user piranha

# service piranha-gui restart
Shutting down piranha-gui: [  OK  ]
Starting piranha-gui: [  OK  ]
# chkconfig piranha-gui on

這裡我偷了一個懶,因為不想再向第一台LVS Router那樣一個一個通過piranha configuration tool配置參數,所以用scp將lvs.cf同步過來,並且開啟服務:
# service pulse start
# chkconfig pulse on
完成之後進入圖形界面,在瀏覽器中登錄piranha configuration tools,需要修改的地方實際上有兩處:
在該界面的第三個要設置的地方REDUNDANCY添加冗餘配置:
Redundant server public IP:                192.168.1.20
Redundant server private IP:              10.0.0.20
Heartbeat Interval (seconds):          6
Assume dead after (seconds):          18
Heartbeat runs on port:                     539
Monitor NIC links for failure:                不勾選
選擇接受配置
另外在第一台LVS Router上也要做這方面的定義。

在該界面的第二個要設置的地方是GLOBAL SETTINGS,在該界面中:
Primary server public IP: 192.168.2.10                   (真實外部地址)
Primary server private IP:10.0.0.20                        (真實內部地址)
Use network type:          NAT                              (LVS方式)
NAT Router IP:               10.0.0.254                     (內部浮動IP)
NAT Router MASK:          255.255.0.0                    (內部浮動掩碼)
NAT Router Device:         eth1:1                          (運行浮動IP的設備)
選擇接受配置
        
這樣的話,配置文件的內容為:
# cat /etc/sysconfig/ha/lvs.cf
serial_no = 73
primary = 192.168.1.20
primary_private = 10.0.0.20
service = lvs
backup_active = 1
backup = 192.168.1.20
backup_private = 10.0.0.20
heartbeat = 1
heartbeat_port = 539
keepalive = 6
deadtime = 18
network = nat
nat_router = 10.0.0.254 eth1:1
nat_nmask = 255.255.0.0
debug_level = NONE
monitor_links = 0
virtual HTTP {
     active = 1
     address = 192.168.1.250 eth0:1
     vip_nmask = 255.255.255.0
     port = 80
     send = "GET / HTTP/1.0rnrn"
     expect = "HTTP"
     use_regex = 0
     load_monitor = none
     scheduler = wlc
     protocol = tcp
     timeout = 6
     reentry = 15
     quiesce_server = 0
     server localhost.localdomain {
         address = 10.0.0.100
         active = 1
         weight = 1
     }
     server localhost.localdomain {
         address = 10.0.0.200
         active = 1
         weight = 1
     }
}

測試的方法很簡單,第一台LVS Router現在是primary,那麼正常情況下他提供服務,而備份lvs router開啟pulse進程對第一台狀態進行監控。現在將第一台LVS Router關閉,在短時間內客戶端訪問虛擬伺服器將受到影響。但是在大概十秒左右的時間就可以訪問成功,此時可以看到備份LVS Router已經成為primary並提供服務。如果此時再將已經關閉的第一台LVS Router開啟,那麼他將再次成為主LVS Router。

不過現在REDHAT是商業行為
用redhat的應該也不是很好,畢竟是一種非法的copy
推薦的還是centos 社區版本,畢竟這個都可以獲得,也沒有什麼install number的困擾

和NAT結構所不同的是,該LVS集群通過DR也就是direct route來實現。所謂direct route指的是LVS Router會將請求轉發到真實伺服器上,而每一台真實伺服器都有能力通過一個特定的網關直接將外部請求轉發出去。也就是說反饋的應答不會再通過原路即LVS Router走,而是通過其他出口出去。
這樣做的好處是可以防止在大規模的LVS集群中因為調度器的性能問題而產生瓶頸,因此效率方面肯定要比NAT高。下面是一個基於DR實現的LVS結構圖。我主要是在沿用上一個實驗的一些結果。而DR和NAT的結構會有所改變。

下面的結構圖是一個採用DR結構的實例:
如上圖所示,我用一台windows主機做客戶端,他的請求通過一台Linux路由器發送到LVS Router上。然後LVS Router再將請求轉發到real server。而real server為了能夠將請求不通過LVS Router轉發出去則將網關直接指向了Router的內部介面。相當於每台real server都有直接將請求轉發出去的能力,這樣可以從很大程度上減少LVS Router的負載。

配置上面和剛才不同的地方是:
1.建立一台雙網卡的Linux Router,並且開啟ip_forward。
2.建立windows機器,配置地址為192.168.100.111,網關為192.168.100.30。
3.在主/備LVS Router上將網關指向Router的內部介面,並且重啟網路和LVS相關服務。
4.比較關鍵的修改是real server上,需要將網關都指向Router的內部介面,這裡是192.168.1.30。
5.必須在所有的real server上建立一個ifcfg-lo:1的介面,該介面的內容如下:
# cat /etc/sysconfig/network-scripts/ifcfg-lo:1
DEVICE=lo:1
IPADDR=192.168.1.250
NETMASK=255.255.255.255
NETWORK=192.168.1.250
ARP=no
TYPE=Ethernet
並且兩台主機的ifcfg-lo:1文件內容是一樣的。
(當時我曾經將子網掩碼更改為255.255.255.0,結果出乎我意料,兩台realserver只有一台能夠啟動網路,另外一台real server在啟動網路的時候報錯,提示地址被佔用)
我猜測,添加這個介面的目的是要real server在收到請求之後能夠冒充LVS Router對外部請求應答。

那麼通過piranha所需要修改的地方包括:
a.取消private的地址;
b.更改real server地址為192.168.1.111和192.168.1.222
c.更改LVS類型為DR
完成之後保存,這是我在主LVS Router上獲取的配置文件:
# cat /etc/sysconfig/ha/lvs.cf
serial_no = 122
primary = 192.168.1.10
service = lvs
backup_active = 1
backup = 192.168.1.20
heartbeat = 1
heartbeat_port = 539
keepalive = 6
deadtime = 18
network = direct
nat_nmask = 255.255.255.0
debug_level = NONE
monitor_links = 1
virtual HTTP {
     active = 1
     address = 192.168.1.250 eth0:1
     vip_nmask = 255.255.255.0
     port = 80
     send = "GET / HTTP/1.0\r\n\r\n"
     expect = "HTTP"
     use_regex = 0
     load_monitor = none
     scheduler = wlc
     protocol = tcp
     timeout = 6
     reentry = 15
     quiesce_server = 0
     server localhost.localdomain {
         address = 192.168.1.111
         active = 1
         weight = 1
     }
     server localhost.localdomain {
         address = 192.168.1.222
         active = 1
         weight = 1
     }
}

同時對備份LVS Router在原來基礎上進行了一些修改,配置文件內容為:
# cat /etc/sysconfig/ha/lvs.cf
serial_no = 122
primary = 192.168.1.20
service = lvs
backup_active = 1
backup = 192.168.1.20
heartbeat = 1
heartbeat_port = 539
keepalive = 6
deadtime = 18
network = direct
nat_nmask = 255.255.255.0
debug_level = NONE
monitor_links = 1
virtual HTTP {
     active = 1
     address = 192.168.1.250 eth0:1
     vip_nmask = 255.255.255.0
     port = 80
     send = "GET / HTTP/1.0\r\n\r\n"
     expect = "HTTP"
     use_regex = 0
     load_monitor = none
     scheduler = wlc
     protocol = tcp
     timeout = 6
     reentry = 15
     quiesce_server = 0
     server localhost.localdomain {
         address = 192.168.1.111
         active = 1
         weight = 1
     }
     server localhost.localdomain {
         address = 192.168.1.222
         active = 1
         weight = 1
     }
}
注意我用藍色標出的地方。有些人的配置中主/備LVS Router的配置文件是完全不一樣的。儘管我沒有測試過但是我總認為這樣可能會導致一些問題的出現。
完成之後重啟network以及lvs相關服務:pulse和ipvsadm。
檢查服務:
主LVS Router上的信息:
# service pulse status
pulse (pid 3664) is running...
# service ipvsadm status
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.1.250:80 wlc
  -> 192.168.1.111:80             Route   1      0          0         
  -> 192.168.1.222:80             Route   1      0          0         
備份LVS Router上的信息:
# service pulse status
pulse (pid 17459 17457 2260) is running...
# service ipvsadm status
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.1.250:80 wlc
  -> 192.168.1.111:80             Route   1      0          0         
  -> 192.168.1.222:80             Route   1      0          0         

測試的時候可以在主/備LVS Router上開啟wireshark並抓包。和NAT一樣的是,如果default情況下有數據通過主LVS Router上過來的話,臨時關閉主LVS Router,備份LVS Router會立刻通過heartbeat發現主LVS Router狀態為失效,所以在這個時候如果在備份LVS Router上抓包會發現備份LVS Router此時會調用系統中的一個send_arp的命令向Router發送一個arp初始化信息,宣告原來的virtual server所對應的MAC地址改變,這個時候router會重新初始化mac-address-table。後續的外部請求將通過備份LVS Router進行轉發。

另外在LVS配置的時候,real server上需要在啟動系統之後檢查自身的地址192.168.1.111和192.168.1.222是否能起來。我碰到的問題是192.168.1.111和192.168.1.222這兩台真實伺服器在正常重啟之後這兩個地址無法生效。而需要執行命令ifup eth0命令將這兩個網卡帶起來。也就是說白了,這兩個地址不是很穩定。我的做法是可以將其加到/etc/rc.local文件中。在啟動的時候確保網路介面啟動。



[火星人 via ] 基於LVS的Linux負載均衡技術實現(第二篇:基本NAT和DR結構的LVS集群構建)已經有149次圍觀

http://www.coctec.com/docs/service/show-post-6943.html