vieyahn2017 / iBlog

44 stars 0 forks source link

9.8 lvs+keepalived #316

Closed vieyahn2017 closed 7 months ago

vieyahn2017 commented 4 years ago

深入理解keepalived+lvs

https://blog.51cto.com/12059878/1909346

keepalived篇:

master和bakeup之间的通信(vrrp协议) master : 172.25.88.1 bakeup :172.25.88.2

1.在matser上抓vrrp的包 [root@server1 ~]# /etc/init.d/keepalived start

Starting keepalived:                                       [  OK  ]
[root@server1 ~]# tcpdump vrrp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
15:07:23.710761 IP 172.25.88.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 102, authtype simple, intvl 1s, length 20
15:07:24.711710 IP 172.25.88.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 102, authtype simple, intvl 1s, length 20
15:07:25.712926 IP 172.25.88.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 102, authtype simple, intvl 1s, length 20
15:07:26.713916 IP 172.25.88.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 102, authtype simple, intvl 1s, length 20
15:07:27.714890 IP 172.25.88.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 102, authtype simple, intvl 1s, length 20

发现master在向224.0.0.18发送广播包,分析包文的值优先级为102,是我们的master

2.在bakeup上抓vrrp的包 [root@server2 ~]# /etc/init.d/keepalived start

Starting keepalived:                                       [  OK  ]
[root@server2 ~]# tcpdump vrrp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
15:07:38.022848 IP 172.25.88.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 102, authtype simple, intvl 1s, length 20
15:07:39.023899 IP 172.25.88.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 102, authtype simple, intvl 1s, length 20
15:07:40.024861 IP 172.25.88.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 102, authtype simple, intvl 1s, length 20
15:07:41.025770 IP 172.25.88.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 102, authtype simple, intvl 1s, length 20
15:07:42.026831 IP 172.25.88.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 102, authtype simple, intvl 1s, length 20

由此发现,master工作时,bakeup不发送vrrp包,只是接受并返回master的包

3.将master的keepalived down了 [root@server1 ~]# /etc/init.d/keepalived stop Stopping keepalived: [ OK ] 再次抓包

[root@server1 ~]# tcpdump vrrp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
15:22:43.293115 IP 172.25.88.2 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 52, authtype simple, intvl 1s, length 20
15:22:44.293714 IP 172.25.88.2 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 52, authtype simple, intvl 1s, length 20
15:22:45.294471 IP 172.25.88.2 > 224.0.0.18: VRRPv2, Advertisement, vrid 188, prio 52, authtype simple, intvl 1s, length 20

由优先级 prio 52可知,现在已经是bakeup在组播vrrp包。

总结:master只发不收,bakeup反之 其他主机也收不到vrrp包,因为有route_id限制

关于接管

BACKUP在确认没有收到MASTER的广播报文后,会主动发送组播报文,声明自己的keepalived状态,随后启用VIP。正式接管keepliaved。

关于谁来当master

1.当两个state均为master时,prio大的为master 2.当两个state均为master时且prio优先级相同时,双方都认为自己是master,双方会出现抢占ip的情况,导致地址冲突。

特殊说明

1.实现不回切 bakeup

vim /etc/keepalived/keepalived.conf

     no preempt      非抢占模式
     priority 150    且proi要比master大,我的master的proi为100

2.主备的virtual_router_id要相同,否则都会发组播报文

    virtual_router_id 188

lvs篇

lvs-why

传统:DNS负载均衡缺点:

1.服务调度算法只支持WRR
2.攻击防御能力很弱,每次有攻击靠一台机器抗。 3.如果server宕了,运维就只能把server的ip从DNS中删除,但localDNS有大量的缓存,至于删除操作什么时候生效不可控.

工作机制

我们都知道netfilter加载iptables模块,实现了防火墙。

其实lvs,就是netfilter加载ipvs模块实现的!

lvs分为ipvs(内核)和ipvsadm(用户空间)两部分:

用户用过ipvsadm编写策略,而内核加载ipvs在netfilter生效!

ipvs 结合input链(钩子函数在链上)工作,发现用户请求的是一个集群服务,就转发至forward,转发至postrouting链,进入RS(后端服务器 )。

类型

1.nat 地址转换 定义:多目标的dnat(目标地址转换) cip->vip->rip->vip->cip

进出的连接都要经过DS,DR压力大,只能负载均衡10个rs左右。

rule:

1)DR和RS必须在同一个网络中。 2)RS网关指向DIP,因为DR要修改目的地址由VIP->RIP 3)RIP为私有地址,仅用于集群通信。 4)DR位于client和real server之间,负责处理所有通信,亚历山大,成为瓶颈。 5)DR支持端口映射。 6)RS可以使用任意系统 7) NAT模式可以防DDOS

2.dr 直接路由

原理:DS在数据链路层直接修改mac地址,源IP和目标IP都没有改变 wKiom1jSVibwifuwAAApuB7sLwI979.png

只有进入的连接经过DS,能负载均衡100个rs左右。 DS:dip,vip RS:rip,vip vip是隐藏的,仅仅作为源地址不通信。可以配置在lo上,或者设置arp防火墙, 通信还是靠rip所在的网络设备

rule:

1)DR和RS必须在同一个物理网络中(同一网段) 2)RS一定网关不能指向DIP。 3)RIP不一定是私有地址,可以ssh上来管理,但有危险。 4)DR仅处理入栈请求,响应报文由RS发往client。 5)DR不支持端口映射,因为请求端口的时候,RS直接响应。 6)RS可以使用大多数操作系统,因为RS要隐藏vip。。

3.tun 隧道

基本同DR,但转发的时候,要封装隧道,再添加一个ip首部。

rule:

1)DR和RS必须可以跨越互联网 2)RIP必须是公网地址 3)DR仅处理入栈请求,响应报文由RS发往client。 4)响应报文一定不能通过DR 5)不支持端口映射 6)RS必须支持隧道协议OS 4.fullnat

调度算法(schedule method)

分为静态和动态:动态则考虑服务器的负载。

静态调度算法(4个)

1.rr(轮叫调度)

2.wrr(加权轮叫)

3.sh(源地址哈希):基于session的会话绑定。一个用户访问过某个RS,下次访问就由这个RS给他提供服务。

4.dh(目的地址哈希):不同用户,相同的访问需求,就访问同一个RS。

活动链接(active):客户与服务器建立连接并且有数据传送

非活动链接(inactive):只是建立连接,没有数据传送,没有断开连接

动态调度算法(6个)

1.lc(最少链接):

算法:active*256 + inactive

因为在实际生产环境中,inactive的数量是巨大的,所以不能忽略

2.wlc(加权最少链接) LVS的默认算法

算法:active*256+inactive)/weight 比lc多考虑了权重

3.sed(最短期望延迟)

基于wlc算法,避免wlc出现的问题。

算法:(active+1)256/weight (活动的连接数+1)256/除以权重 谁小发给谁

4.nq(用不排队)

谁的链接数为0,直接将请求发送给他,一般和sed结合使用,因为有些机器即使空着也调度不到他。

5.LBLC(基于本地的最少连接)类似于dh,目标地址hash

这个算法主要用于Cache集群系统,因为Cache集群的中客户请求报文的目标IP地址的变化,将相同的目标URL地址请求调度到同一台服务器,来提高服务器的访问的局部性和Cache命中率。从而调整整个集群的系统处理能力。但是,如果realserver的负载处于一半负载,就用最少链接算法,将请求发送给活动链接少的主机。

6.LBLCR(带复制的基于本地的最少链接)

该算法首先是基于最少链接的,当一个新请求收到后,一定会将请求发给最少连接的那台主机的。但这样又破坏了cache命中率。但这个算法中,集群服务是cache共享的,假设A的PHP跑了一遍,得到缓存。但其他realserver可以去A那里拿缓存,这是种缓存复制机制。

各种术语

DS:Director Server。前端负载均衡调度器。

RS:Real Server。后端真实工作的服务器。

VIP:向外部直接面向用户请求,作为用户请求的目标的IP地址。

DIP:Director Server IP,主要用于和服务器内部通讯的IP。

RIP:Real Server IP,后端真实服务器的IP地址。

CIP:Client IP,客户端的IP地址。

端口映射:如用户访问80,可在RS上服务实际工作在8080。(只有dnat支持)

vieyahn2017 commented 4 years ago

抓包分析LVS-NAT中出现的SYN_RECV

https://www.cnblogs.com/shizouwei/p/9072186.html

CIP:192.168.10.193

VIP:192.168.10.152:8000

DIP:100.10.8.152:8000

RIP:100.10.8.101:8000 和 100.10.8.102:8000

从CIP到RIP的TCP连接,总是超时。

在Director上看到,lvs已经把来着client的消息转发,但状态是SYN_RECV

# ipvsadm -lnc
IPVS connection entries
pro expire state source virtual destination
TCP 00:58 SYN_RECV 192.168.10.193:45346 192.168.10.152:8000 100.10.8.102:8000

抓包分析一下:

在realserver抓包,看到realserver已经收到了director转发的syn,而且在第一时间返回了syn ack。这是没有问题的。

在client抓包,看到client收到了syn ack,但是地址却是RIP。按照LVS-NAT的原理,在经过director之后,应该把RIP转换为VIP才对。

所以clinet虽然收到了syn ack,但无法和之前发送给VIP的syn配对起来,因此client一直处在等待VIP回复syn ack的状态。

之后检查了网络,发现从RIP到CIP存在多条路由,syn ack没有经过director就路由到了CIP。

解决方案:删除多条路由,将dip作为realserver的网关。

完成上述操作之后,发现lvs状态仍然是SYN_RECV。抓包后的pcap文件中,没有syn ack。于是想到是不是在什么地方丢掉了。

看到官方文档中有描述要设置re_ filter。

查了一下这个参数的解释

rp_filter参数有三个值,0、1、2,具体含义:

0:不开启源地址校验。 1:开启严格的反向路径校验。对每个进来的数据包,校验其反向路径是否是最佳路径。如果反向路径不是最佳路径,则直接丢弃该数据包。 2:开启松散的反向路径校验。对每个进来的数据包,校验其源地址是否可达,即反向路径是否能通(通过任意网口),如果反向路径不同,则直接丢弃该数据包。

default的值是1,这里改为2

echo 2 > /proc/sys/net/ipv4/conf/ 网卡名/rp_filter

echo 2 > /proc/sys/net/ipv4/conf/ 网卡名/rp_filter

systemctl restart network.service

再次尝试,succeed

vieyahn2017 commented 4 years ago

网络虚拟化中的offload技术:LSO/LRO,GSO/GRO,TSO/UFO,VXLAN

https://www.cnblogs.com/vleung/articles/4770557.html

offload 现在,越来越多的网卡设备支持 offload 特性,来提升网络收/发性能。offload 是将本来该操作系统进行的一些数据包处理(如分片、重组等)放到网卡硬件中去做,降低系统 CPU 消耗的同时,提高处理的性能。

包括 LSO/LRO、GSO/GRO、TSO/UFO 等。

LSO/LRO 分别对应到发送和接收两个方向,是 Large Segment Offload 和 Large Receive Offload。

首先来看 LSO。我们知道计算机网络上传输的数据基本单位是离散的网包,既然是网包,就有大小限制,这个限制就是 MTU(Maximum Transmission Unit)的大小,一般是1518字节。比如我们想发送很多数据出去,经过os协议栈的时候,会自动帮你拆分成几个不超过MTU的网包。然而,这个拆分是比较费计算资源的(比如很多时候还要计算分别的checksum),由 CPU 来做的话,往往会造成使用率过高。那可不可以把这些简单重复的操作 offload 到网卡上呢?

于是就有了 LSO,在发送数据超过 MTU 限制的时候(太容易发生了),OS 只需要提交一次传输请求给网卡,网卡会自动的把数据拿过来,然后进行切,并封包发出,发出的网包不超过 MTU 限制。

接下来看 LSO,当网卡收到很多碎片包的时候,LRO 可以辅助自动组合成一段较大的数据,一次性提交给 OS处理。

一般的,LSO 和 LRO 主要面向 TCP 报文。

GSO/GRO Generic Segmentation Offload 和 Generic Receive Offload,分别比 LSO 和 LRO 更通用,自动检测网卡支持特性,支持分包则直接发给网卡,否则先分包后发给网卡。新的驱动一般用 GSO/GRO。

TSO/UFO TCP Segmentation Offload 和 UDP fragmentation offload,分别对应 TCP 报文和 UDP 报文。

很典型的,TCP 协议中就考虑了分片存在的情况,往往是切分 TCP 的数据包,叫做 TSO。而一般的情况,则称为 LSO 或者 GSO。

对于其他不支持切片的协议例如 UDP,则只能进行 IP 层上的切片。

检查与开关 可以通过 ethtool -k eth0 命令来查看各个选项的当前状态,注意输出中各种 off-load 选项的状态。

# ethtool -k eth0
Features for eth0:
rx-checksumming: on
tx-checksumming: on
        tx-checksum-ipv4: on
        tx-checksum-ip-generic: off [fixed]
        tx-checksum-ipv6: on
        tx-checksum-fcoe-crc: off [fixed]
        tx-checksum-sctp: off [fixed]
scatter-gather: on
        tx-scatter-gather: on
        tx-scatter-gather-fraglist: off [fixed]
tcp-segmentation-offload: on
        tx-tcp-segmentation: on
        tx-tcp-ecn-segmentation: off [fixed]
        tx-tcp6-segmentation: on
udp-fragmentation-offload: off [fixed]
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off [fixed]
rx-vlan-offload: on
tx-vlan-offload: on
ntuple-filters: off [fixed]
receive-hashing: on
highdma: on [fixed]
rx-vlan-filter: on [fixed]
vlan-challenged: off [fixed]
tx-lockless: off [fixed]
netns-local: off [fixed]
tx-gso-robust: off [fixed]
tx-fcoe-segmentation: off [fixed]
tx-gre-segmentation: off [fixed]
tx-ipip-segmentation: off [fixed]
tx-sit-segmentation: off [fixed]
tx-udp_tnl-segmentation: off [fixed]
tx-mpls-segmentation: off [fixed]
fcoe-mtu: off [fixed]
tx-nocache-copy: on
loopback: off [fixed]
rx-fcs: off [fixed]
rx-all: off
tx-vlan-stag-hw-insert: off [fixed]
rx-vlan-stag-hw-parse: off [fixed]
rx-vlan-stag-filter: off [fixed]
l2-fwd-offload: off [fixed]
通过 ethtool -K eth0 gso off/on 这样的命令来开关。

VXLAN

VXLAN 现在已经是常见的二层虚拟化实现技术,但是由于它需要对每个数据包都进行封装、解封装等操作,导致基于软件的解决方案效率不高。 现在已经有网卡开始支持对 VXLAN 进行一些辅助操作,包括封装、解封装,以及 checksum 计算等。

网络虚拟化 那么,这些 offload 技术,跟虚拟化有什么联系呢?

在网络虚拟化中,一个最常见的技术就是隧道,这是实现overlay的通用手段。而实现隧道无非就两种思路,一种是把转发信息放到包头上,即封装/解封装(无论VXLAN还是STT都是这个思路);另外一种是由额外的数据库管理,转发时候进行查询。这两种思路各有利弊,这里不细说,如果我们采用封装/解封装的作法,那么可能原来网包并没有超过MTU限制,加上封装包头就超了,这就需要进行切片了。

所以 VMware 在其旗舰产品 NVP 中强调可以通过 TSO 来提高转发性能。

当然,前提是网卡能够支持,并且在os中配置打开。

此外,多核服务器中的网卡还推荐考虑 RSS(Receive Side Scaling),将网流分配到多个 RSS 队列上,多个队列绑定到不同的核心上,分散负载。

vieyahn2017 commented 4 years ago

keepalived组播故障排查

https://blog.51cto.com/qujunorz/1861541

虚拟机无法接收keepalived的vrrp组播

现象:

在Ubuntu1404的系统下安装了三台虚拟机,然后配置了一个简单的keepalived+haproxy服务。

结果启动后发现三台虚拟机都配上vip,keepalived.log日志中也未看见error的报错信息。

排查过程:

这些典型的脑裂(split brain)现象,一般来说先检查配置文件是否配的有问题。注意下virtual_router_id 的值。两边是否一样。

然后就是大杀器tcpdump出马了。

首先分别在三台机器执行

tcpdump -nn -c 20 -i any host 224.0.0.18

抓取20个VRRP包,正常输出应该如下:

15:30:25.406369 IP 192.168.70.99 > 224.0.0.18: VRRPv2, Advertisement, vrid 71, prio 1, authtype simple, intvl 1s, length 20
15:30:25.406440 IP 192.168.70.99 > 224.0.0.18: VRRPv2, Advertisement, vrid 71, prio 1, authtype simple, intvl 1s, length 20
15:30:25.406369 IP 192.168.70.99 > 224.0.0.18: VRRPv2, Advertisement, vrid 71, prio 1, authtype simple, intvl 1s, length 20

如果有输出,查看IP后面字段,在本次故障中,这里只有本机的IP,这说明vrrp包是正常发送出去的,但是没有收到其他机器的vrrp包,说明可能接收组播有问题。

然后再找一台同网段的机器,执行:

tcpdump -nn  -i any host 224.0.0.18

收集一段时间(这时候也可以注意下vrid有没有与别人的冲突),发现三台机的vrrp包都抓到了,说明三台机都能成功发出组播来,但是各自都没有收到。

由于手上也没有iperf工具,也没有做其他的排查,但是基本上也知道是内核参数的设置或者网卡的问题了。

原因:

由于这个系统在其他机器上是正常的,检查发现是在使用virt-manager新建虚拟机的时候,选择nat网卡模式,这种情况需要手动新建br网卡,再使用桥接模式才能成功。

补充:

防火墙开放vrrp包:

#iptables -I INPUT -i eth0 -d 224.0.0.0/8 -p vrrp -j ACCEPT
# iptables -I OUTPUT -o eth0 -d 224.0.0.0/8 -p vrrp -j ACCEPT

内核开启转发:

# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# sysctl -p
vieyahn2017 commented 4 years ago

realServer.sh

#!/bin/bash
VIP=""

if [ -n "$2" ];then
    VIP=$2
    sed -i s#^VIP=.*#VIP=$2#g $0
fi

. /etc/rc.d/init.d/functions

case "$1" in
# 禁用本地的ARP请求、绑定本地回环地址
start)
    # 未设置浮动ip 则退出
    if [[ ! ${VIP} =~ ^([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*) ]]; then
        echo "LVS-VIP is incorrect, exit realServer.sh now."
        exit 0
    fi
    /sbin/ifconfig lo down
    /sbin/ifconfig lo up
    echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
    echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
    echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
    echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
    /usr/sbin/sysctl -p >/dev/null 2>&1
    /sbin/ifconfig lo:0 $VIP netmask 255.255.255.255 up     #在回环地址上绑定VIP,设定掩码,与Direct Server(自身)上的IP保持通信
    /sbin/route add -host $VIP dev lo:0
    echo "LVS-DR real server starts successfully."
    ;;
stop)
    # 未设置浮动ip 则退出
    if [ -z "${VIP}" ]; then
        exit 0
    fi
    # 未设置浮动ip 则退出
    if [[ ! ${VIP} =~ ^([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*) ]]; then
        echo "LVS-VIP is incorrect, exit realServer.sh now."
        exit 0
    fi
    /sbin/ifconfig lo:0 down
    /sbin/route del $VIP >/dev/null 2>&1
    echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
    echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
    echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
    echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
    echo "LVS-DR real server stopped."
    ;;
status)
    isLoOn=`/sbin/ifconfig lo:0 | grep "$VIP"`
    isRoOn=`/bin/netstat -rn | grep "$VIP"`
    if [ "$isLoON" == "" -a "$isRoOn" == "" ]; then
        echo "LVS-DR real server has run yet."
    else
        echo "LVS-DR real server is running."
    fi
    exit 3
    ;;
*)
    echo "Usage: $0 {start|stop|status}"
    exit 1
esac
exit 0

nginx: install.sh

部分代码


OS_NAME=$1

#网关地址
gateway_ip=$2

if [ -n "$3" ]; then
    loadbalance_type=lvs
    # lvs 浮动IP
    LVS_VIP=$3
else
    loadbalance_type=nginx
fi

arr=(${gateway_ip//,/ })
num=${#arr[@]}

# 网关ip数量为1时候直接替换
if [ "$num" -eq 1 ];then
    cp $software_path/nginx.conf.temp $software_path/nginx_http.conf
    sed -i s#{{gateway_ip}}#$gateway_ip# $software_path/nginx_http.conf
else
    # 网关ip数量大于1时候替换比较麻烦:
    # 先读入配置文件,根据数量,把需要替换的行增加到相应的数量
    cat $software_path/nginx.conf.temp | while read line
    do
        if [ `echo $line | grep -c 'server {{gateway_ip}}'` -ne 0 ]; then
            for ((i=1;i<=${num};i++))
            do
               echo $line | sed 's/{{gateway_ip}}/{{gateway_ip_'${i}'}}/g' >> $software_path/nginx.conf
            done
        else
            echo $line >> $software_path/nginx.conf
        fi
    done
    # 再对相应的ip做替换
    for ((i=1;i<=${num};i++))
    do
        sed -i s#{{gateway_ip_${i}}}#${arr[i-1]}# $software_path/nginx_http.conf
    done
    sed -i s#{{gateway_ip}}#${arr[0]}# $software_path/nginx_http.conf

fi

if [ "$loadbalance_type" == "lvs" ]; then
    sed -i s#^VIP=.*#VIP=$LVS_VIP#g $software_path/realServer.sh
fi

#
# cp ...
#

if [ "$loadbalance_type" == "lvs" ]; then
    echo "run realServer.sh, turn ifconig lo on"
    sh $target_path/realServer.sh start
fi
vieyahn2017 commented 4 years ago

keepalived.conf (来自https://www.cnblogs.com/edisonchou/p/4281978.html)

global_defs {  
   notification_email {  
         edisonchou@hotmail.com  
   }  
   notification_email_from sns-lvs@gmail.com  
   smtp_server 192.168.80.1  
   smtp_connection_timeout 30
   router_id LVS_DEVEL  # 设置lvs的id,在一个网络内应该是唯一的
}  
vrrp_instance VI_1 {  
    state MASTER   #指定Keepalived的角色,MASTER为主,BACKUP为备          
    interface eth1  #指定Keepalived的角色,MASTER为主,BACKUP为备
    virtual_router_id 51  #虚拟路由编号,主备要一致
    priority 100  #定义优先级,数字越大,优先级越高,主DR必须大于备用DR    
    advert_int 1  #检查间隔,默认为1s
    authentication {  
        auth_type PASS  
        auth_pass 1111  
    }  
    virtual_ipaddress {  
        192.168.80.200  #定义虚拟IP(VIP)为192.168.2.33,可多设,每行一个
    }  
}  
# 定义对外提供服务的LVS的VIP以及port
virtual_server 192.168.80.200 80 {  
    delay_loop 6 # 设置健康检查时间,单位是秒                    
    lb_algo wrr # 设置负载调度的算法为wlc                   
    lb_kind DR # 设置LVS实现负载的机制,有NAT、TUN、DR三个模式   
    nat_mask 255.255.255.0                
    persistence_timeout 0          
    protocol TCP                  
    real_server 192.168.80.102 80 {  # 指定real server1的IP地址
        weight 3   # 配置节点权值,数字越大权重越高              
        TCP_CHECK {  
        connect_timeout 10         
        nb_get_retry 3  
        delay_before_retry 3  
        connect_port 80  
        }  
    }  
    real_server 192.168.80.103 80 {  # 指定real server2的IP地址
        weight 3  # 配置节点权值,数字越大权重越高  
        TCP_CHECK {  
        connect_timeout 10  
        nb_get_retry 3  
        delay_before_retry 3  
        connect_port 80  
        }  
     }  
} 

模板:

! Configuration File for keepalived

global_defs {
    router_id {{router_id}}
}

vrrp_sync_group VGM2 {
    group {
        VI_2
    }
}

vrrp_instance VI_2 {
    # 非抢占模式,设置nopreempt,两节点state都设置为 BACKUP
    state BACKUP
    #绑定对应的网卡
    interface {{eth_keepalived}}
    virtual_router_id {{vrid}}
    #priority这个配置主从不同,主的比从的高,主、从值相差太大(确保主备可以正常切换)
    priority {{priority}}
    advert_int 1
    nopreempt
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        {{virtual_ip}}
    }

}

virtual_server {{virtual_ip}} {{web_port}} {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    persistence_timeout 50
    protocol TCP

#real_server_web_start
    real_server {{nginx_ip_web}} {{web_port}} {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port {{web_port}}
        }
    }

#real_server_web_end

}

virtual_server {{virtual_ip}} {{backend_port}} {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    persistence_timeout 50
    protocol TCP

#real_server_backend_start
    real_server {{nginx_ip_backend}} {{backend_port}} {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port {{backend_port}}
        }
    }

#real_server_backend_end

}
vieyahn2017 commented 4 years ago

install_lvs.sh


OS_NAME=$1

#浮动ip
v_ip=$2

#转发的目标服务器(nginx)ip
real_server_ips=$3

#判断主从标识,1主,2从
flag_master=$4

#使用网卡
eth_keepalived=$5

#virtual_router_id
vrid=$6

#local_ip 用于设置global_def下的router_id
local_ip=$7

#port
v_web_port=8000
v_backend_port=8001

#
#cp
#

sed -i s#{{virtual_ip}}#${v_ip}#g ${software_path}/keepalived.conf
sed -i s#{{web_port}}#${v_web_port}#g ${software_path}/keepalived.conf
sed -i s#{{backend_port}}#${v_backend_port}#g ${software_path}/keepalived.conf

nginx_ip_num=$((`echo $real_server_ips | grep -o ',' | wc -l ` + 1))
for((i=0;i<$nginx_ip_num;i++)); do
    count=$(($i+1))
    service_ip=`echo $real_server_ips | awk -F ',' '{print $'$count'}'`

    sed -i -rn 'p;/#real_server_web_start/,/#real_server_web_end/H;/#real_server_web_end/{g;s/^\n//;p}' ${software_path}/keepalived.conf
    sed -i '0,/#real_server_web_start/{/#real_server_web_start/d}' ${software_path}/keepalived.conf
    sed -i '0,/{{nginx_ip_web}}/s/{{nginx_ip_web}}/'${service_ip}'/' ${software_path}/keepalived.conf
    sed -i '0,/#real_server_web_end/{/#real_server_web_end/d}' ${software_path}/keepalived.conf

    sed -i -rn 'p;/#real_server_backend_start/,/#real_server_backend_end/H;/#real_server_backend_end/{g;s/^\n//;p}' ${software_path}/keepalived.conf
    sed -i '0,/#real_server_backend_start/{/#real_server_backend_start/d}' ${software_path}/keepalived.conf
    sed -i '0,/{{nginx_ip_backend}}/s/{{nginx_ip_backend}}/'${service_ip}'/' ${software_path}/keepalived.conf
    sed -i '0,/#real_server_backend_end/{/#real_server_backend_end/d}' ${software_path}/keepalived.conf
done

real_server_numbers=`grep -n "#real_server_web" ${software_path}/keepalived.conf | awk -F ':' '{print $1}' | xargs | tr ' ' ','`
sed -i ${real_server_numbers}d ${software_path}/keepalived.conf
real_server_numbers=`grep -n "#real_server_backend" ${software_path}/keepalived.conf | awk -F ':' '{print $1}' | xargs | tr ' ' ','`
sed -i ${real_server_numbers}d ${software_path}/keepalived.conf

# ${flag_master}不再使用
if [ ${flag_master} -eq 1 ]; then
   sed -i s#{{state}}#MASTER#g ${software_path}/keepalived.conf
   sed -i s#{{priority}}#100#g ${software_path}/keepalived.conf
else
   sed -i s#{{state}}#BACKUP#g ${software_path}/keepalived.conf
   sed -i s#{{priority}}#96#g ${software_path}/keepalived.conf
fi

sed -i s#{{eth_keepalived}}#${eth_keepalived}#g ${software_path}/keepalived.conf
sed -i s#{{vrid}}#${vrid}#g ${software_path}/keepalived.conf
sed -i s#{{router_id}}#${local_ip}#g ${software_path}/keepalived.conf

#...