侧边栏壁纸
博主头像
Blog博主等级

行动起来,活在当下

  • 累计撰写 211 篇文章
  • 累计创建 94 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

传统运维技术篇06

keepalive高可用。

一、试验环境

根据前几篇的文章,我们发现请求通过应用服务器(21、22),在经过mysql代理服务器(31)上,给到mysql服务器(36、37)。如果代理服务器出现故障那么将会影响业务。所以我们将再次部署一台mysql-proxy-32服务器,使用keepalived技术将31和32绑定成一组,31为master、32为backup。master负责实时发送心跳包给backup,一旦backup收不到master的心跳包,那么就会将自己设置为master,从而实现业务平滑过渡。

二、keepalive工作流程

下面是 Keepalived 工作的一个典型流程:

  1. 启动时:Keepalived 启动时,主机会通过 VRRP 广播请求成为 Master 节点。如果网络中有多个节点,节点会通过优先级选择哪个节点成为 Master。

  2. Master 节点工作:Master 节点接管虚拟 IP,并且处理该 IP 地址上的所有流量。

  3. 健康检查:Keepalived 会定期对后端服务器进行健康检查,确保服务的可用性。

  4. 节点故障时:如果 Master 节点失效或健康检查失败,Backup 节点会自动接管虚拟 IP,恢复服务,避免了单点故障的发生。

  5. 恢复时:如果故障的 Master 节点恢复,Keepalived 会根据节点的优先级重新选举 Master。

三、开始试验部署

1.部署过程:

从71上克隆一台服务器:jx-mysql-proxy-32。我们将jx-mysql-proxy-31作为master,jx-mysql-proxy-32作为backup。虚拟业务ip为10.10.10.30。虚拟IP只在master节点上,master节点通过vrrp协议不断地发心跳包给backup。只要backup收不到心跳包就会将自己设置为master,虚拟IP就会切换到backup上。

master(jx-mysql-proxy-31)上配置

安装keepalive软件

# yum install -y keepalived -y

配置/etc/keepalived/keepalived.conf

[root@jx-mysql-proxy-31 ~]# cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived

global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
   #vrrp_strict                                  # 注意这里要注释掉vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state MASTER
    interface enp0s3
    virtual_router_id 31
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.10.10.30
    }
}

backup(jx-mysql-proxy-32)配置

vim /etc/keepalived/keepalived.conf

! Configuration File for keepalived

global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
   #vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state BACKUP
    interface enp0s3
    virtual_router_id 31              # 注意这里要和master保持一致,使用相同虚拟id表示同一组。
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
      10.10.10.30
    }
}

先开启master上keepalived,再开启backup上keepalived。

[root@jx-mysql-proxy-31 ~]# systemctl start keepalived

观察IP变化

[root@jx-mysql-proxy-31 ~]# 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: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:43:e4:ba brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.31/24 brd 10.10.10.255 scope global noprefixroute enp0s3
       valid_lft forever preferred_lft forever
    inet 10.10.10.30/32 scope global enp0s3
       valid_lft forever preferred_lft forever
    inet6 fe80::1f0f:78fe:ec44:b570/64 scope link noprefixroute 
       valid_lft forever preferred_lft foreve

backup 上keepalived 启动

[root@jx-mysql-proxy-32 ~]# systemctl start keepalived

观察IP变化,发现backup上也出现了虚拟IP 10.10.10.30。

[root@jx-mysql-proxy-32 ~]# 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: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:5c:cc:3c brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.32/24 brd 10.10.10.255 scope global noprefixroute enp0s3
       valid_lft forever preferred_lft forever
    inet 10.10.10.30/32 scope global enp0s3
       valid_lft forever preferred_lft forever
    inet6 fe80::a261:9cae:15f1:2b70/64 scope link dadfailed tentative noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::6df0:a506:dd46:df23/64 scope link dadfailed tentative noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::f88:76c7:39ca:37a6/64 scope link noprefixroute 
       valid_lft forever preferred_lft foreve

现在这样出现了脑裂

什么是脑裂?如何形成的呢?

具体来说,就是当多个节点同时认为自己是主节点,开始独立地处理流量或请求,而没有协调一致地共享资源或状态,最终造成冲突或数据不一致的现象。

脑裂的成因

Keepalived 中,脑裂通常发生在使用 VRRP(Virtual Router Redundancy Protocol) 协议的场景中。当主节点(Master)与备份节点(Backup)之间的通信发生故障或丢失时,两个节点可能会同时认为自己是主节点,导致虚拟 IP 地址(VIP)被多个节点抢占,并且它们都认为自己是活跃的节点。

例如:

  • 正常情况:一个节点(通常是 Master)拥有虚拟 IP,并处理来自客户端的请求。备份节点只有在主节点宕机时才会接管虚拟 IP。

  • 脑裂发生:如果由于网络分割(如网络延迟、分区或其他故障),Master 节点和 Backup 节点无法通过 VRRP 协议进行正常通信,两者可能会错误地认为自己是主节点,导致虚拟 IP 同时被多个节点占用。

我们查看backup上日志

vim /var/log/messages
Dec 12 11:38:17 jx-mysql-proxy-32 Keepalived_vrrp[4255]: (VI_1) Receive advertisement timeout
Dec 12 11:38:17 jx-mysql-proxy-32 Keepalived_vrrp[4255]: (VI_1) Entering MASTER STATE
Dec 12 11:38:17 jx-mysql-proxy-32 Keepalived_vrrp[4255]: (VI_1) setting VIPs.

backup(32)上的日志。她会接收master上发送的心跳包,收不到就会将自己设为master抢占虚拟IP。

为什么会收不到心跳包呢?我们进一步分析,keepalived 是通过vrrp协议传播心跳包的,而所有包的流出和流入都需要系统自带的防火墙。我们分别查看master和backup的防火墙状态,发现防火墙没关闭。关闭防火墙后我们再次测试,发现正常了,这次只有master上出现了虚拟IP,backup上没有了。

四、四层负载均衡ipvsadm

根据之前的拓扑,数据库36和37做了主从、数据库代理(32、32)做了读写分离、应用服务器21、22业务相同。现在只有jx-nginx-11没有备机,一旦出现故障,整个业务将不能访问。接下来我们将从71上链接复制一台机器jx-nginx-12,复制一份jx-nginx-11的业务给12。

访问过程:

笔记本访问http://jxdl.jxit.net.cn/-》笔记本hosts(127.0.0.1) ->网关服务器(254)nat网卡(10.0.3.15 80)-》应用服务器(21或22的80端口。轮询策略)。

部署过程

在网关服务器(254)上使用ipvsadm创建访问规则,只转发请求而不解析内容。

yum install ipvsadm -y 

安装好后,先将之前使用iptables创建的规则清除掉,只保留nat上网这一条:

[root@jx-gateway-254 opt]# iptables-save 
# Generated by iptables-save v1.8.5 on Thu Dec 12 16:32:19 2024
*nat
:PREROUTING ACCEPT [5:380]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [4:248]
:POSTROUTING ACCEPT [4:248]
-A POSTROUTING -s 10.10.10.0/24 -j SNAT --to-source 10.0.3.15
COMMIT
# Completed on Thu Dec 12 16:32:19 2024

开始配置转发规则:

[root@jx-gateway-254 ~]# ip r 
default via 10.0.3.2 dev enp0s8 proto dhcp metric 101 
10.0.3.0/24 dev enp0s8 proto kernel scope link src 10.0.3.15 metric 101 
10.10.10.0/24 dev enp0s3 proto kernel scope link src 10.10.10.254 metric 100 
[root@jx-gateway-254 ~]# ipvsadm -A -t 10.0.3.15:80 -s rr 
[root@jx-gateway-254 ~]# ipvsadm -nL 
Try `ipvsadm -h' or 'ipvsadm --help' for more information.
[root@jx-gateway-254 ~]# 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.3.15:80 rr
[root@jx-gateway-254 ~]# ipvsadm -a -t 10.0.3.15:80 -r 10.10.10.11:80 -m -w 1 
[root@jx-gateway-254 ~]# ipvsadm -a -t 10.0.3.15:80 -r 10.10.10.12:80 -m -w 1 
[root@jx-gateway-254 ~]# 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.3.15:80 rr
  -> 10.10.10.11:80               Masq    1      0          0         
  -> 10.10.10.12:80               Masq    1      0          0         

从nat网卡进来的流量都转给代理服务器11 和 12 的80 。

访问测试:

浏览器访问:http://jxdl.jxit.net.cn

同时在254上抓包,看ipvsadm轮询策略有没有生效。

[root@jx-gateway-254 ~]# tcpdump -i enp0s3 -p port 80  -nn

发现结果都是12的包,没有11。难道是我们配置错了吗?

其实是浏览器建立TCP三次握手后,即使不传数据了也会等待一段时间断开而不会立马断开。这样每次请求的都使用相同的通道,所以都访问同一台应用服务器。

我们使用curl 来请求,它每次请求完成后会立马断开,下次请求不会转发到同一台。便于我们测试ipvsadm轮询策略。请求的同时在254上抓内网80端口的包,发现第一次给到了12,第二次给到了11。说明我们的轮询策略生效了。

[root@jx-gateway-254 ~]# tcpdump -i enp0s3 -p port 80  -nn 
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes
18:53:01.450869 IP 10.0.3.2.8107 > 10.10.10.12.80: Flags [S], seq 2219392001, win 65535, options [mss 1460], length 0
18:53:01.451662 IP 10.10.10.12.80 > 10.0.3.2.8107: Flags [S.], seq 3939576744, ack 2219392002, win 64240, options [mss 1460], length 0
18:53:01.451918 IP 10.0.3.2.8107 > 10.10.10.12.80: Flags [.], ack 1, win 65535, length 0
18:53:01.452294 IP 10.0.3.2.8107 > 10.10.10.12.80: Flags [P.], seq 1:80, ack 1, win 65535, length 79: HTTP: GET / HTTP/1.1
18:53:01.453058 IP 10.10.10.12.80 > 10.0.3.2.8107: Flags [.], ack 80, win 64161, length 0
18:53:01.453870 IP 10.10.10.12.80 > 10.0.3.2.8107: Flags [P.], seq 1:419, ack 80, win 64161, length 418: HTTP: HTTP/1.1 200 OK
18:53:01.454253 IP 10.0.3.2.8107 > 10.10.10.12.80: Flags [.], ack 419, win 65535, length 0
18:53:01.454411 IP 10.0.3.2.8107 > 10.10.10.12.80: Flags [F.], seq 80, ack 419, win 65535, length 0
18:53:01.455461 IP 10.10.10.12.80 > 10.0.3.2.8107: Flags [F.], seq 419, ack 81, win 64160, length 0
18:53:01.455685 IP 10.0.3.2.8107 > 10.10.10.12.80: Flags [.], ack 420, win 65535, length 0
18:53:02.254832 IP 10.0.3.2.8110 > 10.10.10.11.80: Flags [S], seq 2219520001, win 65535, options [mss 1460], length 0
18:53:02.255459 IP 10.10.10.11.80 > 10.0.3.2.8110: Flags [S.], seq 1618512162, ack 2219520002, win 64240, options [mss 1460], length 0
18:53:02.255718 IP 10.0.3.2.8110 > 10.10.10.11.80: Flags [.], ack 1, win 65535, length 0
18:53:02.255789 IP 10.0.3.2.8110 > 10.10.10.11.80: Flags [P.], seq 1:80, ack 1, win 65535, length 79: HTTP: GET / HTTP/1.1
18:53:02.256307 IP 10.10.10.11.80 > 10.0.3.2.8110: Flags [.], ack 80, win 64161, length 0
18:53:02.256578 IP 10.10.10.11.80 > 10.0.3.2.8110: Flags [P.], seq 1:434, ack 80, win 64161, length 433: HTTP: HTTP/1.1 200 OK
18:53:02.257354 IP 10.0.3.2.8110 > 10.10.10.11.80: Flags [.], ack 434, win 65535, length 0
18:53:02.257421 IP 10.0.3.2.8110 > 10.10.10.11.80: Flags [F.], seq 80, ack 434, win 65535, length 0
18:53:02.258338 IP 10.10.10.11.80 > 10.0.3.2.8110: Flags [F.], seq 434, ack 81, win 64160, length 0
18:53:02.258607 IP 10.0.3.2.8110 > 10.10.10.11.80: Flags [.], ack 435, win 65535, length 0

0

评论区