1. 程式人生 > >lvs(linux virtual server)、keepalived

lvs(linux virtual server)、keepalived

multicast chan lob cer 數據同步 iptables 解析結果 smtp ice

Linux Cluster:

httpd: ab, ?benchmark;

系統的擴展方式:
Scale up:向上擴展;
×××能更好的服務器替代現有的服務器;
Scale out:向外擴展;
提供更多的服務器來滿足同一個需求;

集群:將多臺主機組織起來滿足某一特定需求;

集群類型:
1、LB:Load Balancing, 負載均衡集群;
負載均衡器,調度器;
上遊服務器(upstream server),後端服務器,“真”服務器(real server);
SPOF:Single Point Of Failure

2、HA:High Avalilability, 高可用集群;
Active:活動服務器
Passive:備用服務器

Availability = 平均無故障時間/(平均無故障時間+平均修復時間)
增大分子
減小分母:降低平均修復時間;
冗余:

90%, 95%, 99%, 99.9%, 99.99%, 99.999%

3、HP:High Performance:高性能集群
www.top500.org

DS:Distributed System
hadoop:
mapreduce
hdfs

LB集群的實現:
硬件:
F5 BIG-IP
Citrix Netscaler
A10 A10
Array
Redware
軟件:
lvs: Linux Virtual Server
haproxy
nginx
ats (apache traffic server)

perlbal

基於工作的協議層次劃分:
傳輸層:
lvs, haproxy (mode tcp)
應用層:
haproxy (mode http), nginx, ats, perlbal

HA集群的實現:
keepalived:通過實現vrrp協議來實現地址漂移;
AIS:
heartbeat
cman+rgmanager (RHCS: redhat cluster suite)
corosync+pacemaker

系統構建:分層、分割
分布式:應用、數據、存儲、計算

lvs:Linux Virtual Server

layer 4:四層交換,四層路由;
根據請求報文的目標IP和目標PORT將其轉發至後端主機集群中的某臺服務器(根據調度算法);

lvs工作於director的netfilter表的INPUT鏈,其數據流向PREROUTING------>INPUT------->POSTROUTING

lvs集群的術語:
vs:Virtual Server
Director, Dispatcher, Balancer
rs:Real Server

CIP: Client IP
Director Virtual IP: VIP
Directory IP: DIP
Real Server IP: RIP

負載均衡集群中設計時的要點:
(1) session保持;
session 綁定(sticky) (source ip hash);
session 集群(cluster) (multicast/broadcast/unicast);
session 服務器 (server);
(2) 數據共享;
共享存儲;
NAS:Network Attached Storage (文件級別);
SAN:Storage Area Network (塊級別);
DS:Distributed Storage;
數據同步:
rsync
...

lvs的類型:
lvs-nat
lvs-dr (direct routing)
lvs-tun (ip tunneling)
lvs-fullnat (同時改變請求報文的源IP和目標IP)

註意:前三種為標準類型;fullnat為後來添加的類型,內核默認可能不支持;

lvs-nat:
多目標的DNAT:通過將請求報文的目標地址和目標端口修改為挑選出某RS的RIP和PORT來實現;

(1) RIP和DIP應該使用私網地址,RS的網關應該指向DIP;
(2) 請求和響應報文都要經由director轉發;極高負載的場景中,Director可能會成為系統瓶頸;
(3) 支持端口映射;
(4) VS必須為Linux,RS可以是任意的OS;
(5) RS的RIP與Director的DIP必須在同一IP網絡;

lvs-dr:direct routing
通過修改請求報文的MAC地址進行轉發;IP首部不會發生變化(源IP為CIP,目標IP始終為VIP);

(1) 確保前端路由器將目標IP為VIP的請求報文一定會發送給Director;
解決方案:
1、靜態綁定;
2、禁止RS響應VIP的ARP請求;
(a) arptables;
(b) 修改各RS的內核參數,並把VIP配置在特定的接口上實現禁止其響應;
(2) RS的RIP可以使用私有地址,也可以使用公網地址;
(3) RS跟Director必須在同一物理網絡中;
(4) 請求報文必須由Director調度,但響應報文必須不能經由Director;
(5) 不支持端口映射;
(6) 各RS可以使用大多數的OS;

lvs-tun:ip tunneling,ip隧道;
轉發方式:不修改請求報文的IP首部(源IP為CIP,目標IP為VIP),而是在原有的IP首部之外再次封裝一個IP首部(源IP為DIP,目標IP為RIP);

(1) RIP,DIP,VIP全得是公網地址;
(2) RS的網關不能也不可能指向DIP;
(3) 請求報文經由Director調度,但響應報文將直接發給CIP;
(4) 不支持端口映射;
(5) RS的OS必須支持IP隧道功能;

lvs-fullnat:
通過同時修改請求報文的源IP地址(cip-->dip)和目標IP地址(vip --> rip)實現轉發;

(1) VIP是公網地址;RIP和DIP是私網地址,且可以不在同一IP網絡中,但需要通過路由互相通信;
(2) RS收到的請求報文的源IP為DIP,因此其響應報文將發送給DIP;
(3) 請求報文和響應報文都必須經由director;
(4) 支持端口映射;
(5) RS可使用任意OS;

lvs scheduler:調度算法
a、靜態方法:僅根據算法本身進行調度;
RR:round robin, 輪調,輪詢,輪叫;
WRR:weighted rr, 加權輪詢;
SH:source ip hash, 源地址哈希;實現session保持的機制;將來自於同一個IP的請求始終調度至同一RS;
DH:desination ip hash, 目標地址哈希;提高緩存命中的機制(lvs不支持);將對同一個目標的請求始終發往同一個RS;

b、動態方法:根據算法及各RS的當前負載狀態(Overhead)進行調度;
LC:least connection,最少連接;Overhead=Active256+Inactive
WLC: weighted LC,加權最少連接;Overhead=(Active
256+Inactive)/weight
SED:Shortest Expection Delay,最短期望延遲;Overhead=(Active+1)*256/weight
NQ: Nerver Queue,永不排隊
LBLC:Locality-Based LC,即為動態的DH算法;正向代理情形下的cache server調度;
LBLCR:LBLC with Replication,帶復制功能的LBLC;

lvs:
ipvsadm/ipvs
ipvsadm:用戶空間的命令行工具,用於管理集群服務及集群服務上的RS等;
ipvs:工作於內核上的netfilter INPUT鉤子之上的程序代碼;
其集群功能依賴於ipvsadm定義的集群服務器規則;
支持基於TCP,UDP,SCTP,AH,ESP,AH_ESP等協議的眾多服務;

(1)一個ipvs主機可以同時定義多個cluster service;
(2)一個cluster service上至少應該有一個real server;
定義時,指明lvs-type,以及lvs scheduler;

管理集群服務:
ipvsadm ?-A|E ?-t|u|f ?service-address ?[-s scheduler]
ipvsadm ?-D ?-t|u|f service-address
-A:添加
-E:修改
-D:刪除

service-address:
tcp:-t ?vip:port
udp:-u ?vip:port
fwm:-f ? ?MARK

-s scheduler:默認為wlc;

管理集群服務上的RS:
ipvsadm -a|e ?-t|u|f service-address -r server-address [-g|i|m] [-w weight]
ipvsadm -d -t|u|f service-address -r server-address
-a:添加一個RS
-e:修改一個RS
-d:刪除一個RS

server-address:
rip[:port]

-g:lvs-dr模型(默認)
-i:lvs-tun模型
-m:lvs-nat模型

查看:
ipvsadm -L|l [options]
-n:numeric,數字格式顯示地址和端口;
-c:connection,顯示ipvs連接;
--stats:統計數據;
--rate:速率
--exact:精確值

清空規則:
ipvsadm ?-C

保存和重載:
保存:
ipvsadm -S ?> /PATH/TO/SOME_RULE_FILE
ipvsadm-save ?> /PATH/TO/SOME_RULE_FILE

重載:
ipvsadm ?-R < /PATH/FROM/SOME_RULE_FILE
ipvsadm-restore < /PATH/FROM/SOME_RULE_FILE

計數器清零:
ipvsadm ?-Z ?[-t|u|f service-address]

fwm:firewall mark

ipvsadm -A|E -t|u|f service-address [-s scheduler]
-t, -u: service-address
ip:port
-f: service-address
firewall mark

iptables的功能:
filter, nat, mangle, raw

mangle:
target: MARK
--set-mark value[/mask]

基於fwm定義集群服務的步驟:
(1) 打標

iptables -t mangle -A PREROUTING -d $vip -p $protocol --dport $serviceport -j MARK --set-mark

#:整數
(2) 定義集群服務

ipvsadm -A -f # [-s scheduler]

lvs persistence:持久連接;在定義集群服務時附加上 ?-p ?#
功能:無論ipvs使用何種scheduler,其都能夠實現在指定時間範圍內始終將來自同一個ip地址的請求發往同一個RS;此功能是通過lvs持久連接模板實現,其與調度方法無關;

ipvs持久連接的模式:默認時間為5分鐘
每端口持久(PPC):單服務持久調度
每FWM持久(PFWMC):單防火墻標記(FWM)持久調度
每客戶端持久(PCC):定義tcp或udp協議的0號端口為集群服務端口;director將用戶的任何請求都識別為集群服務,並向RS進行調度
示例:

ipvsadm -A -t 172.20.120.71:0 -s rr -p

ipvsadm -a -t 172.20.120.71:0 -r 172.20.120.41 -g

ipvsadm -a -t 172.20.120.71:0 -r 172.20.120.42 -g

示例lvs-nat模型:拓撲圖如下所示;要點:1、請求和響應報文都經由director;2、各RS網關必須指向dip;
?
director:

ipvsadm -A -t 172.20.120.40:80 -s rr

ipvsadm -a -t 172.20.120.40:80 -r 192.168.20.11 -m

ipvsadm -a -t 172.20.120.40:80 -r 192.168.20.12 -m

示例lvs-dr模型:拓撲圖如下;要點:1、請求報文經由director,響應報文直接由各rs響應;2、各rs由於都有vip,因此需要解決arp廣播跟arp回應的問題;3、請求報文到達director,通過修改mac地址到達挑選後的realserver;4、director跟各rs在同一物理網絡中;

director:

ifconfig eno16777736:0 172.20.120.71/32 up

route add -host 172.20.120.71 dev eno16777736:0

ipvsadm -A -t 172.20.120.71:80 -r ss

ipvsadm -a -t 172.20.120.71:80 -r 172.20.120.41 -g

ipvsadm -a -t 172.20.120.71:80 -r 172.20.120.42 -g

各rs:腳本如下lvs-dr.sh
#!/bin/bash
vip=172.20.120.71
interface=lo

case $1 in
start)
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

ifconfig $interface:0 $vip/32 up
route add -host $vip dev $interface:0
;;
stop)
route del -host $vip dev $interface:0
ifconfig $interface:0 dow

echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
;;
esac

另外一種情況:vip跟rip不在同一網段

lvs HA功能:
director:在節點級別進行冗余;HA集群解決方案:keepalived;
real server:讓director對其做健康狀態檢測,並且根據檢測的結果自動完成添加或移除等管理功能;
健康時:online
非健康時:offline

1、如何對real server做健康狀態檢測:
(1) 網絡層:探測主機的存活狀態;icmp ping
(2) 傳輸層:探測端口的可用性;tcp ping
(3) 應用層:請求關鍵的某資源;curl

2、檢查頻率:

3、狀態判斷:
下線:ok --> failure --> failure --> failure ? ? ? ? ? ? ? ? ? ? ? rs: down
上線:failure --> ok --> ok ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rs: up

4、backup_server(sorry_server):即所有realserver都下線的情況,臨時提供的web頁面;

HA:提供冗余主機來提升系統可用性;
Availability=(MTBF)平均無故障時間/(平均無故障時間+平均修復時間(MTTR))
衡量值:95%,99%,99.9%,99.99%,99.999%

HA Cluster的實現方案:
1、vrrp協議的實現;keepalived
2、ais:完備的HA集群;heartbeat、corosync

keepalived是vrrp的實現,原生設計目的為ipvs服務提供高可用;
vrrp協議在Linux主機上以守護進程方式的實現; 能夠根據配置文件生成ipvs規則,並對各RS的健康做檢測;vrrp_script, vrrp_track;
?vrrp的術語:virtual redundant routing protocol 虛擬冗余路由協議
虛擬路由器、VRID(虛擬路由器的標識0-255)、Master、Backup、VIP、VMAC(00-00-5e-00-01-VRID)、優先級、搶占式、非搶占式;keepalived使用gratuitous arp(免費arp);
工作方式:搶占式、非搶占式
工作模式:主備、主/主(配置多個虛擬路由器)
認證方式:無認證、簡單字符串認證(預共享密鑰)、MD5認證

組件:
1、控制組件:配置文件分析器
2、內存管理
3、IO復用
4、核心組件:vrrp stack、checker、ipvs wrapper、watch dog

HA Cluster的配置前提(?keepalived):
1、各節點時間要同步;
ntp協議、chrony;
2、確保iptables及selinux不會成為障礙;
3、(keepalived可選)各節點之間可通過主機名互相通信;即名稱解析服務的解析結果必須與“uname -n”命令的結果一致;
4、(keepalived可選)各節點之間的root用戶可以基於密鑰認證的ssh通信;

組播地址:224-239

安裝keepalived:centos6.4+,程序包已在base源提供

yum install keepalived -y

主配置文件:/etc/keepalived/keepalived.conf
unit file:/usr/lib/systemd/systemd/keepalived.service,其配置文件/etc/sysconfig/keepalived
配置文件內容塊分為三段:
1、全局配置段:global_defs { ?... ?}
2、VRRP配置段:
a、vrrp_sync_group ?GROUP_NAME ? ?{ ?... }
b、vrrp_instance ?INSTANCE_NAME ? ?{ ?... ?}
3、LVS配置段:virtual_server_group ?VSG_NAME ? ?{ ? ?... ? ?}
virtual_server ? IP ?PORT ?| ?fwmark ?int ? {
protocol ? TCP
...
real_server ?<IPADDR> ? <PORT> ? {
...
}
real_server ?<IPADDR> ? <PORT> ? {
...
}
}

全局配置:
global_defs {
notification_email {
...
}:收件人郵箱地址
notification_email_from:發件人郵箱地址
smtp_server:郵件發送服務器IP;
smtp_connect_timeout:郵件服務器建立連接的超時時長;
router_id LVS_DEVEL:物理節點的標識符;建立使用主機名;
vrrp_mcast_group4:IPV4多播地址,默認224.0.0.18;

VRRP實例配置:
vrrp_instance NAME {
...
}
常用配置:
state MASTER|BACKUP:在當前VRRP實例中此節點的初始狀態;
interface ? IFACE_NAME:vrrp用於綁定vip的接口;
virtual_router_id ?#:當前VRRP實例的VRID,可用範圍為0-255,默認為51;
priority #:當前節點的優先級,可用範圍0-255;
advert_int 1:通告時間間隔;
authentication { ? ? # Authentication block 認證機制

PASS||AH

PASS - Simple Passwd (suggested)

AH - IPSEC (not recommended))

auth_type PASS

Password for accessing vrrpd.

should be the same for all machines.

Only the first eight (8) characters are used.

auth_pass 1234
}
virtual_ipaddress {
<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
}
track_interface{#定義要監控的接口
eth0
eth1

nopreempt:工作於非搶占模式(默認為搶占模式)

定義通知腳本:
vrrp_instance ?<String> ? {
...
notify_master ?<STRING>|<QUOTED-STRING>
notify_backup ?<STRING>|<QUOTED-STRING>
notify_fault ?<STRING>|<QUOTED-STRING>
notify ?<STRING>|<QUOTED-STRING>
}

示例腳本:
#!/bin/bash

Author: MageEdu

Description: An example of notify script

#
contact=‘root@localhost‘

notify() {
mailsubject="$(hostname) to be $1: vip floating"
mailbody="$(date +‘%F %H:%M:%S‘): vrrp transition, $(hostname) changed to be $1"
echo $mailbody | mail -s "$mailsubject" $contact
}

case $1 in
master)
notify master
exit 0
;;
backup)
notify backup
exit 0
;;
fault)
notify fault
exit 0
;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"
exit 1
;;
esac

調用方法:
vrrp_instance <String> {
...
notify_master ?"/etc/keepalived/notify.sh master"
notify_backup ?"/etc/keepalived/notify.sh backup"
notify_fault ?"/etc/keepalived/notify.sh fault"
}
註意:要使用雙引號;

ipvs服務定義方法:
虛擬服務器:
virutal_server ?vip ?port |
virtual_server fwmark int ?{
...
}

常用的參數:
delay_loop ?<INT> ? ?定義服務輪詢時間間隔;
lb_algo ? rr|wrr|lc|wlc|lblc|sh|dh ? ?定義負載均衡調度方法;
lb_kind ?NAT|DR|TUN ? 定義集群的類型
persistence_timeout ?<INT> ? 持久連接時長;
protocol TCP ?服務協議;
sorry_server ?<IPADDR> ?<PORT> ?所有RS均故障時,提供say sorry的服務器;

定義RS的方法:
real_server <IPADDR> <PORT> ?{
...
}
常用的參數:
weight <INT> ?權重;
notify_up ?<STRING>|<QUOTED-STRING> 節點上線時調用的通知腳本;
notify_down ?<STRING>|<QUOTED-STRING> ?節點離線時調用的通知腳本;

HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK
支持的所有健康狀態檢測方式;

健康狀態檢測機制
1、web應用層檢測
HTTP_GET|SSL_GET
{
...
}
檢測參數:
url ?{
path ?<STRING> 健康狀態檢測時請求的資源的URL;
status_code <INT> ? 基於頁面的狀態碼進行健康狀態判定;
digest <STRING>基於獲取內容的摘要碼進行健康狀態判定;借助keepalived提供/usr/bin/genhash生成摘要碼
nb_get_retry <INT>:get請求的重試次數;
delay_before_retry <INT>:兩次重試之間的時間間隔;
connect_timeout <INTEGER>:連接超時時長,默認為5s;
connect_ip <IP ADDRESS>:向此處指定的地址發測試請求;
connect_port <PORT>:向此處指定的端口發測試請求;
bindto <IP ADDRESS>:指定測試請求報文的源IP;
bindport <PORT>:指定測試請求報文的源端口;
warmup <INT>:健康狀態檢測延遲;
}

2、傳輸層健康狀態檢測(tcp協議層)
TCP_CHECK
{
...
}
檢測參數:
connect_timeout ?<INTEGER>

其它:
connect_ip <IP ADDRESS>
connect_port <PORT>
bindto <IP ADDRESS>
bind_port <PORT>

定義外部腳本來檢測高可用功能依賴到的資源的監控
vrrp_script ?NAME ?{
script
interval
weight
}

在實例追蹤定義腳本,用於作為實例的當前節點的監控機制
track_script {
NAME
}

監控關註的網絡接口
track_interface {
IFACE_NAME
}

使用非搶占模式
nopreempt

使用延遲搶占模式
preempt_delay ?TIME

vrrp_script:自定義一個資源監控腳本;vrrp實例能根據腳本狀態返回值來
公共定義,可被多個實例調用,因此定義在vrrp實例之外;

track_script:調用vrrp_script定義的腳本去監控資源;
定義在實例之內,調用事先定義好的vrrp_script;

腳本實例:通過檢測httpd服務是否正常的返回值來減少weight,達到ip漂移。
vrrp_script chk_httpd {
? ? ? ?script "killall -0 httpd"
? ? ? ?interval 2
? ? ? ?weight -5
}
track_script {
? ? ? ? chk_httpd
? ? }

? ? 然後可以借助通知腳本進一步擴展功能;
? ? 調用方法:
vrrp_instance <String> {
...
notify_master ?"/etc/keepalived/notify.sh master"
notify_backup ?"/etc/keepalived/notify.sh backup"
notify_fault ?"/etc/keepalived/notify.sh fault"
}
註意:要使用雙引號;

? ? 示例腳本:
#!/bin/bash

Author: MageEdu

Description: An example of notify script

#
contact=‘root@localhost‘

notify() {
mailsubject="$(hostname) to be $1: vip floating"
mailbody="$(date +‘%F %H:%M:%S‘): vrrp transition, $(hostname) changed to be $1"
echo $mailbody | mail -s "$mailsubject" $contact
}

case $1 in
master)
notify master
exit 0
;;
backup)
notify backup
exit 0
;;
fault)
notify fault
exit 0
;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"
exit 1
;;
esac

lvs(linux virtual server)、keepalived