lvs+keepalived+dr模式部署及10W并发调优实例 作者: sysit 分类: d 发表于 2020-10-10 61人围观 ## 1. 关于LVS及LVS+Keepalived架构 LVS是 Linux Virtual Server 的简称,它自身就可以实现负载均衡技术。为什么还要结合keepalived使用呢? (1)LVS可以实现负载均衡,但是不能够进行健康检查。比如一个RS出现故障,LVS 仍然会把请求转发给故障的RS服务器,这样就会导致请求的无效性;keepalived 软件可以进行健康检查。 (2)使用keepalived能同时实现 LVS 的高可用性,解决 LVS 单点故障的问题。 ## 2. LVS工作原理 (1)当用户向负载均衡调度器(Director Server)发起请求,调度器将请求发往至内核空间 (2)PREROUTING链首先会接收到用户请求,判断目标IP确定是本机IP,将数据包发往INPUT链 (3)IPVS是工作在INPUT链上的,当用户请求到达INPUT时,IPVS会将用户请求和自己已定义好的集群服务进行比对,如果用户请求的就是定义的集群服务,那么此时IPVS会强行修改数据包里的目标IP地址及端口,并将新的数据包发往POSTROUTING链 (4)POSTROUTING链接收数据包后发现目标IP地址刚好是自己的后端服务器,那么此时通过选路,将数据包最终发送给后端的服务器 ## 3. 术语 * DS:Director Server。指的是前端负载均衡器节点。 * RS:Real Server。后端真实的工作服务器。 * VIP:向外部直接面向用户请求,作为用户请求的目标的IP地址。 * DIP:Director Server IP,主要用于和内部主机通讯的IP地址。 * RIP:Real Server IP,后端服务器的IP地址。 * CIP:Client IP,访问客户端的IP地址。 ## 4. LVS的3种模式 ### 4.1 NAT模式 ### 4.2 DR模式 ### 4.1 TUN模式 ## 5. LVS的8种调度算法 * 轮叫调度 rr 轮询算法假设所有的服务器处理请求的能力都是一样的,调度器会将所有的请求平均分配给每个真实服务器,不管后端 RS 配置和处理能力,非常均衡地分发下去。 * 加权轮叫 wrr 在 rr 的算法的基础上多了一个权重的概念,可以给 RS 设置权重,权重越高,那么分发的请求数越多,权重的取值范围 0 – 100。权值越高的服务器,处理的请求越多。 * 最少链接 lc 根据后端 RS 的连接数来决定把请求分发给谁,比如 RS1 连接数比 RS2 连接数少,那么请求就优先发给 RS1 * 加权最少链接 wlc 在 lc 算法的基础上多了一个权重的概念。 * 基于局部性的最少连接调度算法 lblc 先根据请求的目标 IP 地址寻找最近的该目标 IP 地址所有使用的服务器,如果这台服务器依然可用,并且有能力处理该请求,调度器会尽量选择相同的服务器,否则会继续选择其它可行的服务器。 * 复杂的基于局部性最少的连接算法 lblcr 记录的不是要给目标 IP 与一台服务器之间的连接记录,它会维护一个目标 IP 到一组服务器之间的映射关系,防止单点服务器负载过高。 * 目标地址散列调度算法 dh 根据目标 IP 地址通过散列函数将目标 IP 与服务器建立映射关系,出现服务器不可用或负载过高的情况下,发往该目标 IP 的请求会固定发给该服务器。 * 源地址散列调度算法 sh 与目标地址散列调度算法类似,但它是根据源地址散列算法进行静态分配固定的服务器资源。 ## 6. 部署LVS+keepalived的限制 (1)DS和RS不能部署在同一个节点上。 (2)VIP和DS可以部署在同一节点上,但是VIP和DIP要同网段,或者VIP属于DIP所属网段中的一个可用IP。 (3)无论什么时候,如果需要测试LVS的功能和性能,都不能把测试机选择在DS和RS服务器上。 ## 7. 部署IPVS+KEEPALIVED ### 7.1 环境说明  注意: (1)lvs+keepalived至少需要2台服务器。 (2)需要一个VIP。 (3)RS服务器不能和LVS以及Keepalived复用。 ### 7.2 lvs+keepalived服务器安装配置 * 安装ipvs和keepalived ``` yum install ipvsadm keepalived -y ``` * keepalived配置 > 注意: (1)keepalived是否需要争抢主IP,如果不需要,需要把state都修改为BACKUP,并配置nopreempt。 (2)persistence_timeout的作用是:在一定时间内使来自于同一个Client的所有TCP请求被负载到同一个RealServer上,查看ipvsadm -S -n **主节点** ``` #主节点( MASTER )配置文件 cat > /etc/keepalived/keepalived.conf <<'EOF' ! Configuration File for keepalived global_defs { router_id LVS_DEVEL } vrrp_instance VI_1 { state BACKUP # 主为master,不争抢模式改为BACKUP #nopreempt #不争抢模式添加 interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.112.10 } } virtual_server 192.168.112.10 80 { delay_loop 6 lb_algo rr lb_kind DR #persistence_timeout 0 protocol TCP real_server 192.168.112.13 80 { weight 1 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.112.14 80 { weight 1 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.112.15 80 { weight 1 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } } EOF ``` **从节点** ``` cat > /etc/keepalived/keepalived.conf <<'EOF' ! Configuration File for keepalived global_defs { router_id LVS_DEVEL } vrrp_instance VI_1 { state BACKUP #nopreempt #不争抢模式添加 interface eth0 virtual_router_id 51 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.112.10 } } virtual_server 192.168.112.10 80 { delay_loop 6 lb_algo rr lb_kind DR #persistence_timeout 0 protocol TCP real_server 192.168.112.13 80 { weight 1 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.112.14 80 { weight 1 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.112.15 80 { weight 1 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } } EOF ``` * 内核参数 ``` echo 1 > /proc/sys/net/ipv4/ip_forward sysctl -w net.ipv4.ip_forward=1 ``` * 启动 ``` systemctl enable keepalived systemctl start keepalived ``` ### 7.3 真实服务器配置 * 配置脚本 不需要在lvs+keepalived的服务器上配置,需要在所有的真实服务器上配置。注意vip必须与前面keepalived上的vip相同。 ``` # vim lvs_dr_rs.sh SNS_VIP=192.168.112.10 /etc/rc.d/init.d/functions case "$1" in start) ifconfig lo:0 $SNS_VIP netmask 255.255.255.255 broadcast $SNS_VIP /sbin/route add -host $SNS_VIP dev lo:0 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) ifconfig lo:0 down route del $SNS_VIP >/dev/null 2>&1 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 ``` * 执行生效 ``` # 所有RS节点上分别执行脚本: chmod +x lvs_dr_rs.sh ./lvs_dr_rs.sh start ``` ## 8. ipvsadm常用命令 * ipvsadm 参数 ``` -C 清除表中所有的记录 -A --add-service在服务器列表中新添加一条新的虚拟服务器记录 -t 表示为tcp服务 -u 表示为udp服务 -s --scheduler 使用的调度算法, rr | wrr | lc | wlc | lblb | lblcr | dh | sh | sed | nq 默认调度算法是 wlc -a --add-server 在服务器表中添加一条新的真实主机记录 -t --tcp-service 说明虚拟服务器提供tcp服务 -u --udp-service 说明虚拟服务器提供udp服务 -r --real-server 真实服务器地址 -m --masquerading 指定LVS工作模式为NAT模式 -w --weight 真实服务器的权值 -g --gatewaying 指定LVS工作模式为直接路由器模式(也是LVS默认的模式) -i --ipip 指定LVS的工作模式为隧道模式 -p 会话保持时间,定义流量呗转到同一个realserver的会话存留时间 ``` 例子:`ipvsadm -a -t 192.168.112.10:80 -r 192.168.112.13:80 -m -w 1` * 清除表中所有的记录 ``` ipvsadm -C ``` * 查看 `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.112.10:80 wrr -> 192.168.112.13:80 Route 1 171 2153 -> 192.168.112.14:80 Route 1 150 2148 -> 192.168.112.15:80 Route 1 154 2150 ``` >Forward 转发方式,当前是路由转发; Weight 权重; ActiveConn 当前活跃的连接数; InActConn 指非活跃连接数,我们将处于 TCP ESTABLISH 状态以外的连接都称为不活跃连接。例如处于 SYN_RECV 状态的连接,处于 TIME_WAIT 状态的连接等。 * 查看速率 `ipvsadm -Ln --rate` ``` IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port CPS InPPS OutPPS InBPS OutBPS -> RemoteAddress:Port TCP 192.168.112.10:80 54 288 0 31825 0 -> 192.168.112.13:80 18 95 0 10384 0 -> 192.168.112.14:80 18 96 0 10884 0 -> 192.168.112.15:80 18 97 0 10556 0 ``` >CPS (current connection rate) 每秒连接数 InPPS (current in packet rate) 每秒的入包个数 OutPPS (current out packet rate) 每秒的出包个数 InBPS (current in byte rate) 每秒入流量(字节) OutBPS (current out byte rate) 每秒入流量(字节) * 查看全部连接数和流量 `ipvsadm -Ln --stats` ``` IP Virtual Server version 1.2.1 (size=1048576) Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes -> RemoteAddress:Port TCP 192.168.112.10:80 113786 19495479 0 2110M 0 -> 192.168.112.13:80 12883 1679941 0 181747K 0 -> 192.168.112.14:80 40269 10218905 0 1105M 0 -> 192.168.112.15:80 40240 7403127 0 804275K 0 ``` >--stats选项是统计自该条转发规则生效以来的 Conns (connections scheduled) 已经转发过的连接数 InPkts (incoming packets) 入包个数 OutPkts (outgoing packets) 出包个数 InBytes (incoming bytes) 入流量(字节) OutBytes (outgoing bytes) 出流量(字节) * 修改 LVS 表中的 timeout ``` ipvsadm --set 900 60 300 ipvsadm -ln --timeout Timeout (tcp tcpfin udp): 900 60 300 ``` ## 9. lvs负载10w+并发的调优 ### 9.1 LVS参数调优 * 增大ipvs模块hash table的大小 ipvs模块hash table默认值为2^12=4096,改为2^20=1048576。可以用ipvsadm -l命令查询当前hash table的大小。 ``` IP Virtual Server version 1.2.1 (size=4096) ``` 修改方法: 在`/etc/modprobe.d/`目录下添加文件`ip_vs.conf`,内容为: ``` options ip_vs conn_tab_bits=20 ``` 重新加载ipvs模块。 ``` IP Virtual Server version 1.2.1 (size=1048576) ``` ### 9.2 文件句柄及进程数 ``` * soft nofile 1024000 * hard nofile 1024000 * soft nproc 1024000 * hard nproc 1024000 ``` ### 9.3 内核参数 ``` fs.file-max = 1048576 net.ipv4.ip_forward = 1 net.core.wmem_default = 8388608 net.core.wmem_max = 16777216 net.core.rmem_default = 8388608 net.core.rmem_max = 16777216 net.core.somaxconn = 65535 net.core.optmem_max = 81920 net.core.netdev_max_backlog = 262144 net.ipv4.route.gc_timeout = 20 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_abort_on_overflow = 1 net.ipv4.tcp_max_tw_buckets = 6000 net.ipv4.tcp_sack = 1 net.ipv4.tcp_window_scaling = 1 net.ipv4.tcp_no_metrics_save = 1 net.ipv4.tcp_rmem = 32768 131072 16777216 net.ipv4.tcp_wmem = 8192 131072 16777216 net.ipv4.tcp_mem = 94500000 915000000 927000000 net.ipv4.tcp_max_syn_backlog = 262144 net.ipv4.tcp_max_orphans = 3276800 net.ipv4.tcp_timestamps = 0 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_syn_retries = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_fin_timeout = 10 net.ipv4.tcp_keepalive_time = 120 net.ipv4.tcp_keepalive_probes = 3 net.ipv4.tcp_keepalive_intvl = 15 net.ipv4.tcp_retries2 = 5 net.ipv4.ip_local_port_range = 1024 65000 net.ipv4.conf.default.rp_filter = 1 net.ipv4.conf.default.accept_source_route = 0 net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.all.arp_announce = 2 #modprobe ip_conntrack net.netfilter.nf_conntrack_tcp_timeout_established = 180 net.netfilter.nf_conntrack_max = 1048576 net.nf_conntrack_max = 1048576 kernel.sysrq = 0 kernel.core_uses_pid = 1 kernel.msgmnb = 65536 kernel.msgmax = 65536 kernel.shmmax = 68719476736 kernel.shmall = 4294967296 ``` 如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作! 赞赏支持