ip_vs 的管理
ipvsadm 与 keepalived for lvs
ipvsadm 命令及参数介绍
部署和配置LVS服务会经常用到一些命令,如ipvsadm,可以使用“ipvsadm -help”命令查看使用帮助。
-
ipvsadm 命令的常用参数及其说明如下:
# 添加虚拟服务器 # 语法: ipvsadm -A [-t|u|f] [vip_addr:port] [-s:指定算法] --add-service, -A :增加虚拟vip服务 --edit-service, -E :修改虚拟vip服务 --tcp-service, -t service-address :TCP协议,service-address为host[:port] --udp-service, -u service-address :UDP协议 --fwmark-service, -f fwmark :防火墙标记,fwmark 是一个大于零的整数 --scheduler, -s scheduler :指定调度算法(rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq),缺省默认 wlc --delete-service, -D :删除虚拟vip服务 # 添加|编辑虚拟vip服务 ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask] [--pe persistence_engine] [-b sched-flags] # 参数: --add-service, -A :增加虚拟vip服务 --edit-service, -E :修改虚拟vip服务 --tcp-service, -t service-address :TCP协议。service-address为host[:port] --udp-service, -u service-address :UDP协议 --fwmark-service, -f fwmark :防火墙标记,fwmark 是一个大于零的整数 --scheduler, -s scheduler :指定调度算法(rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq),缺省默认 wlc # 删除虚拟vip服务 ipvsadm -D -t|u|f service-address --delete-service, -D # 添加|编辑真实主机 ipvsadm -a|e -t|u|f service-address -r server-address [options] --add-server, -a :添加真实主机 --edit-server, -e :修改真实主机配置 --tcp-service, -t service-address :TCP协议。service-address为host[:port] --udp-service, -u service-address :UDP协议 --fwmark-service, -f fwmark :防火墙标记,fwmark 是一个大于零的整数 --real-server, -r :指定后端realserver的IP --gatewaying, -g :DR模式 --ipip, -i :TUN模式 --masquerading, -m :NAT模式 --weight, -w :指定权重 # 删除真实主机 ipvsadm -d -t|u|f service-address -r server-address --delete-server, -d :删除真实主机配置 # 查看当前集群信息 ipvsadm -ln --list, -L|-l :显示详细列表信息 # 以下选项用于list命令 --numeric, -n :不对ip地址进行dns查询,以数字形式输出信息 --connection, -c :列出当前的IPVS连接。 --timeout :列出超时 --daemon :列出进程 --stats :状态信息 --rate :传输速率 --thresholds :列出阈值 --persistent-conn :坚持连接 --sor :把列表排序 --nosort :不排序 --exact :单位 # 清空所有记录 ipvsadm -C --clear, -C :清空所有记录 # 从stdin恢复规则 ipvsadm -R --restore, -R # 将规则保存到stdout ipvsadm -S [-n] --save, -S # 显示详细列表信息 ipvsadm -L|l [options] --list, -L|-l # 一个服务或所有服务中的计数器归零 ipvsadm -Z [-t|u|f service-address] --zero, -Z # 设置连接超时值,单位s ipvsadm --set tcp_time tcpfin_time udp_time # 启动连接同步守护进程 ipvsadm --start-daemon state [--mcast-interface interface] [--syncid sid] # 停止连接同步守护进程 ipvsadm --stop-daemon state # 查看帮助 ipvsadm -h
-
lvs 进程相关命令:
# 查看下内核是否有加载 lvs lsmod | grep ip_vs # 加载ip_vs模块 modprobe ip_vs # 查看ip_vs版本信息 cat /proc/net/ip_vs # 安装 ipvsadm yum -y install ipvsadm
案例
keepalived 通过配置文件管理 ip_vs
环境说明
- LVS 给两台 nginx 做负载均衡
- keepalived 做 lvs 高可用,同时做 Real-Server 健康检查,如果发现 Real-Server 的端口没开,就认为故障,从集群中剔除
- 在 keepalived 配置文件内就能配置 LVS
主机名 | IP地址 | 作用 |
---|---|---|
lb01 | 192.168.60.111 | lvs-master |
lb02 | 192.168.60.112 | lvs-backup |
realserver-1 | 192.168.60.121 | nginx |
realserver-2 | 192.168.60.122 | nginx |
192.168.60.200 | VIP |
主备服务器系统配置
主备服务器共同操作:
-
安装所需应用,加载系统内核 ip_vs 模块
### 关闭firewalld防火墙 [root@localhost ~]# systemctl stop firewalld.service ### 关闭selinux防火墙 [root@localhost ~]# setenforce 0 ### 安装所需应用 [root@localhost ~]# yum -y install ipvsadm keepalived ### 加载ip_vs模块 [root@localhost ~]# modprobe ip_vs ### 查看ip_vs版本信息 [root@localhost ~]# cat /proc/net/ip_vs IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn
-
编写 lvs 健康检查脚本
vi /usr/libexec/keepalived/lvs_check.sh
脚本内容:
#!/bin/bash ip=$(hostname -I | awk '{print $1}') dt=$(date +'%Y%m%d %H:%M:%S') echo "$0--${ip}--${dt}" >> /tmp/kp.log # 检查 LVS 的状态 if [ -e /proc/net/ip_vs ]; then if [[ $(cat /proc/net/ip_vs | grep TCP) != '' ]];then exit 0 # 正常状态 else echo "${ip}--${dt}: LVS is not running. Take necessary actions" >> /tmp/kp.log exit 1 # 异常状态 fi else echo "${ip}--${dt}: LVS is not running. Take necessary actions" >> /tmp/kp.log exit 1 fi
给脚本加执行权限
chmod +x /usr/libexec/keepalived/lvs_check.sh
主服务器 keepalived 配置文件
[root@localhost ~]#cd /etc/keepalived/ #配置文件存放目录 [root@localhost keepalived]# cp keepalived.conf keepalived.conf.bak #备份一份配置文件 [root@localhost keepalived]# vi keepalived.conf ...... global_defs { ### 定义全局参数 smtp_server 127.0.0.1 ### 修改,邮件服务指向本地 smtp_connect_timeout 30 ### 连接超时时间 router_id LVS_01 ### 修改,指定服务器(路由器)的名称,主备服务器名称须不同,主为LVS_01,备为LVS_02 #vrrp_skip_check_adv_addr ### 这四行注释掉,取消严格遵守VRRP协议功能,否则VIP无法被连接 #vrrp_strict #vrrp_garp_interval 0 #vrrp_gna_interval 0 } # 定义 lvs 健康检查脚本 vrrp_script lvs_check { script "/usr/libexec/keepalived/lvs_check.sh" interval 1 } vrrp_instance VI_1 { ### 定义VRRP热备实例参数 state MASTER ### 修改,指定热备状态,主为MASTER,备为BACKUP interface ens33 ### 修改,指定承载vip地址的物理接口 virtual_router_id 10 ### 修改,指定虚拟路由器的ID号,每个热备组保持一致 #nopreempt ### 如果设置非抢占模式,两个节点state必须为BACKUP,并加上配置 nopreempt priority 100 ### 修改,指定优先级,数值越大优先级越高,这里设置主为100,备为90 advert_int 1 ### 通告间隔秒数(心跳频率) authentication { ### 定义认证信息,每个热备组保持一致 auth_type PASS ### 认证类型 auth_pass abc123 ### 修改,指定验证密码,主备服务器保持一致 } virtual_ipaddress { ### 指定群集vip地址 192.168.60.200 } # 调用 lvs 健康检查脚本 track_script { lvs_check } } ################## LVS配置 ############## # 添加虚拟服务器 # 相当于 ipvsadm -A -t 192.168.60.200:8080 -s wrr virtual_server 192.168.60.200 8080 { ### 修改,指定虚拟服务器地址(VIP)、端口,定义虚拟服务器和Web服务器池参数 delay_loop 6 ### 健康检查的间隔时间(秒) lb_algo rr ### 指定调度算法,轮询(rr) lb_kind DR ### 修改,指定群集工作模式,直接路由(DR) persistence_timeout 0 ### 连接保持时间(秒) protocol TCP ### 应用服务采用的是 TCP协议 # 添加后端realserver # 相当于 ipvsadm -a -t 192.168.0.100:8080 -r 192.168.60.121:8080 -w 1 real_server 192.168.60.121 8080 { ### 修改,指定第一个真实的物理节点的地址、端口 weight 1 # 节点的权重 TCP_CHECK { ### 使用 TCP_CHECK 健康检查方式 connect_port 8080 # 添加检查的目标端口 connect_timeout 3 # 添加连接超时(秒) nb_get_retry 3 # 添加重试次数 delay_before_retry 3 # 添加重试间隔 } } real_server 192.168.60.122 8080 { # 添加第二个真实的物理节点的地址、端口 weight 1 TCP_CHECK { connect_port 8080 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }
备服务器 keepalived 配置文件
[root@localhost ~]#cd /etc/keepalived/ #配置文件存放目录 [root@localhost keepalived]# cp keepalived.conf keepalived.conf.bak #备份一份配置文件 [root@localhost keepalived]# vim keepalived.conf ...... global_defs { smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id LVS_02 } vrrp_script lvs_check { script "/usr/libexec/keepalived/lvs_check.sh" interval 1 } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 10 #nopreempt priority 90 advert_int 1 authentication { auth_type PASS auth_pass abc123 } virtual_ipaddress { 192.168.60.200 } track_script { lvs_check } } virtual_server 192.168.60.200 8080 { delay_loop 6 lb_algo rr lb_kind DR persistence_timeout 0 protocol TCP real_server 192.168.60.121 8080 { weight 1 TCP_CHECK { connect_port 8080 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.60.122 8080 { weight 1 TCP_CHECK { connect_port 8080 connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }
启动 keepalived
-
修改过配置文件之后,主备服务器重启 keepalived 服务
systemctl restart keepalived
-
使用 ip add 命令检查 vip 是否生成
-
查看 lvs
真实服务器的服务启动,lvs 就会添加规则;服务一关闭,lvs 就会去掉规则
[root@lvs1 keepalived]# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.60.200:8080 wrr -> 192.168.60.121:8080 Route 1 0 0 -> 192.168.60.122:8080 Route 1 0 0
-
修改 lvs 的超时时间
# 查看 lvs 的超时时间 [root@DR1 keepalived]# ipvsadm -L --timeout Timeout (tcp tcpfin udp): 900 120 300
900 120 300 这三个数值分别是 TCP TCPFIN UDP 的默认超时时间,也就是说一条 tcp 的连接经过 lvs 后,lvs 会把这台记录保存15 分钟。因为这个时间比较长,所以如果不做修改的话,在使用浏览器测试 lvs 的 dr 轮询效果时会发现轮询现象并没有发生,测试时可以将此数值调整小(单位是 秒)
[root@DR1 ~]# ipvsadm --set 1 2 1
注意:lvs 超时时间虽然调小了,但依然是 秒 级别的,浏览器连续点击不会实现连续跳转,至少需隔 1 秒再点才会出现跳转
真实服务器部署 nginx
-
安装软件
# 安装nginx以及拓展源 yum install epel-release -y yum install -y nginx
-
Nginx 配置 web 站点
#web1 [root@nginx1 ~]# vi /etc/nginx/conf.d/web.conf server{ listen 8080; root /usr/share/nginx/html; index test.html; } [root@nginx1 ~]# echo "<h1>This is web1</h1>" > /usr/share/nginx/html/test.html
#web2 [root@nginx2 ~]# vi /etc/nginx/conf.d/web.conf server{ listen 8080; root /usr/share/nginx/html; index test.html; } [root@nginx2 ~]# echo "<h1>This is web2</h1>" > /usr/share/nginx/html/test.html
-
启动 Nginx
nginx -t nginx
真实服务器绑定 VIP
-
编写脚本
vi rs.sh
脚本内容
#!/bin/bash #description: Config realserver VIP=192.168.60.200 netmask=255.255.255.255 #/etc/rc.d/init.d/functions case "$1" in start) # 添加 vip 到循环网卡(临时生效) ip addr add $VIP brd $netmask dev lo label lo:0 # 添加 vip 到路由(临时生效) ip route add $VIP dev lo:0 # 设置真实服务器的lo接口不做ARP应答,使得各个接口只对本接口上的地址进行响应 #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 sysctl -p >/dev/null 2>&1 echo "RealServer Start OK" ;; stop) ip addr del $VIP brd $netmask dev lo label lo:0 ip route del $VIP dev lo:0 #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 "RealServer Stoped" ;; *) echo "Usage: $0 {start|stop}" exit 1 esac exit 0
-
执行脚本
sh rs.sh start
拓展
-
永久绑定 VIP
[root@web02 network-scripts]# cd /etc/sysconfig/network-scripts [root@web02 network-scripts]# cp ifcfg-lo ifcfg-lo:1 [root@web02 network-scripts]# vi ifcfg-lo:1 DEVICE=lo:1 IPADDR=192.168.245.166 NETMASK=255.255.255.255 ONBOOT=yes NAME=loopback
-
抑制 arp 解析
#方法1: cat >> /etc/sysctl.conf << EOF net.ipv4.conf.all.arp_ignore=1 net.ipv4.conf.all.arp_announce=2 #net.ipv4.conf.lo.arp_ignore=1 #net.ipv4.conf.lo.arp_announce=2 EOF sysctl -p #方法2: #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
注:
-
arp_ignore 为 1 时:只响应目的 IP 地址为接收网卡上的本地地址的 arp 请求
-
arp_announce 为 2 时:只向该网卡回应与该网段匹配的 ARP 报文
-
回环网卡 lo 和网卡 ens33 是物理隔离的,不在一个网段,在回环网卡上加一个 IP,默认设置下(net.ipv4.conf.lo.arp_ignore=0)是不会把回应 ens33 所在局域网的arp广播的。
所以 net.ipv4.conf.lo.arp_ignore=1 和 /proc/sys/net/ipv4/conf/lo/arp_announce=1 实际是无效设置。
-
net.ipv4.conf.all.arp_announce 参数也可以不设置,应为在这个架构中真实服务器不发 arp 广播,只接收和回应 arp 广播。
-
验证
- 在非 keepalived master 主机(即拿到 vip 的主机)使用 curl 命令测试,而是在其他主机或者用浏览器测试
- 注意:lvs 应对高并发负载均衡,访问是比较少时,并不能像 nginx 那样 1:1 轮询。在浏览器连续点击不会实现连续跳转,需隔 lvs 的超时时间再点才会出现跳转
参考
- LVS的介绍与使用
- LVS详解
- LVS+Keepalived
- [LVS+Keepalived 构造高可用负载均衡集群](