双剑合璧(Keepalived+LVS)

详细介绍了工作中经常用到的组合技IPVS=Keepalive+LVS

3.4双主架构

说明:
每一个vrrp只有一个主,但是可以在两台服务器上配置多个vrrp,每一台服务器是某一个虚拟ip的主设备

master/slave的单主架构,同一时间只有一个Keepalived对外提供服务,此主机繁忙,而另一台主机却很空闲,利用率低下,可以使用master/master的双主架构,解决此问题。

master/master 的双主架构:
即将两个或以上VIP分别运行在不同的keepalived服务器,以实现服务器并行提供web访问的目的,提高服务器资源利用率

##ka1主机配置
#针对于vrid55的vrrp配置
[root@ka1 /etc/keepalived/conf.d]#cat master.conf 
vrrp_instance test1 {               #添加 test1 实例
    state MASTER                    #在另一个主机上为BACKUP
    interface ens33                 #网卡
    virtual_router_id 55            #每个vrrp_instance唯一
    priority 100                    #在另一个主机上为80(只要比100小就行)
    advert_int 1
    preempt_delay 5
    authentication {
        auth_type PASS
        auth_pass sunxiang
    }
    virtual_ipaddress {
        10.0.0.15 dev ens33 laber ens33:0       #指定vrrp_instance各自的VIP
    }
}   

#针对于vrid66的vrrp配置
[root@ka1 /etc/keepalived/conf.d]#cat backup.conf 
vrrp_instance test2 {
    state BACKUP
    interface ens33
    virtual_router_id 66            #每个vrrp_instance唯一
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass sunxiang
    }
    virtual_ipaddress {
        10.0.0.25 dev ens33 laber ens33:1       #指定vrrp_instance各自的VIP
    }
}


##ka2主机配置
#针对于vrid55的vrrp配置
[root@ka2 /etc/keepalived/conf.d]#cat backup.conf 
vrrp_instance test1 {
    state BACKUP
    interface ens33
    virtual_router_id 55
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass sunxiang
    }
    virtual_ipaddress {
        10.0.0.15 dev ens33 laber ens33:0
    }
} 

#针对于vrid66的vrrp配置
[root@ka2 /etc/keepalived/conf.d]#cat master.conf 
vrrp_instance test2 {
    state MASTER
    interface ens33
    virtual_router_id 66
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass sunxiang
    }
    virtual_ipaddress {
        10.0.0.25 dev ens33 laber ens33:1
    }
}


#重启服务
[root@ka1 /etc/keepalived/conf.d]#systemctl restart keepalived.service
[root@ka2 /etc/keepalived/conf.d]#systemctl restart keepalived.service
#查看虚拟ip信息
[root@ka1 /etc/keepalived/conf.d]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:95:b7:a2 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.11/24 brd 10.0.0.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 10.0.0.15/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe95:b7a2/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever


[root@ka2 /etc/keepalived/conf.d]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:ff:33:b2 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.21/24 brd 10.0.0.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 10.0.0.25/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feff:33b2/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

#抓包 vrid66主设备为10.0.0.21,vrid55主设备为10.0.0.11。都会向对方发送组播报文
[root@centos7blog ~]# tcpdump -i ens33 -nn host 224.0.0.18
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
18:29:27.488548 IP 10.0.0.21 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
18:29:27.566569 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
18:29:28.489312 IP 10.0.0.21 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
18:29:28.570515 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
18:29:29.491238 IP 10.0.0.21 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
18:29:29.573328 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
18:29:30.493232 IP 10.0.0.21 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
18:29:30.574217 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20

#模拟故障,在ka2上停服务
#抓包 在停服务之前都是互为主备,当服务停止之后vrid55和66的主设备都是10.0.0.11,都是10.0.0.11发送组播
[root@centos7blog ~]# tcpdump -i ens33 -nn host 224.0.0.18
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
18:37:28.562324 IP 10.0.0.21 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
18:37:28.676421 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
18:37:29.563015 IP 10.0.0.21 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
18:37:29.679107 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
18:37:30.080837 IP 10.0.0.21 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 0, authtype simple, intvl 1s, length 20
18:37:30.681044 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
18:37:30.772663 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 80, authtype simple, intvl 1s, length 20
18:37:31.683951 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
18:37:31.776033 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 80, authtype simple, intvl 1s, length 20

3.5脑裂(需要避免)

生成中出现一个虚拟地址在多台设备上都有的情况,比如说心跳线故障,就会导致脑裂。

#正常情况下访问10.0.0.25应该是ka2进行回应
[root@centos7blog ~]# arping 10.0.0.25
ARPING 10.0.0.25 from 10.0.0.40 ens33
Unicast reply from 10.0.0.25 [00:0C:29:FF:33:B2]  0.849ms
Unicast reply from 10.0.0.25 [00:0C:29:FF:33:B2]  1.029ms
Unicast reply from 10.0.0.25 [00:0C:29:FF:33:B2]  1.000ms
Unicast reply from 10.0.0.25 [00:0C:29:FF:33:B2]  1.464ms
^CSent 4 probes (1 broadcast(s))
Received 4 response(s)

[root@ka2 ~]#ip a
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:ff:33:b2            #确实是ka2的mac地址


#我这里没有心跳线就直接用防火墙禁止ka2上发过来的消息
[root@ka1 ~]#iptables -AINPUT -s 10.0.0.21 -j DROP

#通过arping进行ping发现有ka1的应答也有ka2的应答,这就是脑裂
root@ubuntu1804:~# arping 10.0.0.25
ARPING 10.0.0.25
60 bytes from 00:0c:29:95:b7:a2 (10.0.0.25): index=0 time=4.500 usec
60 bytes from 00:0c:29:ff:33:b2 (10.0.0.25): index=1 time=32.781 usec
60 bytes from 00:0c:29:ff:33:b2 (10.0.0.25): index=2 time=134.991 usec
60 bytes from 00:0c:29:95:b7:a2 (10.0.0.25): index=3 time=172.941 usec
60 bytes from 00:0c:29:95:b7:a2 (10.0.0.25): index=4 time=273.242 usec
60 bytes from 00:0c:29:ff:33:b2 (10.0.0.25): index=5 time=334.562 usec
60 bytes from 00:0c:29:ff:33:b2 (10.0.0.25): index=6 time=237.685 usec
60 bytes from 00:0c:29:95:b7:a2 (10.0.0.25): index=7 time=287.485 usec


#看一下ka1和ka2的ip信息。发现两台设备上都有10.0.0.25这个地址
[root@ka1 ~]#hostname -I
10.0.0.11 10.0.0.15 10.0.0.25       

[root@ka2 ~]#hostname -I
10.0.0.21 10.0.0.25

这个我上一份工作中还真就出现过,一个同事配置iptables的时候直接没注意结果学校的同学反映某个网站卡顿,当时以为是宿舍网的问题都没重视,过了三四天反映的人多起来了,排查一下才发现的。后来我是准备通过arping进行一个监控,发现频繁的抖动就直接停一台设备的服务,给学校的领导反映了一下,但是学校有钱准备直接买设备监控,我就没弄了。正好那会也要离职了没机会玩一下可惜了

3.6实现IPVS的高可用性(LVS+Keepalive)

3.6.1 IPVS相关配置

3.6.1.1 虚拟服务器配置结构

virtual_server IP port {
    ...
    real_server {
        ...
    }
    real_server {
        ...
    }
    …
}

3.6.1.2 virtual server (虚拟服务器)的定义格式

virtual_server IP port          #定义虚拟主机IP地址及其端口
virtual_server fwmark int       #ipvs的防火墙打标,实现基于防火墙的负载均衡集群
virtual_server group string     #使用虚拟服务器组

3.6.1.3 虚拟服务器组

将多个虚拟服务器定义成一个组,统一对外服务,如:http和https定义成一个虚拟服务器组

#参考文档:/usr/share/doc/keepalived/keepalived.conf.virtual_server_group

virtual_server_group <STRING> {
     # Virtual IP Address and Port
     <IPADDR> <PORT>
     <IPADDR> <PORT>
     ...
     # <IPADDR RANGE> has the form
     # XXX.YYY.ZZZ.WWW-VVV eg 192.168.200.1-10
     # range includes both .1 and .10 address
     <IPADDR RANGE> <PORT># VIP range VPORT
     <IPADDR RANGE> <PORT>
     ...
     # Firewall Mark (fwmark)
     fwmark <INTEGER>
     fwmark <INTEGER>
     ...
}

3.6.1.4 虚拟服务器配置

virtual_server IP port {                    #VIP和PORT
    delay_loop <INT>                        #检查后端服务器的时间间隔
    lb_algo rr|wrr|lc|wlc|lblc|sh|dh        #定义调度方法
    lb_kind NAT|DR|TUN                      #集群的类型,注意要大写
    persistence_timeout <INT>               #持久连接时长
    protocol TCP|UDP|SCTP                   #指定服务协议,一般为TCP
    sorry_server <IPADDR> <PORT>            #所有RS故障时,备用服务器地址
    real_server <IPADDR> <PORT> {           #RS的IP和PORT
        weight <INT>                        #RS权重
        notify_up <STRING>|<QUOTED-STRING>  #RS上线通知脚本
        notify_down <STRING>|<QUOTED-STRING> #RS下线通知脚本
        HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK { ... } #定义当前主机健康状态检测方法
    }
}
#注意:括号必须分行写,两个括号写在一行,如: }} 会出错

3.6.1.5 应用层监测

应用层检测:HTTP_GET|SSL_GET

HTTP_GET|SSL_GET {
    url {
        path <URL_PATH>             #定义要监控的URL
        status_code <INT>           #判断上述检测机制为健康状态的响应码,一般为 200
    }
    connect_timeout <INTEGER>       #客户端请求的超时时长, 相当于haproxy的timeout server
    nb_get_retry <INT>              #重试次数
    delay_before_retry <INT>        #重试之前的延迟时长
    connect_ip <IP ADDRESS>         #向当前RS哪个IP地址发起健康状态检测请求
    connect_port <PORT>             #向当前RS的哪个PORT发起健康状态检测请求
    bindto <IP ADDRESS>             #向当前RS发出健康状态检测请求时使用的源地址
    bind_port <PORT>                #向当前RS发出健康状态检测请求时使用的源端口
}

3.6.1.6 TCP监测

传输层检测:TCP_CHECK

TCP_CHECK {
  connect_ip <IP ADDRESS>           #向当前RS的哪个IP地址发起健康状态检测请求
  connect_port <PORT>               #向当前RS的哪个PORT发起健康状态检测请求
  bindto <IP ADDRESS>               #发出健康状态检测请求时使用的源地址
  bind_port <PORT>                  #发出健康状态检测请求时使用的源端口
  connect_timeout <INTEGER>         #客户端请求的超时时长, 等于haproxy的timeout server 
}

3.6.2实战案例

3.6.2.1 实战案例1:实现单主的 LVS-DR 模式

3.6.2.1.1配置后端RS主机(两台操作一样)
#安装nginx
[root@web1 ~]# yum install -y nginx
[root@web1 ~]# systemctl enable --now nginx.service 

#用脚本绑定VIP至web服务器lo网卡
[root@web1 ~]# bash lvs_dr_rs.sh start
The RS Server is Ready!
[root@web1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet 10.0.0.15/32 scope global lo:1
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever

#脚本内容
[root@web1 ~]# cat lvs_dr_rs.sh 
#!/bin/bash
#Author:sunxiang
#Date:2021-10-22
vip=10.0.0.15
mask='255.255.255.255'
dev=lo:1

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 $dev $vip netmask $mask #broadcast $vip up
    echo "The RS Server is Ready!"
    ;;

stop)
    ifconfig $dev down
    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
    echo "The RS Server is Canceled!"
    ;;
*)
    echo "Usage: $(basename $0) start|stop"
    exit 1
    ;;
esac


#修改一下nginx默认页面便于区分
[root@web1 ~]# echo `hostname -I` > /usr/share/nginx/html/index.html
3.6.2.1.2访问测试
root@ubuntu1804:~# curl 10.0.0.20
10.0.0.20
root@ubuntu1804:~# curl 10.0.0.30
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
curl: (7) Failed to connect to 10.0.0.15 port 80: Connection refused

3.6.2.1.3配置keepalive
##ka1
#全局配置
[root@ka1 /etc/keepalived/conf.d]#cat ../keepalived.conf
! Configuration File for keepalived
global_defs {
   notification_email {
     448803503@qq.com
   }
   notification_email_from 448803503@qq.com
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id ka1                                    #设备标识
   vrrp_skip_check_adv_addr
   #vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}
include /etc/keepalived/conf.d/*.conf

#vrrp配置
[root@ka1 /etc/keepalived/conf.d]#cat master.conf 
vrrp_instance test1 {
    state MASTER
    interface ens33                             #网卡
    virtual_router_id 55                        #vid全局唯一
    priority 100                                #主设备优先级比备设备高即可
    advert_int 1
    preempt_delay 5
    authentication {
        auth_type PASS
        auth_pass sunxiang
    }
    virtual_ipaddress {
        10.0.0.15 dev ens33 laber ens33:0       #vip
    }
}        


#virtual_server配置
[root@ka1 /etc/keepalived/conf.d]#cat lvs.conf 
virtual_server 10.0.0.15 80 {
    delay_loop 3
    lb_algo rr                                  #调度方式
    lb_kind DR                                  #集群的类型,注意要大写
    protocol TCP
    sorry_server 127.0.0.1 80                   #后端服务器出现故障时候备用的服务器
    real_server 10.0.0.20 80 {                  #后端服务器
        weight 1
        HTTP_GET {
            url {                       #通过url进行监控检查(如果不能返回状态吗200则认为故障)
                path /
                status_code 200
            }
            connect_timeout 1
            nb_get_retry 3
            delay_before_retry 1
        }   
    }

    real_server 10.0.0.30 80 {
        weight 1
        TCP_CHECK {                     #通过tcp协议监控如果不能连接端口80则认为故障
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connetc_port 80
        }
    }
}


##ka2与ka1大同小异
#全局配置
[root@ka2 /etc/keepalived/conf.d]#cat ../keepalived.conf
! Configuration File for keepalived
global_defs {
   notification_email {
     448803503@qq.com
   }
   notification_email_from 448803503@qq.com
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id ka2                                #设备标识
   vrrp_skip_check_adv_addr
   #vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}
include /etc/keepalived/conf.d/*.conf

#vrrp配置
[root@ka2 /etc/keepalived/conf.d]#cat backup.conf 
vrrp_instance test1 {
    state BACKUP                                #改成BACKUP
    interface ens33
    virtual_router_id 55
    priority 80                                 #修改为小于主设备的优先级
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass sunxiang
    }
    virtual_ipaddress {
        10.0.0.15 dev ens33 laber ens33:0
    }
} 


#virtual_server配置
[root@ka2 /etc/keepalived/conf.d]#cat lvs.conf 
virtual_server 10.0.0.15 80 {
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 10.0.0.20 80 {
        weight 1
        HTTP_GET {
            url {
                path /
                status_code 200
            }
            connect_timeout 1
            nb_get_retry 3
            delay_before_retry 1
        }   
    }

    real_server 10.0.0.30 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connetc_port 80
        }
    }
}


#重启服务
[root@ka1 /etc/keepalived/conf.d]#systemctl restart keepalived.service
[root@ka2 /etc/keepalived/conf.d]#systemctl restart keepalived.service
3.6.2.1.4访问测试
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20


[root@ka1 ~]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.0.15:80 rr
  -> 10.0.0.20:80                 Route   1      0          3         
  -> 10.0.0.30:80                 Route   1      0          3         

3.6.2.1.5模拟故障
针对url检查,我们使其检查的页面是一个不存在的网页
[root@ka1 /etc/keepalived/conf.d]#vim lvs.conf 
virtual_server 10.0.0.15 80 {
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 10.0.0.20 80 {
        weight 1
        HTTP_GET {
            url {
                path /bucunzai          #一个不存在的url
                status_code 200
            }
            connect_timeout 1
            nb_get_retry 3
            delay_before_retry 1
        }
    }

    real_server 10.0.0.30 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connetc_port 80
        }
    }
}

#重启服务
[root@ka1 /etc/keepalived/conf.d]#systemctl restart keepalived.service 


#查看一下lvs的信息,只有一个后端服务器了
[root@ka1 /etc/keepalived/conf.d]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.0.15:80 rr
  -> 10.0.0.30:80                 Route   1      0          7     

#访问测试,只有一台服务器响应
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30


#当故障恢复后(改为存在的url),后端rs服务器又恢复正常
[root@ka1 /etc/keepalived/conf.d]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.0.15:80 rr
  -> 10.0.0.20:80                 Route   1      0          0         
  -> 10.0.0.30:80                 Route   1      0          0   

3.6.2.2 实战案例2:实现双主的 LVS-DR 模式

vip 10.0.0.15       Nginx       10.0.0.11为主   10.0.0.21为备
vip 10.0.0.25       Mysql       10.0.0.11为备   10.0.0.21为主
3.6.2.2.1配置后端RS服务器(两台服务器一样)
##正常生产中都是不同的服务器运行不同的服务,我这里就直接一个服务器上跑多个服务了
#先停脚本
[root@web1 ~]# bash lvs_dr_rs.sh stop
The RS Server is Canceled!

#修改一下脚本
[root@web1 ~]# cat lvs_dr_rs.sh 
#!/bin/bash
#Author:sunxiang
#Date:2021-10-22
vip=10.0.0.15
vip2=10.0.0.25
mask='255.255.255.255'
dev=lo:1
dev2=lo:2

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 $dev $vip netmask $mask #broadcast $vip up
    ifconfig $dev2 $vip2 netmask $mask #broadcast $vip2 up
    echo "The RS Server is Ready!"
    ;;

stop)
    ifconfig $dev down
    ifconfig $dev2 down
    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
    echo "The RS Server is Canceled!"
    ;;
*)
    echo "Usage: $(basename $0) start|stop"
    exit 1
    ;;
esac

#运行脚本
[root@web1 ~]# bash lvs_dr_rs.sh start
The RS Server is Ready!

#查看ip信息
[root@web1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet 10.0.0.15/32 scope global lo:1
       valid_lft forever preferred_lft forever
    inet 10.0.0.25/32 scope global lo:2
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever

#安装服务
#Nginx之前已经安装了,再装一个MySQL,直接跑脚本了,mysql章节有写这个脚本自己去看吧
[root@web1 mysql]# . mysql_5.7_8.0_Online.sh 

#配置mysql
#获取初始化密码
[root@web1 ~]# grep password /data/mysql/mysql.log
2021-12-29T08:11:05.705363Z 1 [Note] A temporary password is generated for root@localhost: nwes(3dJeV.Q

#修改初始化密码
[root@web1 ~]# mysql -uroot -p'nwes(3dJeV.Q'
mysql> alter user root@'localhost' identified by 'sunxiang';
Query OK, 0 rows affected (0.00 sec)

#创建用于测试的账号
mysql> create user test@'10.0.0.%' identified by 'sunxiang';
Query OK, 0 rows affected (0.00 sec)

#为测试账号授权
mysql> grant all on *.* to test@'10.0.0.%';
Query OK, 0 rows affected (0.00 sec)

3.6.2.2.2配置keepalive

在实例一的基础上增加一个vrrp配置和virtual_server配置

##ka1
#vrrp配置
[root@ka1 /etc/keepalived/conf.d]#cat backup.conf 
vrrp_instance test2 {
    state BACKUP
    interface ens33
    virtual_router_id 66
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass sunxiang
    }
    virtual_ipaddress {
        10.0.0.25 dev ens33 laber ens33:1
    }
}

#virtual_server配置      与Nginx的区别在于端口号和健康检查方式,mysql只能通过tcp来进行监控了
[root@ka1 /etc/keepalived/conf.d]#cat mysql.conf 
virtual_server 10.0.0.25 3306 {
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 10.0.0.20 3306 {
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connetc_port 3306
        }   
    }

    real_server 10.0.0.30 3306 {
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connetc_port 3306
        }
    }
}



##ka2
#vrrp配置
[root@ka2 /etc/keepalived/conf.d]#cat master.conf 
vrrp_instance test2 {
    state MASTER
    interface ens33
    virtual_router_id 66
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass sunxiang
    }
    virtual_ipaddress {
        10.0.0.25 dev ens33 laber ens33:1
    }
}


#virtual_server配置
[root@ka2 /etc/keepalived/conf.d]#cat mysql.conf 
virtual_server 10.0.0.25 3306 {
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 10.0.0.20 3306 {
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connetc_port 3306
        }   
    }

    real_server 10.0.0.30 3306 {
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connetc_port 3306
        }
    }
}


#重启服务
[root@ka1 /etc/keepalived/conf.d]#systemctl restart keepalived.service 
[root@ka2 /etc/keepalived/conf.d]#systemctl restart keepalived.service 
3.6.2.2.3访问测试
#查看一下vip的绑定情况,一台服务器上有一个keepalive没啥问题
[root@ka1 /etc/keepalived/conf.d]#ip addr show ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:95:b7:a2 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.11/24 brd 10.0.0.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 10.0.0.15/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe95:b7a2/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

[root@ka2 /etc/keepalived/conf.d]#ip addr show ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:ff:33:b2 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.21/24 brd 10.0.0.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 10.0.0.25/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feff:33b2/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

#访问mysql  正常进行轮询
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web1       |
+------------+
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web2       |
+------------+
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web1       |
+------------+

#访问nginx       正常进行轮询
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20

3.6.2.2.4模拟故障
#模拟后端RS服务器故障
#web2直接关机
[root@web2 mysql]# poweroff 

root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web1       |
+------------+
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web1       |
+------------+
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web1       |
+------------+


#故障恢复
#重启服务器,运行lvs脚本
[root@web2 ~]# bash lvs_dr_rs.sh start
The RS Server is Ready!

#恢复正常
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web2       |
+------------+
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web1       |
+------------+

##模拟keepalive服务器故障
#在ka2上停服务
[root@ka2 /etc/keepalived/conf.d]#systemctl stop keepalived.service 

#连接测试依旧是正常的轮询
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web1       |
+------------+
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web2       |
+------------+
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.25 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web1       |
+------------+
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20


#抓包  都是从10.0.0.11发的组播报文
[root@centos7blog ~]# tcpdump -i ens33 -nn host 224.0.0.18
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
02:36:27.381322 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
02:36:27.449187 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 80, authtype simple, intvl 1s, length 20
02:36:28.382133 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
02:36:28.450149 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 80, authtype simple, intvl 1s, length 20
02:36:29.384165 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
02:36:29.451119 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 80, authtype simple, intvl 1s, length 20
02:36:30.385787 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
02:36:30.453772 IP 10.0.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 66, prio 80, authtype simple, intvl 1s, length 20
^C
8 packets captured
8 packets received by filter
0 packets dropped by kernel

3.6.2.3 实战案例3:实现单主的 LVS-DR 模式,利用FWM绑定成多个服务为一个集群服务

参考文档: 注意有bug

/usr/share/doc/keepalived/keepalived.conf.fwmark
3.6.2.3.1打标签
[root@ka1 ~]#iptables -t mangle -A PREROUTING -d 10.0.0.15 -p tcp -m multiport --dports 80,3306 -j MARK --set-mark 6
[root@ka2 ~]#iptables -t mangle -A PREROUTING -d 10.0.0.15 -p tcp -m multiport --dports 80,3306 -j MARK --set-mark 6
3.6.2.3.2配置keepalive
#修改virtual_server的配置,将上面两个实验创建virtual_server的conf文件修改后缀为bak
#创建一个新的调用组的virtual_server的conf文件
[root@ka1 /etc/keepalived/conf.d]#cat fwm.conf 
virtual_server fwmark 6 {               #指定FWM为6
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 10.0.0.20 80 {          #注意端口必须指定(官方文档上没有指定端口,会报错,随意指定组成员的任意一个端口即可)
        weight 1
        HTTP_GET {
            url {
                path /
                status_code 200
            }
            connect_timeout 1
            nb_get_retry 3
            delay_before_retry 1
        }
    }

    real_server 10.0.0.30 80 {          #注意端口必须指定
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connetc_port 80
        }
    }
}

[root@ka2 /etc/keepalived/conf.d]#cat fwm.conf 
virtual_server fwmark 6 {               #指定FWM为6
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 10.0.0.20 80 {          #注意端口必须指定(官方文档上没有指定端口,会报错,随意指定组成员的任意一个端口即可)
        weight 1
        HTTP_GET {
            url {
                path /
                status_code 200
            }
            connect_timeout 1
            nb_get_retry 3
            delay_before_retry 1
        }
    }

    real_server 10.0.0.30 80 {          #注意端口必须指定
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connetc_port 80
        }
    }
}


#重启服务
[root@ka1 /etc/keepalived/conf.d]#systemctl restart keepalived.service
[root@ka2 /etc/keepalived/conf.d]#systemctl restart keepalived.service
3.6.2.3.3访问测试
#都是进行正常的轮询,与之前不同的地方在于此时一个虚拟ip对应多个服务
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.30
root@ubuntu1804:~# curl 10.0.0.15
10.0.0.20
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.15 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web2       |
+------------+
root@ubuntu1804:~# mysql -utest -psunxiang -h10.0.0.15 -e 'select @@hostname'
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| web1       |
+------------+