keepalived+lvs 架构
keepalived+lvs 是比较常用的一种架构,它能够很容易地实现高可用和负载均衡,在互联网公司使用较为广泛,适用于 web ,ftp,缓存,数据库等多种场景。
一、keepalived
keepalived 官方网站:https://www.keepalived.org/
Keepalived 是一个用 C 语言编写的开源免费的路由软件,主要目的是为 Linux 平台上的系统提供简单、稳定、可靠的负载均衡和高可用功能,防止单点故障。其中负载均衡依赖于 Linux 虚拟服务器 Linux Virtual Server(IPVS)内核模块提供的 4 层负载均衡。Keepalived 实现了一组检查程序,根据服务器的运行状况动态地、自适应地维护和管理负载均衡服务器池。Keepalived 的高可用通过 VRRP 协议实现,VRRP 协议是故障转移的基础。
1.1 VRRP 协议
VRRP,虚拟路由冗余协议(Virtual Router Redundancy Protocol),简单点说,就是实现地址漂移,是一种容错协议。Keepalived 在部署时通常一个 Master,多个 Backup,Master 节点周期性地发送 VRRP 报文,在虚拟路由器中公布其配置信息(优先级等)和工作状况。Backup 节点通过接收到 VRRP 报文的情况来判断 Master 路由器是否工作正常,在不正常的情况下接管 Master 的工作。
VRRP 根据优先级来确定每个节点的角色(Master 或 Backup)。优先级越高,则越有可能成为Master,VRRP 优先级的可配置的取值范围为 1 到 254。
1.2 组播与单播
keepalived 早期版本只支持组播,从 1.2.8 版本开始支持单播,keepalived 组播模式下所有的信息都会向 224.0.0.18 的组播地址发送,产生众多的无用信息,可能导致干扰和冲突,尤其在一个网段内部署多组 keepalived 时更为严重,可以通过对 keepalived vrrp 协议抓包,查看网络情况:
tcpdump -iany vrrp
另外在某些云环境中,网络不支持组播,此时 keepalived Backup 节点收不到 Master 的 VRRP 通告,就会出现脑裂(split brain)现象,此时集群中会存在多个 Master 节点。这种情况就需要将组播改为单播,单播是一种更安全的方法,能够避免局域网内大量 keepalived 集群造成虚拟路由 id 的冲突。
单播模式,需要在配置中加入单播的源地址和目标地址,单播模式需要关闭 vrrp_strict,如下:
unicast_src_ip 172.20.27.10 #配置单播的源地址
unicast_peer {
172.20.27.11 #配置单播的目标地址
}
1.3 virtuall_router_id 冲突问题
virtuall_router_id 取值在 0-255 之间,用来区分多个 instance 的 VRRP 组播,在同一网段内,如果有多组 keepalived 的话,每组的 virtuall_router_id 不能相同,否则会报错如下:
Sep 3 14:38:45 mydb01 Keepalived_vrrp[17228]: ip address associated with VRID not present in received packet : 192.168.2.103
Sep 3 14:38:45 mydb01 Keepalived_vrrp[17228]: one or more VIP associated with VRID mismatch actual MASTER advert
Sep 3 14:38:45 mydb01 Keepalived_vrrp[17228]: bogus VRRP packet received on eth0 !!!
Sep 3 14:38:45 mydb01 Keepalived_vrrp[17228]: VRRP_Instance(VI_1) ignoring received advertisment...
单播模式下,多个 keepalived 集群,其 virtuall_router_id 值可以相同,virtuall_router_id 值必须要设置,如果不设置该值,会在日志中看到如下错误:
VRRP_Instance(VI_1) the virtual id must be set!
二、lvs
lvs 官方网站:http://www.linux-vs.org/
lvs 是 Linux 虚拟服务器(Linux Virtual Server)的简称,与 virtual server 对应的是 real server,lvs 通过一组 real server 实现了系统的高可用和高可扩展性。用户通过 virtual server 进行业务访问,lvs 内部将连接转发到 real server,实现负载均衡和高可用。lvs 可用于 web,cache,mail,ftp,database 等多种场景。
lvs 因为使用了 virtual server,所以需要申请 vip 资源。vip 与 主机实际 ip 并没有太大的区别,都在一个网段内,实际 ip 与主机绑定,实际 ip 在主机的生命周期内不会发生变动,而 vip 与具体哪个主机绑定是不固定的,在满足一定条件下,会从一个主机漂移到另一个主机。
keepalived + lvs 能够实现负载均衡,业务只需要访问 vip,lvs 会根据实际的 real server 进行流量的转发。当有多个 real server 时,就实现了负载均衡,同时某个 real server 发生故障,这套架构会自动将故障 real server 摘除,该节点恢复后,能够重新加入到流量分发中。
keepalived 与 lvs 本身也是高可用的,可以部署在多个节点上,比如一个 master,一个 backup,master 节点挂掉,它会自动切到 backup 节点,实现 keepalived 和 lvs 的故障转移。
keepalived 与 lvs 可以独立部署,也可以与后端服务部署在一起,因为 keepalived 与 lvs 本身对资源消耗不大,为了节省资源,将其与后端服务部署在一起也是一种不错的选择。
2.1 lvs 的组成
- lvs 由 2 部分程序组成,包括 ipvs 和 ipvsadm。ipvs(ip virtual server):工作在内核空间,是真正生效实现调度的代码。
- ipvsadm:工作在用户空间,负责为 ipvs 内核框架编写规则,定义谁是集群服务,而谁是后端真实的服务器(real Server)。
2.2 lvs 相关术语
- DS:Director Server, 指的是前端负载均衡器节点。
- RS:Real Server, 后端真实的工作服务器。
- VIP:向外部直接面向用户请求,作为用户请求的目标IP地址。
- DIP:Director Server IP, 前端负载均衡器IP地址,主要用于和内部主机通信。
- RIP:Real Server IP, 后端服务器的IP地址。
- CIP:Client IP, 访问客户端的IP地址
2.3 lvs 工作模式
(1)LVS-DR 模式:
DR 模式(Virtual Server via Direct Routing),客户端向 vip 发送请求,vip 绑在 Director(调度器)上,Director 根据调度算法将这一请求转发给 real server,注意在转发的过程中,仅仅是修改了数据报文中的 mac 地址,所以这也是为什么我们要求Director 和 real server 必须在同一个物理网络内,就是为了保证可以通过修改 mac 地址而进行数据报文的转发。当 real server 处理请求,响应数据,发送响应数据给客户端,按理说此时的数据包的源 ip 为 real server 的 ip,目标 ip 为 client 的 ip,虽然能找到客户端,但是客户端是不收该数据包的,因为客户端并没有请求该 real server 的 ip,现在的做法就是进行 ip 欺骗,即就是修改源 ip 为 vip,但是不可以将 vip 设置在出口网卡上,否则会响应客户端的 arp request,造成 client/gateway arp table 紊乱,以至于整个 load balance 都不能正常工作。要在 lo 接口上配置 vip,并将此 vip 屏蔽。
LVS-DR 模式数据包流向分析:
- 用户发送请求到 Director Server,请求的数据报文(源 IP 是 CIP,目标 IP 是 VIP)到达内核空间。
- 由于 DS 和 RS 在同一个网络中,所以是通过二层数据链路层来传输。
- 内核空间判断数据包的目标 IP 是本机 IP,此时IPVS 比对数据包请求的服务是否为集群服务,若是,重新封装数据包,修改源 MAC 地址为 DIP 的 MAC 地址,目标 MAC 地址为 RIP 的 MAC 地址,源 IP 地址与目标 IP 地址没有改变,然后将数据包发送给 Real Server。
- RS 发现请求报文的 MAC 地址是自己的 MAC 地址,就接收此报文,重新封装报文(源 IP 地址为VIP,目标 IP 为 CIP),将响应报文通过 lo 接口传送给 eth0 网卡然后向外发出。
- RS 直接将响应报文传送到客户端。
LVS-DR 模式的特点:
- RS 和 DS 必须在同一个物理网络中。
- RS 可以使用私有地址,也可以使用公网地址,如果使用公网地址,可以通过互联网对 RIP 进行直接访问。
- 所有的请求报文经由 Director Server,但响应报文必须不能经过 Director Server。
- RS 的网关绝不允许指向 DIP (不允许数据包经过Director)。
- RS 上的 lo 接口配置 VIP 的 IP 地址。
LVS-DR 模式注意事项:
保证前端路由将目标地址为 VIP 报文统统发给 Director Server,而不是 RS。
解决方案是:修改 RS 上内核参数(arp_ignore 和 arp_announce)将 RS 上的 VIP 配置在 lo 接口的别名上,并限制其不能响应对VIP地址解析请求。arp_ignore=1 表示系统只响应目的 IP 为本地 IP 的 ARP 请求。arp_announce=2 表示系统不使用 IP 包的源地址来设置 ARP 请求的源地址,而选择发送接口的 IP 地址。
LVS-DR 模式设置内核参数如下:
- net.ipv4.conf.lo.arp_ignore = 1
- net.ipv4.conf.lo.arp_announce = 2
- net.ipv4.conf.all.arp_ignore = 1
- net.ipv4.conf.all.arp_announce = 2
(2)LVS-NAT 模式:
LVS-NAT 模式数据包流向分析:
- 用户发送请求到 Director Server,请求的数据报文(源 IP 是 CIP,目标 IP 是 VIP)到达内核空间。
- 内核空间判断数据包的目标 IP 是本机,此时 IPVS 比对数据包请求的服务是否为集群服务,若是,修改数据包的目标 IP 地址为后端服务器 IP,重新封装数据包(源 IP 为 CIP,目标 IP 为 RIP),然后选路将数据包发送给 Real Server。
- Real Server 比对发现目标 IP 是本机的 IP,重新封装报文(源 IP 为 RIP,目标 IP 为 CIP)发回给 Director Server。
- Director Server 重新封装数据包,将源 IP 地址修改为自己的 VIP 地址,然后响应给客户端。 此时报文的源 IP 为 VIP,目标 IP 为 CIP。
LVS-NAT 模式的特点:
- RS 必须使用私有 IP 地址,网关指向 DIP。
- DIP 与 RIP 必须在同一网段内。
- DS 作为所有服务器节点的网关,也就是说请求和响应报文都需要经过 Director Server。
- 支持端口映射
- 高负载场景中,Director Server 压力比较大,易成为性能瓶颈。
2.4 lvs的负载均衡调度算法
最常用的有四种;轮询(rr)、加权轮询(wrr)、最少连接(lc)和加权最少连接(wlc)。
- 轮询(rr):将收到的访问请求按照顺序轮流调度到不同的服务器上,不管后端真实服务器的实际连接数和系统负载。
- 加权轮询(wrr):给 RS 设置权重,权重越高,那么分发的请求数越多,权重的取值范围 0–100。根据每台服务器的性能,给每台服务器添加权值,如果 RS1 的权值为 1,RS2 的权值为 2,那么调度到 RS2 的请求会是 RS1 的 2 倍。权值越高的服务器,处理的请求越多。这种算法是对 rr 算法的一种优化和补充。
- 最少连接(lc):根据后端 RS 的连接数来决定把请求分发给谁,比 RS1 连接数比 RS2 连接数少,那么请求就优先发给 RS1。
- 加权最少连接(wlc):根据后端 RS 的权重和连接数来决定把请求分发给谁,权重较高,连接数少的 RS 会优先处理请求。
三、keepalived+lvs 常用示例
安装 keepalived:
yum install keepalived -y
安装 ipvsadm:
yum install ipvsadm -y
3.1 高可用
场景:
有两个数据库节点,1主1从,客户端通过 vip 查询数据库。vip 绑在 从库上,在从库挂掉的情况下,vip 自动漂移到主库,保证业务可用性。
- 数据库主库(Keepalived Master):192.168.56.101
- 数据库从库(Keepalived Backup):192.168.56.102
- vip:192.168.56.103
数据库主库同时也是 keepalived 的 Master 节点,数据库从库同时也是 keepalived 的 Backup 节点,Master 节点配置如下:
/etc/keepalived/keepalived.conf
vrrp_script check1 {
script "/opt/test1.sh"
interval 2
weight 1
}
vrrp_script check2 {
script "/opt/test2.sh"
interval 1
weight 3
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 101
priority 100
advert_int 1
track_script {
check1
check2
}
virtual_ipaddress {
192.168.56.103
}
unicast_src_ip 192.168.56.101
unicast_peer {
192.168.56.102
}
}
由于使用了单播,主备节点的 keepalived 配置主要区别在于 unicast_src_ip 和 unicast_peer,分别配置为本机 IP 和 对端 IP。不使用单播的话,去掉 unicast_src_ip 和 unicast_peer 配置项,主备节点的 keepalived 配置完全相同。
keepalived 的主备角色可以通过自定义脚本 check1,check2 来决定,比如让数据库从节点获取更高的权重,那么业务通过 vip 访问数据库将优先连接到从库,从库挂掉后,vip 会自动漂移到主库,业务也随之连接到主库。
check1 和 check2 中定义了具体执行的脚本,脚本执行的时间间隔,以及权重值,当脚本返回 0 时,节点权重值增加,返回非 0 时,则不增加权重。
3.2 负载均衡
- keepalived Master:192.168.56.99
- keepalived Backup:192.168.56.100
- 数据库主库:192.168.56.101
- 数据库从库:192.168.56.102
- vip:192.168.56.103
场景:
业务连接 vip,能够将业务流量均衡地转发到后端数据库主从节点上。
配置步骤:
(1)在 real server 上设置内核参数
- net.ipv4.conf.lo.arp_ignore = 1
- net.ipv4.conf.lo.arp_announce = 2
- net.ipv4.conf.all.arp_ignore = 1
- net.ipv4.conf.all.arp_announce = 2
(2)在 real server 的 lo 上配置 vip 地址
如果不需要持久化,直接执行下面命令即可:
ip addr add 192.168.56.103/32 dev lo
如果需要持久化虚拟网络配置,如下:
cd /etc/sysconfig/network-scripts/
cp ifcfg-lo ifcfg-lo:0
vim ifcfg-lo:0
DEVICE=lo:0
IPADDR=192.168.56.103
NETMASK=255.255.255.255 #子网掩码必须全为1
ONBOOT=yes 1
ifup lo:0
ifconfig
执行 ifconfig 查看 lo:0 虚拟网卡接口是否配置成功。
(3)在 director server 上开启路由功能,关闭Linux 内核重定向参数响应
vim /etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.ens33.send_redirects = 0
sysctl -p #保存
(4)在 director server 上配置 keepalived
Master 节点:
global_defs {
notification_email {
}
notification_email_from mail@example.org
smtp_connect_timeout 30
router_id LVS_01 #指定名称,Backup节点名称不同
}
vrrp_instance VI_1 { #定义VRRP热备实例
state MASTER #MASTER表示主调度器
interface ens33 #承载VIP地址的物理接口
virtual_router_id 51 #虚拟路由器的ID号,每个热备组保持一致
priority 100 #主调度器优先级
advert_int 1 #通告间隔秒数
authentication { #认证信息
auth_type PASS #认证类型
auth_pass 1111 #字码密串
}
virtual_ipaddress { #指定群集VIP地址,也就是漂移地址
192.168.56.103
}
}
virtual_server 3306 { #虚拟服务器VIP地址
delay_loop 6 #健康检查的间隔时间
lb_algo rr #轮询rr的调度算法
lb_kind DR #直接路由工作模式
persistence_timeout 0 #连接保持时间
protocol TCP #应用服务采用的是TCP协议
real_server 192.168.56.101 3306 { #第一个mysql节点的服务器地址、端口
weight 1
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 3306
}
}
real_server 192.168.56.102 3306 { #第二个mysql节点的服务器地址、端口
weight 1
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 3306
}
}
}
Backup 节点:
- router_id LVS_01 -> router_id LVS_02 #Backup节点名称
- state MASTER -> state BACKUP #从调度器
- priority 100 -> priority 90 #从调度器优先级
启动 keepalived:
#先主后从分别启动 keepalived
systemctl start keepalived
(4)动态添加删除real server:
ipvsadm -a -t $VIP:3306 -r $RIP1:3306 -g
ipvsadm -d -t $VIP:3306 -r $RIP1:3306 -g
以上是组播的 keepalived 负载均衡配置,如果网络环境不支持组播,需要配置单播:
unicast_src_ip 192.168.56.99 #配置单播的源地址
unicast_peer {
192.168.56.100 #配置单播的目标地址
}
四、director server 与 real server 部署在同一台机器上
director server 与 real server 分开部署会浪费机器资源,尤其在访问量不大的情况下,资源浪费更为严重。这时可以考虑将 director server 和 real server 部署在同一台机器上,节点机器资源。
比如数据库1主1从,在两台数据库机器上同时部署两个 director server。但是由于 lvs-dr 模式下,负载均衡从一个 director server 转发到另外一个 director server,会产生循环转发,为了避免这个问题,需要在 director server 上为网络包打上标记(mark),区分哪些包需要负载均衡进行转发,哪些不再转发。
在 Master 节点,执行如下命令:
iptables -t mangle -I PREROUTING -d $VIP -p tcp -m tcp --dport 3306 -m mac ! --mac-source $backup_physical_addr -j MARK --set-mark 0x1
在 Backup 节点,执行如下命令:
iptables -t mangle -I PREROUTING -d $VIP -p tcp -m tcp --dport 3306 -m mac ! --mac-source $master_physical_addr -j MARK --set-mark 0x2
keepalived 配置文件上加上 fwmark,Master 节点为 1,Backup 节点为 2,如下所示:
virtual_server fwmark 1 {
delay_loop 10
lb_algo rr
lb_kind DR
protocol TCP
real_server 192.168.56.101 3306 {
...
}
}
设置 fwmark 后,动态增加删除 real server,使用如下命令:
Master节点:
- ipvsadm -a -f 1 -r $real_server_ip:3306
- ipvsadm -d -f 1 -r $real_server_ip:3306
Backup节点:
- ipvsadm -a -f 2 -r $real_server_ip:3306
- ipvsadm -d -f 2 -r $real_server_ip:3306
文章评论