LVS进阶(第30天)
回顾:
lvs: l4 switch, l4 router
vip, port, {tcp|udp}
lvs-type:
lvs-nat, masquerade
lvs-dr, gateway
lvs-tun, ipip
lvs-fullnat (keepalived)
lvs scheduler: lvs调度算法
static: rr, wrr, sh, dh
dynamic: lc, wlc, sed, nq, lblc, lblcr
overhead: active connections, inactive connections
lvs-dr: vip和dip/rip不再同一个网段时,
vmware的网络模型:bridge, nat, host-only,
lvs(3)
netfilter:
PREROUTING --> INPUT
PREROUTING --> FORWARD --> POSTROUTING
OUTPUT --> POSTROUTING
ipvs: 工作在INPUT链上
FWM:防护墙标记
当请求到达的时候,请求是先进入ipvs调度机的PREROUTING链上的,然后是INPUT链接,或者是先进入PREROUTING链,然后是FORWARD链,2种可能中都必须要经由PREROUTING链,所以netfilter就可以在PREROUTING链上对某特征报文打标机,比如对tcp的80端口的报文打标记(而要对报文打标记,要用到iptables命令的-j选项指定动作为打标记)。
具体做法如下,分2步:
PREROUTING: 第1步,使用iptables对某种特征的报文打标记
iptables -j MARK --set-mark 10 设计标记10
ipvs: 第2步,调度的时候,使用标记数字来表示这种特征的报文
ipvsadm -A -f 10 这里就可以用-f指定标记,比如,10可能就是表示tcp 80端口的报文, ipvsadm -A -f 10 相当于 ipvsadm -A -t ip:80
通过FWM定义集群的方式:
(1) 在director上netfilter的mangle表的PREROUTING定义用于“打标”的规则
~]# iptables -t mangle -A PREROUTING -d $vip -p $protocol --dports $port -j MARK --set-mark #
$vip: VIP地址
$protocol:协议
$port: 协议端口
(2) 基于FWM定义集群服务:
~]# ipvsadm -A -f # -s scheduler
~]# ipvsadm -a -f # -r RS1_IP -g
~]# ipvsadm -a -f # -r RS2_IP -g
~]# ipvsadm -a -f # -r RS3_IP -g
功用:将共享同一组RS的集群服务统一进行定义;比如,80和443端口的服务统一进行定义
session保持的实现方式如下:
session绑定
session复制
session服务器
session绑定:可以使用lvs sh算法
对某一特定服务;
lvs persistence:lvs的持久连接
功能:无论ipvs使用何种调度方法,其都能实现将来自于同一个Client的请求始终定向至第一次调度时挑选出的RS;
持久连接的实现方式:
持久连接会话模板:sourceip rs timer timer表示倒数器,表示请求来源对应的rs,通过指定-p选项来实现,-p 后面跟上超时时间,比如 ipvsadm -A -t 192.168.0.10:80 -s rr -p && ipvsadm -a -t 192.168.0.10:80 -r 172.16.100.21 -g && ipvsadm -a -t 192.168.0.10:80 -r 172.16.100.22 -g
每端口持久:PPC,单服务持久调度,同一种服务(比如80,或者22的服务)的请求被调度至同一个rs
每FWM持久:PFWMC,单FWM持久调度,同一个防火墙标记的请求被调度之同一个rs
PORT AFFINITY
每客户端持久:PCC,单客户端持久调度
director会将单用户的任何请求(包括任何端口)都识别为集群服务,并向RS进行调度
TCP:1-65535 说白了,无非就是把端口范围定义为1到65535
UDP: 1-65535
HA:高可用
SPOF: Single Point of Failure 单点故障
单点故障越少,越高可用
director: 高可用集群;
realserver: 让director对其做健康状态检测,并且根据检测的结果自动完成添加或移除等管理功能;
健康检查后端的RS服务器要考虑的问题:
1、基于协议层次检查
ip: icmp
传输层:检测端口的开放状态(使用nmap)
应用层:请求获取关键性的资源
2、检查频度,过于频繁会造成RS的压力,过于离散会造成检查不够准确
3、状态判断
下线:ok --> failure(软状态) --> failure(软状态) --> failure(硬状态)
上线:failure --> ok(软状态) --> ok(硬状态)
4、back server也称之为sorry server:因为可能出现所有的RS都挂掉的情况,这时候就需要一个可用的back server来告知用户当前服务不可用。
LVS没有提供对于后端RS的健康监测的模块,haproxy,nginx等就提供了对于后端RS的健康监测的模块。
maybe可以自己写脚本对后端RS的健康状态做监测。
示例脚本:
#!/bin/bash
#
fwm=6
sorry_server=127.0.0.1
rs=('172.16.100.21' '172.16.100.22') #后端的RS服务器
rw=('1' '2') #RS的权重
type='-g' #lvs类型
chkloop=3 #从软状态到硬状态要经过几次监测
rsstatus=(0 0) #RS的初始状态
logfile=/var/log/ipvs_health_check.log
addrs() { #添加RS
ipvsadm -a -f $fwm -r $1 $type -w $2
[ $? -eq 0 ] && return 0 || return 1
}
delrs() { #删除RS
ipvsadm -d -f $fwm -r $1
[ $? -eq 0 ] && return 0 || return 1
}
chkrs() { #监测RS
local i=1
while [ $i -le $chkloop ]; do
if curl --connect-timeout 1 -s http://$1/.health.html | grep "OK" &> /dev/null; then
return 0
fi
let i++
sleep 1
done
return 1
}
initstatus() { #初始化
for host in `seq 0 $[${#rs[@]}-1]`; do
if chkrs ${rs[$host]}; then
if [ ${rsstatus[$host]} -eq 0 ]; then
rsstatus[$host]=1
fi
else
if [ ${rsstatus[$host]} -eq 1 ]; then
rsstatus[$host]=0
fi
fi
done
}
initstatus
while :; do
for host in `seq 0 $[${#rs[@]}-1]`; do
if chkrs ${rs[$host]}; then
if [ ${rsstatus[$host]} -eq 0 ]; then
addrs ${rs[$host]} ${rw[$host]}
[ $? -eq 0 ] && rsstatus[$host]=1
fi
else
if [ ${rsstatus[$host]} -eq 1 ]; then
delrs ${rs[$host]} ${rw[$host]}
[ $? -eq 0 ] && rsstatus[$host]=0
fi
fi
done
sleep 5
done
附:director和rs的示例脚本
DR类型director脚本示例:
#!/bin/bash
#
vip=172.16.100.33
rip=('172.16.100.8' '172.16.100.9')
weight=('1' '2')
port=80
scheduler=rr
ipvstype='-g'
case $1 in
start)
iptables -F -t filter
ipvsadm -C
ifconfig eth0:0 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip dev eth0:0
echo 1 > /proc/sys/net/ipv4/ip_forward
ipvsadm -A -t $vip:$port -s $scheduler
[ $? -eq 0 ] && echo "ipvs service $vip:$port added." || exit 2
for i in `seq 0 $[${#rip[@]}-1]`; do
ipvsadm -a -t $vip:$port -r ${rip[$i]} $ipvstype -w ${weight[$i]}
[ $? -eq 0 ] && echo "RS ${rip[$i]} added."
done
touch /var/lock/subsys/ipvs
;;
stop)
echo 0 > /proc/sys/net/ipv4/ip_forward
ipvsadm -C
ifconfig eth0:0 down
rm -f /var/lock/subsys/ipvs
echo "ipvs stopped."
;;
status)
if [ -f /var/lock/subsys/ipvs ]; then
echo "ipvs is running."
ipvsadm -L -n
else
echo "ipvs is stopped."
fi
;;
*)
echo "Usage: `basename $0` {start|stop|status}"
exit 3
;;
esac
DR类型RS脚本示例:
#!/bin/bash
#
vip=172.16.100.33
interface="lo:0"
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 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip dev $interface
;;
stop)
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
ifconfig $interface down
;;
status)
if ifconfig lo:0 |grep $vip &> /dev/null; then
echo "ipvs is running."
else
echo "ipvs is stopped."
fi
;;
*)
echo "Usage: `basename $0` {start|stop|status}"
exit 1
esac
课堂实践任务:
(1) 建立一个由至少两个RS组成的负载均衡集群;rs用于提供apache+php,mysql由单独的服务器实现;
(2) 部署安装discuz_x3.1;分别基于rr/lc/sh算法调度,查看两台rs是否都接收到了请求;
部署环境说明:假设页面访问路径为/www/app/discuz,则需要将discuz_3.1部署于/www/app目录中,而后将/www/app/discuz创建为符号链接,链接至带版本号的目录上;多台RS路径均采用此方式;
(3) 基于灰度的方式进行应用程序升级;
(4) 尝试着写脚本自动进行灰度发布;
lvs: l4 switch, l4 router
vip, port, {tcp|udp}
lvs-type:
lvs-nat, masquerade
lvs-dr, gateway
lvs-tun, ipip
lvs-fullnat (keepalived)
lvs scheduler: lvs调度算法
static: rr, wrr, sh, dh
dynamic: lc, wlc, sed, nq, lblc, lblcr
overhead: active connections, inactive connections
lvs-dr: vip和dip/rip不再同一个网段时,
vmware的网络模型:bridge, nat, host-only,
lvs(3)
netfilter:
PREROUTING --> INPUT
PREROUTING --> FORWARD --> POSTROUTING
OUTPUT --> POSTROUTING
ipvs: 工作在INPUT链上
FWM:防护墙标记
当请求到达的时候,请求是先进入ipvs调度机的PREROUTING链上的,然后是INPUT链接,或者是先进入PREROUTING链,然后是FORWARD链,2种可能中都必须要经由PREROUTING链,所以netfilter就可以在PREROUTING链上对某特征报文打标机,比如对tcp的80端口的报文打标记(而要对报文打标记,要用到iptables命令的-j选项指定动作为打标记)。
具体做法如下,分2步:
PREROUTING: 第1步,使用iptables对某种特征的报文打标记
iptables -j MARK --set-mark 10 设计标记10
ipvs: 第2步,调度的时候,使用标记数字来表示这种特征的报文
ipvsadm -A -f 10 这里就可以用-f指定标记,比如,10可能就是表示tcp 80端口的报文, ipvsadm -A -f 10 相当于 ipvsadm -A -t ip:80
通过FWM定义集群的方式:
(1) 在director上netfilter的mangle表的PREROUTING定义用于“打标”的规则
~]# iptables -t mangle -A PREROUTING -d $vip -p $protocol --dports $port -j MARK --set-mark #
$vip: VIP地址
$protocol:协议
$port: 协议端口
(2) 基于FWM定义集群服务:
~]# ipvsadm -A -f # -s scheduler
~]# ipvsadm -a -f # -r RS1_IP -g
~]# ipvsadm -a -f # -r RS2_IP -g
~]# ipvsadm -a -f # -r RS3_IP -g
功用:将共享同一组RS的集群服务统一进行定义;比如,80和443端口的服务统一进行定义
session保持的实现方式如下:
session绑定
session复制
session服务器
session绑定:可以使用lvs sh算法
对某一特定服务;
lvs persistence:lvs的持久连接
功能:无论ipvs使用何种调度方法,其都能实现将来自于同一个Client的请求始终定向至第一次调度时挑选出的RS;
持久连接的实现方式:
持久连接会话模板:sourceip rs timer timer表示倒数器,表示请求来源对应的rs,通过指定-p选项来实现,-p 后面跟上超时时间,比如 ipvsadm -A -t 192.168.0.10:80 -s rr -p && ipvsadm -a -t 192.168.0.10:80 -r 172.16.100.21 -g && ipvsadm -a -t 192.168.0.10:80 -r 172.16.100.22 -g
每端口持久:PPC,单服务持久调度,同一种服务(比如80,或者22的服务)的请求被调度至同一个rs
每FWM持久:PFWMC,单FWM持久调度,同一个防火墙标记的请求被调度之同一个rs
PORT AFFINITY
每客户端持久:PCC,单客户端持久调度
director会将单用户的任何请求(包括任何端口)都识别为集群服务,并向RS进行调度
TCP:1-65535 说白了,无非就是把端口范围定义为1到65535
UDP: 1-65535
HA:高可用
SPOF: Single Point of Failure 单点故障
单点故障越少,越高可用
director: 高可用集群;
realserver: 让director对其做健康状态检测,并且根据检测的结果自动完成添加或移除等管理功能;
健康检查后端的RS服务器要考虑的问题:
1、基于协议层次检查
ip: icmp
传输层:检测端口的开放状态(使用nmap)
应用层:请求获取关键性的资源
2、检查频度,过于频繁会造成RS的压力,过于离散会造成检查不够准确
3、状态判断
下线:ok --> failure(软状态) --> failure(软状态) --> failure(硬状态)
上线:failure --> ok(软状态) --> ok(硬状态)
4、back server也称之为sorry server:因为可能出现所有的RS都挂掉的情况,这时候就需要一个可用的back server来告知用户当前服务不可用。
LVS没有提供对于后端RS的健康监测的模块,haproxy,nginx等就提供了对于后端RS的健康监测的模块。
maybe可以自己写脚本对后端RS的健康状态做监测。
示例脚本:
#!/bin/bash
#
fwm=6
sorry_server=127.0.0.1
rs=('172.16.100.21' '172.16.100.22') #后端的RS服务器
rw=('1' '2') #RS的权重
type='-g' #lvs类型
chkloop=3 #从软状态到硬状态要经过几次监测
rsstatus=(0 0) #RS的初始状态
logfile=/var/log/ipvs_health_check.log
addrs() { #添加RS
ipvsadm -a -f $fwm -r $1 $type -w $2
[ $? -eq 0 ] && return 0 || return 1
}
delrs() { #删除RS
ipvsadm -d -f $fwm -r $1
[ $? -eq 0 ] && return 0 || return 1
}
chkrs() { #监测RS
local i=1
while [ $i -le $chkloop ]; do
if curl --connect-timeout 1 -s http://$1/.health.html | grep "OK" &> /dev/null; then
return 0
fi
let i++
sleep 1
done
return 1
}
initstatus() { #初始化
for host in `seq 0 $[${#rs[@]}-1]`; do
if chkrs ${rs[$host]}; then
if [ ${rsstatus[$host]} -eq 0 ]; then
rsstatus[$host]=1
fi
else
if [ ${rsstatus[$host]} -eq 1 ]; then
rsstatus[$host]=0
fi
fi
done
}
initstatus
while :; do
for host in `seq 0 $[${#rs[@]}-1]`; do
if chkrs ${rs[$host]}; then
if [ ${rsstatus[$host]} -eq 0 ]; then
addrs ${rs[$host]} ${rw[$host]}
[ $? -eq 0 ] && rsstatus[$host]=1
fi
else
if [ ${rsstatus[$host]} -eq 1 ]; then
delrs ${rs[$host]} ${rw[$host]}
[ $? -eq 0 ] && rsstatus[$host]=0
fi
fi
done
sleep 5
done
附:director和rs的示例脚本
DR类型director脚本示例:
#!/bin/bash
#
vip=172.16.100.33
rip=('172.16.100.8' '172.16.100.9')
weight=('1' '2')
port=80
scheduler=rr
ipvstype='-g'
case $1 in
start)
iptables -F -t filter
ipvsadm -C
ifconfig eth0:0 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip dev eth0:0
echo 1 > /proc/sys/net/ipv4/ip_forward
ipvsadm -A -t $vip:$port -s $scheduler
[ $? -eq 0 ] && echo "ipvs service $vip:$port added." || exit 2
for i in `seq 0 $[${#rip[@]}-1]`; do
ipvsadm -a -t $vip:$port -r ${rip[$i]} $ipvstype -w ${weight[$i]}
[ $? -eq 0 ] && echo "RS ${rip[$i]} added."
done
touch /var/lock/subsys/ipvs
;;
stop)
echo 0 > /proc/sys/net/ipv4/ip_forward
ipvsadm -C
ifconfig eth0:0 down
rm -f /var/lock/subsys/ipvs
echo "ipvs stopped."
;;
status)
if [ -f /var/lock/subsys/ipvs ]; then
echo "ipvs is running."
ipvsadm -L -n
else
echo "ipvs is stopped."
fi
;;
*)
echo "Usage: `basename $0` {start|stop|status}"
exit 3
;;
esac
DR类型RS脚本示例:
#!/bin/bash
#
vip=172.16.100.33
interface="lo:0"
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 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip dev $interface
;;
stop)
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
ifconfig $interface down
;;
status)
if ifconfig lo:0 |grep $vip &> /dev/null; then
echo "ipvs is running."
else
echo "ipvs is stopped."
fi
;;
*)
echo "Usage: `basename $0` {start|stop|status}"
exit 1
esac
课堂实践任务:
(1) 建立一个由至少两个RS组成的负载均衡集群;rs用于提供apache+php,mysql由单独的服务器实现;
(2) 部署安装discuz_x3.1;分别基于rr/lc/sh算法调度,查看两台rs是否都接收到了请求;
部署环境说明:假设页面访问路径为/www/app/discuz,则需要将discuz_3.1部署于/www/app目录中,而后将/www/app/discuz创建为符号链接,链接至带版本号的目录上;多台RS路径均采用此方式;
(3) 基于灰度的方式进行应用程序升级;
(4) 尝试着写脚本自动进行灰度发布;
评论
发表评论