LVS之2---基于LVS负载均衡集群架构实现

LVS之2---基于LVS负载均衡集群架构实现

ipvsadm

software package

[root@lb01 ~]# rpm -ql ipvsadm
/etc/sysconfig/ipvsadm-config             # 配置文件
/usr/lib/systemd/system/ipvsadm.service   # 服务
/usr/sbin/ipvsadm                         # 主命令
/usr/sbin/ipvsadm-restore                 # 导入规则命令
/usr/sbin/ipvsadm-save                    # 导出规则命令
/usr/share/doc/ipvsadm-1.27               # 说明书
/usr/share/doc/ipvsadm-1.27/README
/usr/share/man/man8/ipvsadm-restore.8.gz
/usr/share/man/man8/ipvsadm-save.8.gz
/usr/share/man/man8/ipvsadm.8.gz

Options

Usage:
  ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask] [--pe persistence_engine] [-b sched-flags]
  ipvsadm -D -t|u|f service-address
  ipvsadm -C
  ipvsadm -R
  ipvsadm -S [-n]
  ipvsadm -a|e -t|u|f service-address -r server-address [options]
  ipvsadm -d -t|u|f service-address -r server-address
  ipvsadm -L|l [options]
  ipvsadm -Z [-t|u|f service-address]
  ipvsadm --set tcp tcpfin udp
  ipvsadm --start-daemon state [--mcast-interface interface] [--syncid sid]
  ipvsadm --stop-daemon state

Commands:
  --add-service     -A        添加具有选项的虚拟服务
  --edit-service    -E        编辑具有选项的虚拟服务
  --delete-service  -D        删除虚拟服务
  --clear           -C        清理整张表
  --restore         -R        从标准输入还原规则
  --save            -S        保存规则到标准输出
  --add-server      -a        添加带有选项的真实服务器
  --edit-server     -e        编辑带有选项的真实服务器
  --delete-server   -d        删除真实服务器
  --list            -L|-l     列出表
  --zero            -Z        一个或所有服务的计数器清零(清空当前的连接数量等)
  --set tcp tcpfin udp        设置连接超时值
  --start-daemon              启动连接同步守护程序
  --stop-daemon               停止连接同步守护程序

Options:
  --tcp-service  -t service-address   service-address is host[:port]
  --udp-service  -u service-address   service-address is host[:port]
  --fwmark-service  -f fwmark         fwmark是一个大于零的整数
  --ipv6         -6                   fwmark使用ipv6
  --scheduler    -s 调度器             one of rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq,(default=wlc)
  --pe            engine              备用持久性引擎可以是sip,默认不设置
  --persistent   -p [timeout]         持久服务,会话保持时间,省略时长,默认360秒
  --netmask      -M netmask           持久粒度掩码
  --real-server  -r server-address    server-address is host (and port)
指定工作模式:
  --gatewaying   -g                   网关 (直接路由) (default)
  --ipip         -i                   ipip 封装 (tunneling)
  --masquerading -m                   伪装 (NAT)
  
  --weight       -w weight            真实服务器的权值
  --u-threshold  -x uthreshold        连接的上限阈值
  --l-threshold  -y lthreshold        连接的下限阈值
  --mcast-interface interface         用于连接同步的多播接口
  --syncid sid                        用于连接同步的 syncid (default=255)
  --connection   -c                   输出当前的IPVS连接
  --timeout                           输出超时 (tcp tcpfin udp)
  --daemon                            输出守护进程信息
  --stats                             输出统计信息
  --rate                              输出速率信息
  --exact                             精确展开数字(显示精确值)
  --thresholds                        输出阈值信息
  --persistent-conn                   输出持久连接信息
  --nosort                            禁用服务/服务器项的输出排序
  --sort                              为了向后兼容,什么都不做
  --ops          -o                   单包调度
  --numeric      -n                   以数字输出地址和端口
  --sched-flags  -b flags             计划程序标志 (逗号分隔)

常用命令

管理集群服务

添加:-A -t|u|f service-address [-s scheduler]
	 -t: TCP协议的集群
	 -u: UDP协议的集群
		service-address:     IP:PORT
	 -f: FWM: 防火墙标记
		service-address: Mark Number
修改:-E
删除:-D -t|u|f service-address

例如:
# ipvsadm -A -t 10.10.0.1:80 -s rr

管理集群服务中的 RS

添加:-a -t|u|f service-address -r server-address [-g|i|m] [-w weight]
	-t|u|f service-address:事先定义好的某集群服务
	-r server-address: 某RS的地址,在NAT模型中,可使用IP:PORT实现端口映射;
	[-g|i|m]: LVS类型
		-g: DR
		-i: TUN
		-m: NAT
	[-w weight]: 定义服务器权重
修改:-e
删除:-d -t|u|f service-address -r server-address

例如:
# ipvsadm -a -t 10.10.0.2:80 -r 192.168.10.8 -m
# ipvsadm -a -t 10.10.0.3:80 -r 192.168.10.9:8080 -m

查看规则

-L|-l
-n:数字格式显式主机地址和端口
--stats:统计数据
--rate: 速率
--timeout: 显示tcp、tcpfin和udp的会话超时时长
-c: 显示当前的ipvs连接状况

删除所有集群服务

-C:清空 ipvs 规则

保存及重载规则

启动ipvsadm服务并设置为开机启动

systemctl start ipvsadm
systemctl enable ipvsadm

停止ipvsadm服务会自动保存到/etc/sysconfig/ipvsadm配置文件

systemctl stop ipvsadm

重启ipvsadm服务会自动重载/etc/sysconfig/ipvsadm配置文件中的LVS规则

systemctl restart ipvsadm

手动将LVS规则保存在指定的/tmp/ipvs.log文件中

ipvsadm-save > /tmp/ipvs.log
ipvsadm -R > /tmp/ipvs.log

手动将指定的/tmp/ipvs.log文件中的LVS规则加载到ipvsadm服务中

ipvsadm-restore < /tmp/ipvs.log
ipvsadm -S  < /tmp/ipvs.log

内存映射文件

 [root@lb01 ~]# ls /proc/net/ip_vs* | xargs -l
 /proc/net/ip_vs               # ipvs规则
 /proc/net/ip_vs_app
 /proc/net/ip_vs_conn          # ipvs连接
 /proc/net/ip_vs_conn_sync
 /proc/net/ip_vs_stats
 /proc/net/ip_vs_stats_percpu

arp_ignore:定义接受到ARP请求时的相应级别
      0:只要本地配置的有相应地址,就给予响应(默认)
      1:仅回应目标IP地址是本地的入网地址的arp请求。
      2:仅回应目标IP地址是本地的入网地址,而且源IP和目标IP在同一个子网的arp请求。
      3:不回应该网络界面的arp请求,而只对设置的唯一和连接地址做出回应
      4-7:保留未使用
      8:不回应所有的arp请求
arp_announce: 定义将自己地址向外界通告的通告级别

支持内核参数

# 查看内核是否有lvs模块
[root@lb01 ~]# grep -i -C 10 " IPVS " /boot/config-3.10.0-1127.19.1.el7.x86_64
... ...
# IPVS transport protocol load balancing support
#
CONFIG_IP_VS_PROTO_TCP=y  # 开启tcp
CONFIG_IP_VS_PROTO_UDP=y  # 开启udp
CONFIG_IP_VS_PROTO_AH_ESP=y
CONFIG_IP_VS_PROTO_ESP=y
CONFIG_IP_VS_PROTO_AH=y
CONFIG_IP_VS_PROTO_SCTP=y

#
# IPVS scheduler # 默认支持的算法
#
CONFIG_IP_VS_RR=m
CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
CONFIG_IP_VS_SH=m
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m

#
# IPVS SH scheduler
#
CONFIG_IP_VS_SH_TAB_BITS=8

#
# IPVS application helper
#
CONFIG_IP_VS_FTP=m
CONFIG_IP_VS_NFCT=y
CONFIG_IP_VS_PE_SIP=m

#
# IP: Netfilter Configuration
#
CONFIG_NF_DEFRAG_IPV4=m
CONFIG_NF_CONNTRACK_IPV4=m

实现

环境准备

  • CentOS 7.6 关闭防火墙和selinux

  • Keepalived 1.3.5

  • ipvsadm 1.27

  • Nginx 1.18.0

主机名 eth0 eth1 角色
lb01 DIP:10.0.0.5 VIP:10.0.0.3 172.16.1.5 DS1
lb02 DIP:10.0.0.6 VIP:10.0.0.3 172.16.1.6 DS2
web01 RIP:10.0.0.7 172.16.1.7 RS1
web02 RIP:10.0.0.8 172.16.1.8 RS2

相关软件安装配置

RS

yum install nginx -y
cat > /etc/nginx/conf.d/web.conf <<EOF
server {
    listen       80;
    location / {
        root /usr/share/nginx/html;
    }
}
EOF
echo `hostname` >/usr/share/nginx/html/index.html
systemctl start nginx

DS

yum install ipvsadm keepalived -y
[root@lb01 ~]# curl 10.0.0.7
web01
[root@lb01 ~]# curl 10.0.0.8
web02

LVS-DR模式(VIP与RIP在同一网段)

架构图:

img

                              |                
                              |VIP:10.0.0.3
                      +-------+--------+        
                      |    DS1:lb01    |        
                      |      LVS       |        
                      +-------+--------+        
                              |DIP:10.0.0.5		       
                              |
  +------------+VIP:10.0.0.3  |   VIP:10.0.0.3+------------+
  | RS1:web01  |RIP:10.0.0.7  |   RIP:10.0.0.8| RS2:web02  |
  | Web Server +--------------+---------------+ Web Server |
  +------------+                              +------------+

DS

# 设置 tcp tcpfin udp 连接超时值
ipvsadm --set 10 5 20
# 手动绑定VIP到eth0
ip a a 10.0.0.3/32 dev eth0
# 创建LVS服务调度算法规则,将VIP地址绑定在LVS调度器上,指定调度算法rr
ipvsadm -A -t 10.0.0.3:80 -s rr
# 使用DR模型,添加后端RS1服务器
ipvsadm -a -t 10.0.0.3:80 -r 10.0.0.7 -g
# 使用DR模型,添加后端RS2服务器
ipvsadm -a -t 10.0.0.3:80 -r 10.0.0.8 -g
# 查看规则表
ipvsadm -ln
# 保存规则
ipvsadm-save > /etc/sysconfig/ipvsadm
systemctl start ipvsadm
systemctl enable ipvsadm

RS

# 开启ARP抑制
cat >> /etc/sysctl.conf << EOF
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.lo.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.lo.arp_announce=2
EOF
sysctl -p
# 手动绑定VIP到eth0
ip a a 10.0.0.3/32 dev lo

测试

[root@m01 ~]# i=0;while ((i<6)); do curl 10.0.0.3; sleep 0.5;((i++));done;
web01
web02
web01
web02
web01
web02

注意:如果VIP和RIP的IP地址在同一网段,会导致客户端也可以直接访问RS服务器内网地址,可能会不需要经过LVS,造成访问网络风险。


持久连接

persistence template:持久连接模板:将多个集群服务归并到一起统一调度

  • PPC:每端口持久;持久连接生效范围仅为单个集群服务;如果有多个集群服务,每服务被单独持久调度;
  • PCC:每客户端持久;持久连接生效范围为所有服务;定义集群服务时,其TCP或UDP协议的目标端口要使用0;
  • PFWM:每FWM持久:持久连接生效范围为定义为同一个FWM下的所有服务;

语法

ipvsadm -A t|u|f server-address -s scheduler -p

无-p选项:不启用持久链接
-p:指定持久时长,省略时长,默认360秒

定义一个PPC持久链接服务 (客户端请求同一个集群服务,始终调度到同一台RS服务器)

ipvsadm -A -t 10.0.0.3:80 -s rr -p
ipvsadm -a -t 10.0.0.3:80 -r 10.0.0.7 -g -w 1
ipvsadm -a -t 10.0.0.3:80 -r 10.0.0.8 -g -w 1

定义一个PCC持久链接服务(客户端的所有请求都调度到同一个realserver)

ipvsadm -A -t 10.0.0.3:80 -s rr -p
ipvsadm -a -t 10.0.0.3:80 -r 10.0.0.7 -g
ipvsadm -a -t 10.0.0.3:80 -r 10.0.0.8 -g

定义一个FWM持久链接服务 (根据防火墙标记,将相同的标记的调度到同一个realserver)

iptables -t mangle -A PREROUTING -d 10.0.0.3 -p tcp --dport 80 -j MARK --set-mark 10
iptables -t mangle -A PREPOUTING -d 10.0.0.3 -p tcp --dport 443 -j MARK --set-mark 10
ipvsadm -A -f 10 -s rr -p
ipvsadm -a -f 10 -r 10.0.0.7 -g -w 1
ipvsadm -a -f 10 -r 10.0.0.8 -g -w 1

80/443 的请求都会调用到同一个realserver

示例

DS

ipvsadm -C
ipvsadm -A -t 10.0.0.3:80 -s rr -p 5
ipvsadm -a -t 10.0.0.3:80 -r 10.0.0.7 -g
ipvsadm -a -t 10.0.0.3:80 -r 10.0.0.8 -g
ipvsadm -ln

测试

# 一直保持连接
[root@m01 ~]# i=0;while ((i<6)); do curl 10.0.0.3; sleep 1;((i++));done;
web01
web01
web01
web01
web01
web01
# 长连接
[root@m01 ~]# i=0;while ((i<6)); do curl 10.0.0.3; sleep 350;((i++));done;
web01
web02
web01
web02

LVS-NAT模式

架构图:

img

                                |
                                |VIP:10.0.0.3
                        +-------+--------+        
                        |    DS1:lb01    |        
                        |      LVS       |        
                        +-------+--------+        
                                |DIP:172.16.1.5	
                                |
    +------------+              |               +------------+
    | RS1:web01  |RIP:172.16.1.7| RIP:172.16.1.8| RS2:web02  |
    | Web Server +--------------+---------------+ Web Server |
    +------------+                              +------------+

DS

ipvsadm -C
# 手动绑定VIP到eth0
ip a a 10.0.0.3/32 dev eth0
# 创建LVS服务调度算法规则,将VIP地址绑定在LVS调度器上,指定调度算法rr
ipvsadm -A -t 10.0.0.3:80 -s rr
# 使用NAT模型,添加后端RS1服务器
ipvsadm -a -t 10.0.0.3:80 -r 172.16.1.7 -m
# 使用NAT模型,添加后端RS2服务器
ipvsadm -a -t 10.0.0.3:80 -r 172.16.1.8 -m
# 查看规则表
ipvsadm -ln
# 保存规则
ipvsadm-save > /etc/sysconfig/ipvsadm
# 开启路由转发功能
cat >> /etc/sysctl.conf << EOF
net.ipv4.ip_forward=1
EOF
sysctl -p

RS

mv /etc/sysconfig/network-scripts/ifcfg-eth0{,.bak}
cat > /etc/sysconfig/network-scripts/ifcfg-eth1 << EOF
TYPE=Ethernet
BOOTPROTO=static
NAME=eth1
DEVICE=eth1
ONBOOT=yes
IPADDR=172.16.1.7
PREFIX=24
GATEWAY=172.16.1.5
DNS1=223.5.5.5
EOF
systemctl restart network
mv /etc/sysconfig/network-scripts/ifcfg-eth0{,.bak}
cat > /etc/sysconfig/network-scripts/ifcfg-eth1 << EOF
TYPE=Ethernet
BOOTPROTO=static
NAME=eth1
DEVICE=eth1
ONBOOT=yes
IPADDR=172.16.1.8
PREFIX=24
GATEWAY=172.16.1.5
DNS1=223.5.5.5
EOF
systemctl restart network

测试

[root@m01 ~]# i=0;while ((i<6)); do curl 10.0.0.3; sleep 0.5;((i++));done;
web01
web02
web01
web02
web01
web02

WRR算法

DS

ipvsadm -C
# 手动绑定VIP到eth0
ip a a 10.0.0.3/32 dev eth0
# 创建LVS服务调度算法规则,将VIP地址绑定在LVS调度器上,指定调度算法wrr
ipvsadm -A -t 10.0.0.3:80 -s wrr
# 使用NAT模型,添加后端RS1服务器,权重3
ipvsadm -a -t 10.0.0.3:80 -r 172.16.1.7 -m -w 3
# 使用NAT模型,添加后端RS2服务器,权重1
ipvsadm -a -t 10.0.0.3:80 -r 172.16.1.8 -m -w 1
# 查看规则表
ipvsadm -ln
# 保存规则
ipvsadm-save > /etc/sysconfig/ipvsadm

测试

[root@m01 ~]# i=0;while ((i<12)); do curl 10.0.0.3; sleep 0.5;((i++));done;
web02
web01
web01
web01
web02
web01
web01
web01
web02
web01
web01
web01

HTTPS

借助于 FireWall Mark(防火墙标签)来分类报文,而后基于标记定义集群服务;可将多个不同的应用使用同一个集群服务进行调度,贴同一个标签就是同一个服务

--set-mark NUMBER  # NUMBER 可为十六进制数,格式0xffff

实现方法:

# LVS主机打标记:
iptables -t mangle -A PREROUTING -d $vip -p $proto -m multiport --dports $port1,$port2,… -j MARK --set-mark NUMBER
# LVS主机基于标记定义集群服务:
ipvsadm -A -f NUMBER [options]

DS

# 最后一个10是自定义的标签
iptables  -t mangle -A PREROUTING -d 10.0.0.3  -p tcp -m multiport --ports 80,443 -j MARK --set-mark 10
# 查看防火墙的规则
iptables -t mangle -vnL
ipvsadm -C
# 添加标签调度算法
ipvsadm -A -f 10 -s rr
# 使用NAT模型,添加后端RS1服务器
ipvsadm -a -f 10 -r 172.16.1.7 -m
# 使用NAT模型,添加后端RS1服务器
ipvsadm -a -f 10 -r 172.16.1.8 -m
# 查看规则表
ipvsadm -ln
# 保存规则
ipvsadm-save > /etc/sysconfig/ipvsadm

RS

# 安装mod_ssl模块,并启动httpd服务
yum install mod_ssl
systemctl start httpd

验证

[root@m01 ~]# i=0;while ((i<6)); do curl 10.0.0.3; sleep 0.5;((i++));done;
web01
web02
web01
web02
web01
web02

Keepalived集成LVS

keepalived中集成有LVS,可以不用安装ipvsadm,在keepalived配置文件内就能配置LVS,可以用于双机热备的自动故障转移,也可以管理lvs的RS列表,自动对RS做健康检查。

                              |  
         +--------------------+--------------------+
         |-----         VIP:10.0.0.3          -----|
 +-------+--------+                        +-------+--------+        
 |    DS1:lb01    |                        |    DS2:lb02    |        
 |   keepalived   |                        |   keepalived   |        
 +-------+--------+                        +-------+--------+        
         |DIP:10.0.0.5                             |DIP:10.0.0.6	
         +--------------------+--------------------+
                              |
  +------------+              |               +------------+
  | RS1:web01  |RIP:10.0.0.7  |   RIP:10.0.0.8| RS2:web02  |
  | Web Server +--------------+---------------+ Web Server |
  +------------+                              +------------+

DS

主lb1配置

cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
	router_id lb01
}

vrrp_instance VI_1 {
    # 指定Keepalived角色,MASTER 为主,BACKUP 为备
    state MASTER
    # 当前 IP 对应的网卡,可以使用 ip a 查看
    interface eth0
    # 虚拟路由编号(0-255),主备一致
    virtual_router_id 51
    # 优先级,数字越大,优先级越高,主必须大于备
    priority 100
    # 通告时间间隔:默认1s,主备一致
    advert_int 1
    # 认证机制,主备一致,密码最多为8位
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.3  # 虚拟IP(VIP),可多设,每行一个
    }
}

# 定义对外提供服务的LVS的VIP以及port
virtual_server 10.0.0.3 80 {
    # 设置健康检查时间,单位是秒
    delay_loop 6
    # 设置调度算法为rr
    lb_algo rr
    # 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
    lb_kind DR
    nat_mask 255.255.255.0
    # 持久连接超时时间
    persistence_timeout 0
    protocol TCP
    # 指定real server1的IP地址
    real_server 10.0.0.7 80 {
        # 配置节点权值,数字越大权重越高
        weight 3
        TCP_CHECK {
            connect_timeout 10
            # 旧版本为 nb_get_retry 
            retry 3
            delay_before_retry 3
            connect_port 80
        }
    }
    # 指定real server2的IP地址
    real_server 10.0.0.8 80 {
        weight 3
        TCP_CHECK {
            connect_timeout 10
            retry 3
            delay_before_retry 3
            connect_port 80
        }
     }
}
EOF
# 删除手动绑定的VIP
ip a d 10.0.0.3/32 dev eth0
systemctl start keepalived

​ 从lb2配置

cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
	router_id lb01
}

vrrp_instance VI_1 {
    # 指定Keepalived角色,MASTER 为主,BACKUP 为备
    state BACKUP
    # 当前 IP 对应的网卡,可以使用 ip a 查看
    interface eth0
    # 虚拟路由编号(0-255),主备一致
    virtual_router_id 51
    # 优先级,数字越大,优先级越高,主必须大于备
    priority 50
    # 通告时间间隔:默认1s,主备一致
    advert_int 1
    # 认证机制,主备一致,密码最多为8位
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.3  # 虚拟IP(VIP),可多设,每行一个
    }
}

# 定义对外提供服务的LVS的VIP以及port
virtual_server 10.0.0.3 80 {
    # 设置健康检查时间,单位是秒
    delay_loop 6
    # 设置调度算法为rr
    lb_algo rr
    # 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
    lb_kind DR
    nat_mask 255.255.255.0
    # 持久连接超时时间
    persistence_timeout 0
    protocol TCP
    # 指定real server1的IP地址
    real_server 10.0.0.7 80 {
        # 配置节点权值,数字越大权重越高
        weight 3
        TCP_CHECK {
            connect_timeout 10
            # 旧版本为 nb_get_retry 
            retry 3
            delay_before_retry 3
            connect_port 80
        }
    }
    # 指定real server2的IP地址
    real_server 10.0.0.8 80 {
        weight 3
        TCP_CHECK {
            connect_timeout 10
            retry 3
            delay_before_retry 3
            connect_port 80
        }
     }
}
EOF
# 删除手动绑定的VIP
ip a d 10.0.0.3/32 dev eth0
systemctl start keepalived

测试

[root@m01 ~]# i=0;while ((i<6)); do curl 10.0.0.3; sleep 0.5;((i++));done;
web01
web02
web01
web02
web01
web02
# 关闭DS1,仍然可以访问
[root@lb01 ~]# systemctl stop keepalived
[root@m01 ~]# i=0;while ((i<6)); do curl 10.0.0.3; sleep 0.5;((i++));done;
web01
web02
web01
web02
web01
web02

LVS-DR模式(VIP与RIP不在同一网段)

                              |  
                              +--------------------+
                                                   |IP1:10.0.0.6
 +----------------+                        +-------+--------+        
 |    DS1:lb01    |                        |   Route:lb02   |        
 |      LVS       |                        |      Route     |        
 +-------+--------+                        +-------+--------+        
         |VIP:10.0.1.3                             |IP2:172.16.1.6	
         |DIP:172.16.1.5                           |VIP网关:10.0.1.6
         +--------------------+--------------------+
                              |
  +------------+VIP:10.0.1.3  |   VIP:10.0.1.3+------------+
  | RS1:web01  |RIP:172.16.1.7| RIP:172.16.1.8| RS2:web02  |
  | Web Server +--------------+---------------+ Web Server |
  +------------+                              +------------+

Router

# 手动绑定VIP网关到eth1
ip a a 10.0.1.6/24 dev eth1
# 开启路由转发功能
cat >> /etc/sysctl.conf << EOF
net.ipv4.ip_forward=1
EOF
sysctl -p

DS

ipvsadm -C
# 手动绑定VIP到eth0
ip a a 10.0.0.3/32 dev eth0
# 创建LVS服务调度算法规则,将VIP地址绑定在LVS调度器上,指定调度算法rr
ipvsadm -A -t 10.0.1.3:80 -s rr
# 使用DR模型,添加后端RS1服务器
ipvsadm -a -t 10.0.1.3:80 -r 172.16.1.7 -g
# 使用DR模型,添加后端RS2服务器
ipvsadm -a -t 10.0.1.3:80 -r 172.16.1.8 -g
# 查看规则表
ipvsadm -ln
# 保存规则
ipvsadm-save > /etc/sysconfig/ipvsadm
# 开启路由转发功能
cat >> /etc/sysctl.conf << EOF
net.ipv4.ip_forward=1
EOF
sysctl -p
mv /etc/sysconfig/network-scripts/ifcfg-eth0{,.bak}
cat > /etc/sysconfig/network-scripts/ifcfg-eth1 << EOF
TYPE=Ethernet
BOOTPROTO=static
NAME=eth1
DEVICE=eth1
ONBOOT=yes
IPADDR=172.16.1.5
PREFIX=24
GATEWAY=172.16.1.6
DNS1=223.5.5.5
EOF
systemctl restart network
# 手动绑定VIP到eth1
ip a a 10.0.1.3/32 dev eth1

RS

mv /etc/sysconfig/network-scripts/ifcfg-eth0{,.bak}
cat > /etc/sysconfig/network-scripts/ifcfg-eth1 << EOF
TYPE=Ethernet
BOOTPROTO=static
NAME=eth1
DEVICE=eth1
ONBOOT=yes
IPADDR=172.16.1.7
PREFIX=24
GATEWAY=172.16.1.6
DNS1=223.5.5.5
EOF
systemctl restart network
# 手动绑定VIP到lo
ip a a 10.0.1.3/32 dev lo
mv /etc/sysconfig/network-scripts/ifcfg-eth0{,.bak}
cat > /etc/sysconfig/network-scripts/ifcfg-eth1 << EOF
TYPE=Ethernet
BOOTPROTO=static
NAME=eth1
DEVICE=eth1
ONBOOT=yes
IPADDR=172.16.1.8
PREFIX=24
GATEWAY=172.16.1.6
DNS1=223.5.5.5
EOF
systemctl restart network
# 手动绑定VIP到lo
ip a a 10.0.1.3/32 dev lo

测试

[root@m01 ~]# ip route add 10.0.1.3 via 10.0.0.6
[root@m01 ~]# i=0;while ((i<6)); do curl 10.0.1.3; sleep 0.5;((i++));done;
web01
web02
web01
web02
web01
web02

LVS-TUN模式


DS

# Install keepalived
# CentOS
yum install keepalived ipvsadm

# update iptables
vim /etc/sysconfig/iptables

# For keepalived:
# allow vrrp 
-A INPUT -p vrrp -j ACCEPT
-A INPUT -p igmp -j ACCEPT
# allow multicast
-A INPUT -d 224.0.0.18 -j ACCEPT

# reload iptables
service iptables reload

# open ip_forward
echo "1" > /proc/sys/net/ipv4/ip_forward
# edit sysctl.conf
vi /etc/sysctl.conf
net.ipv4.ip_forward = 1

sysctl -p

# keepalived for lvs-tun
vim /etc/keepalived/keepalived.conf

vrrp_sync_group GOP {
    group {
        VI_PRI_AUTH
    }
}

vrrp_instance VI_PRI_AUTH {
    state BACKUP
    interface em1
    virtual_router_id 11
    priority 100
    advert_int 1
    nopreempt
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.10.36.11/23 dev em1
    }
}

virtual_server 10.10.36.11 80 {
    delay_loop 6
    lb_algo rr
    lb_kind TUN
    protocol TCP

    real_server 10.10.36.4 80 {
        weight 100
        TCP_CHECK {
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
                connect_port 80
        }
    }
    real_server 10.10.36.7 80 {
        weight 100
        TCP_CHECK {
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
                connect_port 80
        }
    }
}

# enable and start keepalived
systemctl start keepalived
systemctl enable keepalived
watch ipvsadm -L -n --stats

# write script, recommand manage it by keepalived.conf
#!/bin/sh
# Startup script handle the initialisation of LVS
# chkconfig: - 28 72
# description: Initialise the Linux Virtual Server for TUN
#
### BEGIN INIT INFO
# Provides: ipvsadm
# Required-Start: $local_fs $network $named
# Required-Stop: $local_fs $remote_fs $network
# Short-Description: Initialise the Linux Virtual Server
# Description: The Linux Virtual Server is a highly scalable and highly
#   available server built on a cluster of real servers, with the load
#   balancer running on Linux.
# description: start LVS of TUN
LOCK=/var/lock/lvs-tun.lock
VIP=10.10.36.11
RIP1=10.10.36.4
RIP2=10.10.36.7
. /etc/rc.d/init.d/functions

start()    {
     PID=`ipvsadm -Ln | grep ${VIP} | wc -l`
     if    [ $PID -gt 0 ];

     then
           echo "The LVS-TUN Server is already running !"
     else
           #Load the tun mod
           /sbin/modprobe tun
           /sbin/modprobe ipip
           #Set the tun Virtual IP Address
           /sbin/ifconfig tunl0 $VIP broadcast $VIP netmask 255.255.255.255 up
           /sbin/route add -host $VIP dev tunl0
           #Clear IPVS Table
           /sbin/ipvsadm -C
           #The icmp recruit setting
           echo "0" >/proc/sys/net/ipv4/ip_forward
           echo "0" >/proc/sys/net/ipv4/conf/all/send_redirects
           echo "0" >/proc/sys/net/ipv4/conf/default/send_redirects
           #Set Lvs
           /sbin/ipvsadm -At $VIP:80 -s rr
           /sbin/ipvsadm -at $VIP:80 -r $RIP1:80 -i  -w 1
           /sbin/ipvsadm -at $VIP:80 -r $RIP2:80 -i  -w 1
           /bin/touch $LOCK
           #Run Lvs
           echo "starting LVS-TUN-DIR Server is ok !"
     fi
}

stop()    {
           #stop  Lvs server
           /sbin/ipvsadm -C
           /sbin/ifconfig tunl0 down >/dev/null
           #Remove the tun mod
           /sbin/modprobe -r tun
           /sbin/modprobe -r ipip
           rm -rf $LOCK
           echo "stopping LVS-TUN-DIR server is ok !"
}

status()  {
     if [ -e $LOCK ];
     then
         echo "The LVS-TUN Server is already running !"
     else
         echo "The LVS-TUN Server is not running !"
     fi
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
        sleep 1
        start
        ;;
  status)
        status
        ;;
  *)
        echo "Usage: $1 {start|stop|restart|status}"
        exit 1
esac
exit 0

RS

# 在加载好ipip模块后就会有默认的tunl0隧道
modprobe ipip

# 添加VIP
# ifconfig tunl0 down
ifconfig tunl0 10.10.36.11 broadcast 10.10.36.11 netmask 255.255.255.255 up

# 添加路由
route add -host 10.10.36.11 tunl0

# 手动关闭ARP转发
echo '1' > /proc/sys/net/ipv4/conf/tunl0/arp_ignore 
echo '2' > /proc/sys/net/ipv4/conf/tunl0/arp_announce
echo '1' > /proc/sys/net/ipv4/conf/all/arp_ignore
echo '2' > /proc/sys/net/ipv4/conf/all/arp_announce 
echo '0' > /proc/sys/net/ipv4/conf/tunl0/rp_filter
echo '0' > /proc/sys/net/ipv4/conf/all/rp_filter 

# iptables允许ipip协议
iptables -I INPUT 1 -p 4 -j ACCEPT
vim /etc/sysconfig/iptables
-A INPUT -p ipv4 -j ACCEPT

# 编写RS启停脚本,推荐用脚本管理RS
vim /etc/init.d/lvs-tun

#!/bin/sh
#
# Startup script handle the initialisation of LVS
# chkconfig: - 28 72
# description: Initialise the Linux Virtual Server for TUN
#
### BEGIN INIT INFO
# Provides: ipvsadm
# Required-Start: $local_fs $network $named
# Required-Stop: $local_fs $remote_fs $network
# Short-Description: Initialise the Linux Virtual Server
# Description: The Linux Virtual Server is a highly scalable and highly
#   available server built on a cluster of real servers, with the load
#   balancer running on Linux.
# description: start LVS of TUN-RIP
LOCK=/var/lock/ipvsadm.lock
VIP=10.10.36.11
. /etc/rc.d/init.d/functions
start() {
     PID=`ifconfig | grep tunl0 | wc -l`
     if [ $PID -ne 0 ];
     then
         echo "The LVS-TUN-RIP Server is already running !"
     else
         #Load the tun mod
         /sbin/modprobe tun
         /sbin/modprobe ipip
         #Set the tun Virtual IP Address
         /sbin/ifconfig tunl0 $VIP netmask 255.255.255.255 broadcast $VIP up
         /sbin/route add -host $VIP dev tunl0
         echo "1" >/proc/sys/net/ipv4/conf/tunl0/arp_ignore
         echo "2" >/proc/sys/net/ipv4/conf/tunl0/arp_announce
         echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
         echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
         echo "0" > /proc/sys/net/ipv4/conf/tunl0/rp_filter
         echo "0" > /proc/sys/net/ipv4/conf/all/rp_filter
         /bin/touch $LOCK
         echo "starting LVS-TUN-RIP server is ok !"
     fi
}

stop() {
         /sbin/ifconfig tunl0 down
         echo "0" >/proc/sys/net/ipv4/conf/tunl0/arp_ignore
         echo "0" >/proc/sys/net/ipv4/conf/tunl0/arp_announce
         echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
         echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
         #Remove the tun mod
         /sbin/modprobe -r tun
         /sbin/modprobe -r ipip
         rm -rf $LOCK
         echo "stopping LVS-TUN-RIP server is ok !"
}

status() {
     if [ -e $LOCK ];
     then
        echo "The LVS-TUN-RIP Server is already running !"
     else
        echo "The LVS-TUN-RIP Server is not running !"
     fi
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
        start
        ;;
  status)
        status
        ;;
  *)
        echo "Usage: $1 {start|stop|restart|status}"
        exit 1
esac
exit 0

# start lvs-tun
chmod 755 /etc/init.d/lvs-tun
service lvs-tun start
chkconfig lvs-tun on

# Nginx test
echo "rs1" > /usr/share/nginx/html/index.html
echo "rs2" > /usr/share/nginx/html/index.html

for i in {1..100}; do curl 10.10.36.11; sleep 0.5; done

这一步的主要目的是让 RS 禁言,在相对较新的版本中新增了两个内核参数 (kernel parameter)

  • 第一个是 arp_ignore 定义接受到 ARP 请求时的相应级别
  • 第二个是 arp_announce 定义将自己地址向外通告是的通告级别
  • 第三个是 rp_filter 定义系统是否开启对数据包源地址的校验

总结: LVS/TUN 是所有模式中最最适用于跨网络跨地域地理位置的一种模式,需要注意的是:

  1. 若 DIR 和 RIP 在不同 lan 网络中,比如不同的网段,不同的 IDC 机房,就不需要设置 arp 仰制,不同网段中,arp 会被屏蔽掉,所以只需设置 ip tunne 以及报文反向验证即可;
  2. 若 DIR 和 RIP 在同一广播域中,需要和 LVS/DR 模式一样在所有的 RIP 上仰制 arp,防止 arp 响应导致 arp 表混乱,这样 lvs 就不能正常工作!

配置时除了配置 DIR,还需要需要配置后端 RS server,即在 tunl 上口配置 vip 地址(需要系统支持 tunl 才行),广播为自己,此模式下无需开启路由转发功能!

posted @ 2021-03-08 19:29  上善若水~小辉  阅读(148)  评论(0编辑  收藏  举报