lvs+keepalived實現web集羣高可用性
負載均衡集羣的概念
負載均衡是設計分佈式系統架構必須要考慮的因素之一,它指的是通過調度分發的方式儘可能將“請求”、“訪問”的壓力負載平均分攤到集羣中的各個節點,避免有些節點負載太高導致訪問延遲,而有些節點負載很小導致資源浪費。這樣,每個節點都可以承擔一定的訪問請求負載壓力,並且可以實現訪問請求在各節點之間的動態分配,以實現負載均衡,從而爲企業提供更高性能,更加穩定的系統架構解決方案。
高可用集羣的概念
高可用是指以減少服務中斷時間或者避免服務中斷爲目標的技術,它也是分佈式系統架構中必須要考慮的因素之一。集羣中節點之間進行心跳檢查,可以實現對整個集羣中的節點健康狀態的檢測,如果某個節點失效,它的備節點將在幾秒鐘的時間內接管它的工作。因此對於用戶而言,服務總是可以訪問的。
一點點概念
1,directory server 負載均衡器(DR)
2,real server 提供服務的真實服務器
3,VIP 虛擬IP
4,CIP 客戶端的IP
5,DIP directory server的IP
6,RIP real server的IP
什麼是lvs?
lvs全稱是linux virtual server,基於IP負載均衡技術和基於內容請求分發技術。它通過一個資源調度器將請求均衡地分發到不同的服務器上,從而將一組服務器構成一個高性能的、高可用的虛擬服務器。
lvs有三種類型:
①lvs-nat模型:請求報文到達調度器(DR)的時候,DR將目的IP(VIP)轉換成真正的服務器地址再根據調度算法,將請求轉發給後端真實的服務器;真實服務器的響應報文通過調度器時,報文的源地址被轉換成(RIP),再返回給客戶端,完成整個負載調度過程。由於請求報文和迴應報文都必須經過DR,所以DR會成爲性能的瓶頸。這種模型的VIP和RIP可以在不同的網段,值得注意的是:真實服務器的網關必須指向DR。
②lvs-dr模型:DR模型是通過把請求報文的MAC地址改寫成真實服務器的MAC地址直接把請求發送給真實服務器,而真實服務器將響應直接返回給客戶端。對於DR模型,由於請求報文是通過廣播的方式在LAN傳輸,所以VIP和RIP必須在同一個網段,否則廣播後所有的請求報文都會丟失。
③lvs-tun模型:調度器會把請求報文通過IP隧道轉發到真實服務器,而真實服務器將響應直接返回給客戶端,所以調度器只處理請求報文,不處理響應報文。這種模型的lvs需要在所有的真實服務器上綁定VIP,VIP和RIP可以不在同一個網段。
keepalived又是什麼?
keepalived是一款輕量級的高可用軟件,它只能實現對IP資源的高可用。主要通過虛擬路由冗餘協議(VRRP)實現高可用的功能。在非雙主keepalived集羣中,會依靠優先級選舉出一個主節點,IP資源會優先綁定到主節點,其他節點成爲備節點,主節點與備節點之間會通過檢查心跳線來檢測對方的存活,一旦主節點宕機,備用節點就搶佔IP資源,當主節點恢復正常,備節點又會釋放IP資源給主節點。
實驗:lvs+keepalived
主機名 | 角色 | IP | ||
lvs-master | 主調度器 | 172.16.1.136/24 | ||
lvs-backup | 備調度器 | 172.16.1.133/24 | ||
web1 | 真實服務器 | 172.16.1.140/24 | ||
web2 | 真實服務器 | 172.16.1.137/24 | ||
client | 客戶端 |
vip | 172.16.1.111/24 |
//所有的服務器都要同步時間
ntpdate time.nist.gov
crontab -l
*/10 * * * * ntpdate time.nist.gov
real server的配置
關閉防火牆和selinux
[root@web1 ~]#systemctl stop firewalld
[root@web1 ~]#systemctl disable firewalld
[root@web1 ~]#vim /etc/selinux/config
SELINUX=disabled
配置web服務
[root@web1 ~]#yum -y install httpd
[root@web1 ~]#echo web1 > /var/www/html/index.html
[root@web1 ~]#systemctl start httpd
----------------------web2同web1,略
lvs-master的配置
關閉防火牆還有selinux
[root@lvs-master~]# systemctl stop firewalld
[root@lvs-master~]# systemctl disable firewalld
[root@lvs-master~]# vim /etc/selinux/config
SELINUX=disabled
配置lvs
[root@lvs-master~]# yum -y install ipvsadm #下載工具
[root@lvs-master~]# vim lvs.sh #通過腳本配置lvs
#!/bin/bash
VIP=172.16.1.111
RIP1=172.16.1.140
RIP2=172.16.1.137
PORT=80
start() {
echo 1 > /proc/sys/net/ipv4/ip_forward
ipvsadm -A -t $VIP:$PORT -s rr
ipvsadm -a -t $VIP:$PORT -r $RIP1:$PORT -g
ipvsadm -a -t $VIP:$PORT -r $RIP2:$PORT -g
}
stop() {
ipvsadm -D -t $VIP:$PORT
echo 0 > /proc/sys/net/ipv4/ip_forward
}
case $1 in
start)
start;;
stop)
stop;;
*)
echo "/root/lvs.sh start|stop";;
esac
由於lvs不能對後端服務器進行健康檢測,所以需要寫一個檢查後端服務健康狀態的腳本
[root@lvs-master~]# vim lvs_healcheck.sh
#!/bin/bash
VIP=172.16.1.111
RIP1=172.16.1.140
RIP2=172.16.1.137
PORT=80
for i in $RIP1$RIP2
do
/usr/sbin/ipvsadm -a -t $VIP:$PORT -r $i:$PORT -g &> /dev/null
if ["$?" -ne "0" ];then
curl http://$i &> /dev/null
if [ "$?" == "0" ];then
echo "real server in `date +%F-%T`is ok" >> /tmp/healcheresult
else
/usr/sbin/ipvsadm -d -t $VIP:$PORT -r $i:$PORT
fi
else
curl http://$i &> /dev/null
if [ "$?" == "0" ];then
echo "real server in `date +%F-%T` comme on" >> /tmp/nok
else
/usr/sbin/ipvsadm -d -t $VIP:$PORT -r $i:$PORT
fi
fi
done
編寫計劃任務,每時每刻執行健康檢查腳本
[root@lvs-master~]# crontab -l
* * * * */usr/bin/sh /root/lvs_healcheck.sh
配置keepalived
[root@lvs-master~]# yum -y install keepalived
[root@lvs-master~]# vim /etc/keepalived/keepalived.conf
! ConfigurationFile for keepalived
//全局配置
global_defs {
notification_email {
root@localhost #報警郵件的地址
}
notification_email_from keepalived@localhost #郵件的發送地址
smtp_server 127.0.0.1 #smtp服務器的地址
smtp_connect_timeout 30 #連接smtp服務器的超時時間
router_id LVS_M #keepalived服務器的一個標識
}
//實例配置
vrrp_instanceVI_1 {
state MASTER #指定keepalived的角色,MASTER|BACKUP
interface eno16777736 #實例綁定的網卡,配置VIP必須在已有的網卡添加
virtual_router_id 51 #相同的VRID爲一組,決定多播的MAC地址
priority 100 #優先級
advert_int 3 #設定MASTER與BACKUP負載均衡器之間同步檢查的時間間隔,單位是秒
authentication {
auth_type PASS #認證類型 PASS|AH
auth_pass redhat #驗證密碼,在同一個實例,MASTER與BACKUP的密碼必須保持一致纔可以正常通信
}
virtual_ipaddress {
172.16.1.111 #VIP
}
}
virtual_server 172.16.1.111 80 {
delay_loop 6 #運行情況檢查時間,單位是秒
lb_algo rr #負載均衡算法,wlc爲最小加權算法,rr爲輪詢
lb_kind DR #使用DR模式
net_mask 255.255.255.0
persistence_timeout 50
protocol TCP #使用TCP協議檢查realserver狀態,指定轉發協議類型,有TCP和UDP兩種
real_server172.16.1.140 80
{
weight 1 #節點權重值
TCP_CHECK #健康檢查方式
{
connect_port 80 #連接端口
connect_timeout 5 #連接超時
nb_get_retry 3 #重試次數
delay_before_retry 3 #重試間隔
}
}
real_server172.16.1.137 80
{
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 5
nb_get_retry 3
delay_before_retry 3
}
}
}
重啓服務,設置服務開機自動啓動
[root@lvs-master~]# touch /etc/sysconfig/ipvsadm
[root@lvs-master~]# systemctl restart ipvsadm
[root@lvs-master~]# systemctl restart keepalived.service
[root@lvs-master~]# systemctl enable ipvsadm
[root@lvs-master~]# systemctl enable keepalived.service
驗證是否有vip
[root@lvs-master~]# ip add show|grep 172.16.1.111
inet172.16.1.111/32 scope global eno16777736
lvs-backup的配置
關閉防火牆和selinux
[root@lvs-backup~]# systemctl stop firewalld
[root@lvs-backup~]# systemctl disable firewalld
[root@lvs-backup~]# vim /etc/selinux/config
SELINUX=disabled
配置lvs
[root@lvs-backup~]# yum -y install ipvsadm
[root@lvs-master~]# scp lvs.sh [email protected]:/root/
[root@lvs-master~]# scp lvs_healcheck.sh [email protected]:/root/
[root@lvs-backup~]# chmod +x lvs.sh
[root@lvs-backup~]# chmod +x lvs_healcheck.sh
[root@lvs-backup~]# crontab -l
* * * * */usr/bin/sh /root/lvs_healcheck.sh
配置keepalived
[root@lvs-backup~]# yum -y install keepalived
[root@lvs-master ~]# scp /etc/keepalived/[email protected]:/etc/keepalived/
[root@lvs-backup~]# vim /etc/keepalived/keepalived.conf
! ConfigurationFile for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_S #修改router_id
}
vrrp_instanceVI_1 {
state BACKUP #修改keepalived角色
interface eno16777736
virtual_router_id 51
priority 99 #修改優先級
advert_int 3
authentication {
auth_type PASS
auth_pass redhat
}
virtual_ipaddress {
172.16.1.111
}
}
virtual_server172.16.1.111 80 {
delay_loop 6
lb_algo rr
lb_kind DR
nat_mask 255.255.255.0
persistence_timeout 50
protocol TCP
real_server 172.16.1.140 80
{
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 5
nb_get_retry 3
delay_before_retry 3
}
real_server 172.16.1.137 80
{
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 5
nb_get_retry 3
delay_before_retry 3
}
}
}
重啓服務,設置服務開機自動啓動
[root@lvs-backup~]# touch /etc/sysconfig/ipvsadm
[root@lvs-backup~]# systemctl restart ipvsadm
[root@lvs-backup~]# systemctl restart keepalived.service
[root@lvs-backup~]# systemctl enable ipvsadm
[root@lvs-backup~]# systemctl enable keepalived.service
在lvs-master和lvs-backup上創建集羣服務
[root@lvs-master~]# ./lvs.sh start
[root@lvs-master~]# ipvsadm -L -n
IP VirtualServer version 1.2.1 (size=4096)
ProtLocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.1.111:80 rr
-> 172.16.1.137:80 Route 1 0 0
-> 172.16.1.140:80 Route 1 0 0
[root@lvs-backup~]# ./lvs.sh start
[root@lvs-backup~]# ipvsadm -L -n
IP VirtualServer version 1.2.1 (size=4096)
Prot LocalAddress:PortScheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.1.111:80 rr
-> 172.16.1.137:80 Route 1 0 0
-> 172.16.1.140:80 Route 1 0 0
驗證
[root@client~]#curl http://172.16.1.111
web1
[root@client~]#curl http://172.16.1.111
web2
[root@lvs-master~]# ipvsadm -L -n
IP VirtualServer version 1.2.1 (size=4096)
ProtLocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.1.111:80 rr
-> 172.16.1.137:80 Route 1 1 0
-> 172.16.1.140:80 Route 1 1 0
#lvs-master上ActiveConn會一直增加,因爲所有訪問vip的連接都會經過lvs-master進行調度,轉發到後端real server
[root@lvs-backup~]# ipvsadm -L -n
IP VirtualServer version 1.2.1 (size=4096)
ProtLocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.1.111:80 rr
-> 172.16.1.137:80 Route 1 0 0
-> 172.16.1.140:80 Route 1 0 0
#除非lvs-master宕機,lvs-backup上ActiveConn會一直爲0,因爲沒有請求轉發到lvs-backup進行調度
關閉lvs-master模仿宕機
[root@lvs-backup~]# ip add show | grep 172.16.1.111
inet 172.16.1.111/32 scope globaleno16777736
[root@client~]#curl http://172.16.1.111
web1
[root@client~]#curl http://172.16.1.111
web2
#由於此時lvs-backup仍然正常工作,所有訪問vip的連接經過lvs-backup進行調度,轉發到後端real server,所有還可以訪問到後端的real server
再關閉lvs-backup模仿宕機
[root@client~]# curl http://172.16.1.111
curl: (7)Failed connect to 172.16.1.111:80; Connection timed out
#網絡中沒有可用的lvs負載均衡器,所有訪問vip的連接無法被調度轉發到real server
開啓lvs-master模仿故障恢復
[root@client~]# curl http://172.16.1.111
web1
[root@client~]# curl http://172.16.1.111
web2
#lvs-master正常工作所有訪問vip的連接都會經過lvs-master進行調度,轉發到後端real server
如有紕漏,歡迎指正。