Haproxy/LVS负载均衡实现+keepalived实现高可用

haproxy+keepalived 集群高可用集群转发 环境介绍

#内核版本 Ubuntu 18.04.4 LTS \n \l 107-Ubuntu SMP Thu Jun 4 11:27:52 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux #节点介绍 192.168.1.113hk-master1 192.168.1.114hk-master2 192.168.1.111hk-slave1 192.168.1.112hk-slave2

内核调优
#调整Linux进程资源限制 vim /etc/security/limits.conf root soft core unlimited root hard core unlimited root soft nproc 600000 root hard nproc 600000 root soft nofile 648576 root hard nofile 600000 root soft memlock 32000 root hard memlock 32000 root soft msgqueue 8192000 root hard msgqueue 8192000* soft core unlimited * hard core unlimited * soft nproc 600000 * hard nproc 600000 * soft nofile 600000 * hard nofile 600000 * soft memlock 32000 * hard memlock 32000 * soft msgqueue 8192000 * hard msgqueue 8192000 #验证(进程对资源的使用情况) root@hk-master2:~# ulimit -a core file size(blocks, -c) unlimited data seg size(kbytes, -d) unlimited scheduling priority(-e) 0 file size(blocks, -f) unlimited pending signals(-i) 7376 max locked memory(kbytes, -l) 32000 max memory size(kbytes, -m) unlimited open files(-n) 600000 pipe size(512 bytes, -p) 8 POSIX message queues(bytes, -q) 8192000 real-time priority(-r) 0 stack size(kbytes, -s) 8192 cpu time(seconds, -t) unlimited max user processes(-u) 600000 virtual memory(kbytes, -v) unlimited file locks(-x) unlimited#调整内核限制追加以下配置 /etc/sysctl.conf net.ipv4.conf.default.rp_filter = 1 net.ipv4.ip_nonlocal_bind = 1 net.ipv4.ip_forward = 1 net.ipv4.conf.default.accept_source_route = 0 kernel.sysrq = 0 kernel.msgmnb = 65536 kernel.msgmax = 65536 kernel.shmmax = 68719476736 kernel.shmall = 4294967296 net.ipv4.tcp_mem = 786432 1048576 1572864 net.ipv4.tcp_rmem = 4096 87380 4194304 net.ipv4.tcp_wmem = 4096 16384 4194304 net.ipv4.tcp_window_scaling = 1 net.ipv4.tcp_sack = 1 net.core.wmem_default = 8388608 net.core.rmem_default = 8388608 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.core.netdev_max_backlog = 262144 net.core.somaxconn = 20480 net.core.optmem_max = 81920 net.ipv4.tcp_max_syn_backlog = 262144 net.ipv4.tcp_syn_retries = 3 net.ipv4.tcp_retries1 = 3 net.ipv4.tcp_retries2 = 15 net.ipv4.tcp_timestamps = 0 #代理不要开这个 net.ipv4.tcp_fin_timeout = 1 net.ipv4.tcp_max_tw_buckets = 20000 net.ipv4.tcp_max_orphans = 3276800 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_keepalive_time = 300 net.ipv4.tcp_keepalive_intvl = 30 net.ipv4.tcp_keepalive_probes = 3 net.ipv4.ip_local_port_range = 10001 65000 vm.overcommit_memory = 0 vm.swappiness = 10 #验证 sysctl -p

haproxy安装和功能介绍
#安装 root@hk-master2:~# apt install -y haproxy root@hk-master1:~# apt install -y haproxy

配置介绍
配置文件目录
主程序:/usr/sbin/haproxy 配置文件:/etc/haproxy/haproxy.cfg Unit file:/usr/lib/systemd/system/haproxy.service

配置段:
#global 配置: ? chroot #锁定运行目录 ? deamon #以守护进程运行 ? #stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin #socket文件 ? user, group, uid, gid #运行haproxy的用户身份 ? nbproc #开启的haproxy进程数,与CPU保持一致 ? nbthread #指定每个haproxy进程开启的线程数,默认为每个进程一个线程 ? cpu-map 1 0 #绑定haproxy 进程至指定CPU ? maxconn #每个haproxy进程的最大并发连接数 ? maxsslconn #SSL每个haproxy进程ssl最大连接数 ? maxconnrate #每个进程每秒最大连接数 ? spread-checks #后端server状态check随机提前或延迟百分比时间,建议2-5(20%-50%)之间 ? pidfile #指定pid文件路径 ? log 127.0.0.1 local3 info #定义全局的syslog服务器;最多可以定义两个 ? defaults [] #默认配置项,针对以下的frontend、backend和lsiten生效,可以多个name ? frontend #前端servername,类似于Nginx的一个虚拟主机 server。 ? backend #后端服务器组,等于nginx的upstream ? listen #将frontend和backend合并在一起配置 ? 注:name字段只能使用”-”、”_”、”.”、和”:”,并且严格区分大小写,例如:Web和web是完全不 同的两组服务器。#defaults 配置参数: ? option redispatch #当server Id对应的服务器挂掉后,强制定向到其他健康的服务器 ? option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接 ? option http-keep-alive 60#开启会话保持 ? option forwardfor #开启IP透传 ? mode http #默认工作类型 ? timeout connect 120s #转发客户端请求到后端server的最长连接时间(TCP之前) ? timeout server 600s #转发客户端请求到后端服务端的超时超时时长(TCP之后) ? timeout client 600s #与客户端的最长空闲时间 ? timeout http-keep-alive 120s #session 会话保持超时时间,范围内会转发到相同的后端服务器 ? #timeout check 5s #对后端服务器的检测超时时间#listen 配置参考: listen WEB_PORT_80 bind 192.168.7.102:80 mode http option forwardfor server web1 192.168.7.101:8080 check inter 3000 fall 3 rise 5 server web2 192.168.7.101:8080 check inter 3000 fall 3 rise 5#后端服务器检测机制参数介绍: check #对指定real进行健康状态检查,默认不开启 ? addr IP #可指定的健康状态监测IP ? port num #指定的健康状态监测端口 ? inter num #健康状态检查间隔时间,默认2000 ms ? fall num #后端服务器失效检查次数,默认为3 ? rise num #后端服务器从下线恢复检查次数,默认为2 ? weight #默认为1,最大值为256,0表示不参与负载均衡 ? backup #将后端服务器标记为备份状态 ? disabled #将后端服务器标记为不可用状态 ? redirect prefix http://www.magedu.com/ #将请求临时重定向至其它URL,只适用于http模式 ? maxconn :当前后端server的最大并发连接数 ? backlog :当server的连接数达到上限后的后援队列长度

调度算法 静态调度算法
balance: 指明对后端服务器的调度算法,配置在listen或backend 静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、链接数和相应速度等,且无法实时修改权重,只能重启后生效。 static-rr:基于权重的轮询调度,不支持权重的运行时调整及后端服务器慢启动,其后端主机数量没有限制 (出现请求按比例分发给后端) first:根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置。(配置的后端服务器连接数到了上线,才会分发到下台后端服务器)

动态调度算法
动态算法:基于后端服务器 状态进行调度适当调整,比如优先调度至当前负载较低的服务器,且权重可以在haproxy运行时动态调整无需重启。 roundrobin:基于权重的轮询动态调度算法,支持权重的运行时调整,不等于lvs 的rr,支持慢启动即新加的服务器会逐渐增加转发数,每个后端backend中最多支持4095个server,此为默认调度算法,server 权重设置 weight leastconn: 加权的最少连接的动态,支持权重的运行时调整和慢启动,即当前后端服务器连接最少的优先调度,比较适合长连接的场景使用,比如MySQL等场景。

source调度算法
source:源地址hash,基于用户源地址hash并将请求转发到后端服务器,默认为静态即取模方式,但是可以通过hash-type支持的选项更改,后续同一个源地址请求将被转发至同一个后端web服务器,比较适用于session保持/缓存业务等场景。? map-based:取模法,基于服务器权重的hash数组取模,该hash是静态的即不支持在线调整权重,不支持慢启动,其对后端服务器调度均衡,缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因权重发生变化而导致调度结果整体改变hash(o)mod n 。?consistent:一致性哈希,该hash是动态的,支持在线调整权重,支持慢启动,优点在于当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动。#配置案例: listen web_prot_http_nodes bind 192.168.7.101:80 mode http balance source hash-type consistent log global option forwardfor server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5 server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5

uri调度算法
uri:基于对用户请求的uri做hash并将请求转发到后端指定服务器 ? map-based:取模法 ? consistent:一致性哈希listen web_prot_http_nodes bind 192.168.7.101:80 mode http #不支持tcp,会切换到tcp的roundrobin负载模式 balance uri hash-type consistent log global option forwardfor server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5 server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5

url_param 调度算法
#url_param: 对用户请求的url中的部分中的参数name作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个Backend Server #url 传递的查询字符串进行bash listen web_prot_http_nodes bind 192.168.7.101:80 mode http #不支持tcp,会切换到tcp的roundrobin负载模式 balance url_param name #基于参数name做hash hash-type consistent log global option forwardfor server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5 server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5

hdr调度算法
#针对每个用户的http请求头中的指定信息做hash,此处由指定的http首部将会被取出并做hash计算,然后由服务器总权重相除以后派发至某挑出的服务器,假如无有效的值,则会被轮询调度 hdr( Cookie、 User-Agent、host )listen web_prot_http_nodes bind 192.168.7.101:80 mode http balance hdr(User-Agent) hash-type consistent #一致性hash log global option forwardfor server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5 server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5

rdp-cookie调度算法
rdp-cookie对远程桌面的负载,使用cookie保持会话listen RDP bind 192.168.7.101:3389 balance rdp-cookie mode tcp server rdp0 172.18.139.20:3389 check fall 3 rise 5 inter 2000 weight 1 server rdp1 172.18.139.21:3389 check fall 3 rise 5 inter 2000 weight 1

配置状态页
stats enable #基于默认的参数启用stats page stats hide-version # 隐藏版本 stats refresh # 设定自动刷新时间间隔 stats uri
#自定义stats page uri,默认值:/haproxy?stats stats realm #账户认证时的提示信息,示例:stats realm : HAProxy\ Statistics stats auth : #认证时的账号和密码,可使用多次,默认:no authentication stats admin { if | unless } #启用stats page中的管理功能listen stats bind :9009 stats enable #stats hide-version stats uri /haproxy-status stats realm HAPorxy\ Stats\ Page stats auth haadmin:123456 stats auth admin:123456 stats refresh 30s stats admin if TRUE

自定义错误页面
errorfile 500 /usr/local/haproxy/html/500.html #自定义错误页面跳转 errorfile 502 /usr/local/haproxy/html/502.html errorfile 503 /usr/local/haproxy/html/503.htmlerrorloc 503 http://192.168.7.103/error_page/503.html

压缩功能
compression algo #启用http协议中的压缩机制,常用算法有gzip deflate compression type #要压缩的类型 ? 示例: ? compression algo gzip ? compression type compression type text/plain text/html text/css text/xml text/javascript application/javascript

配置https
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE crt 后证书文件为PEM格式,且同时包含证书和所有私钥 cat demo.crt demo.key > demo.pem 把80端口的请求重向定443 bind *:80 redirect scheme https if !{ ssl_fc } 向后端传递用户请求的协议和端口(frontend或backend) http_request set-header X-Forwarded-Port %[dst_port] http_request add-header X-Forwared-Proto https if { ssl_fc } #配置示例: frontend https_frontend bind *:443 ssl crt /etc/ssl/certs/servername.pem mode http option httpclose option forwardfor reqadd X-Forwarded-Proto:\ https default_backend web_serverbackend web_server mode http balance roundrobin cookie SERVERID insert indirect nocache server s1 192.168.250.47:80 check cookie s1 server s2 192.168.250.49:80 check cookie s2 注意:这里的pem 文件是下面两个文件合并而成: cat servername.crt servername.key |tee servername.pem#第二种四层转发 frontend https_frontend bind *:443 mode tcp default_backend web_serverbackend web_server mode tcp balance roundrobin stick-table type ip size 200k expire 30m stick on src server s1 192.168.250.47:443 server s2 192.168.250.49:443注意,这种模式下mode 必须是tcp 模式

四层负载IP透传
#在四层负载设备中,把client发送的报文目标地址(原来是负载均衡设备的IP地址),根据均衡设备设置的选择web服务器的规则选择对应的web服务器IP地址,这样client就可以直接跟此服务器建立TCP连接并发送数据。listen web_prot_http_nodes bind 192.168.7.102:80 mode tcp server 192.168.7.102 blogs.studylinux.net:80 send-proxy check inter 3000 fall 3 rise 5 #send-proxyNginx配置: listen 80 proxy_protocol; '"tcp_ip":"$proxy_protocol_addr",' #TCP获取客户端真实IP日志格式

七层负载IP透传
#七层负载均衡服务器起了一个代理服务器的作用,服务器建立一次TCP连接要三次握手,而client要访问webserver要先与七层负载设备进行三次握手后建立TCP连接,把要访问的报文信息发送给七层负载均衡;然后七层负载均衡再根据设置的均衡规则选择特定的webserver,然后通过三次握手与此台webserver建立TCP连接,然后webserver把需要的数据发送给七层负载均衡设备,负载均衡设备再把数据发送给client;所以,七层负载均衡设备起到了代理服务器的作用。listen web_prot_http_nodes bind 192.168.7.102:80 mode http #option forwardfor server 192.168.7.102 blogs.studylinux.net:80 check inter 3000 fall 3 rise 5

heepalived 安装和功能介绍
root@hk-master2:~# apt install -y haproxy root@hk-master1:~# apt install -y haproxy

功能
基于vrrp协议完成地址流动 为vip地址所在的节点生成ipvs规则(在配置文件中预先定义) 为ipvs集群的各RS做健康状态检测 基于脚本调用接口通过执行脚本完成脚本中定义的功能,进而影响集群事务,以此支持nginx、haproxy等服务

环境要求
#个节点时间同步 #关闭selinux #添加防火墙策略/关闭防火墙 firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 \ --in-interface ens0 --destination 192.168.1.114 --protocol vrrp -j ACCEPT success firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 \ --out-interface ens0 --destination 192.168.1.114 --protocol vrrp -j ACCEPT success firewall-cmd --reload success

配置介绍
主配置文件:/etc/keepalived/keepalived.conf 主程序文件:/usr/sbin/keepalived Unit File: ? /usr/lib/systemd/system/keepalived.service (CentOS) ? /lib/systemd/system/keepalived.service (Ubuntu)#配置文件组成部分 TOP HIERACHY GLOBAL CONFIGURATION Global definitionsVRRP CONFIGURATION VRRP instance(s):即一个vrrp虚拟路由器LVS CONFIGURATION Virtual server group(s) Virtual server(s):ipvs集群的vs和rs#配置参数: state MASTER|BACKUP:当前节点在此虚拟路由器上的初始状态,状态为MASTER或者BACKUP interface IFACE_NAME:绑定为当前虚拟路由器使用的物理接口ens32,ens0,bond0,br0 virtual_router_id VRID:当前虚拟路由器惟一标识,范围是0-255 priority 100:当前物理节点在此虚拟路由器中的优先级;范围1-254 advert_int 1:vrrp通告的时间间隔,默认1s authentication { #认证机制 auth_type AH|PASS auth_pass 仅前8位有效 } virtual_ipaddress { #虚拟IP / brd devscopelabel

组播配置
#master : global_defs { notification_email { root@localhost #keepalived 发生故障切换时邮件发送的对象,可以按行区分写多个 } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id ha1.example.com vrrp_skip_check_adv_addr #所有报文都检查比较消耗性能,此配置为如果收到的报文和上一个报文是同一个路由器则跳过检查报文中的源地址 vrrp_strict #严格遵守VRRP协议,不允许状况:1,没有VIP地址,2.单播邻居,3.在VRRP版本2中有IPv6地 址. ? vrrp_garp_interval 0 #ARP报文发送延迟 vrrp_gna_interval 0 #消息发送延迟 vrrp_mcast_group4 224.0.0.18 #默认组播IP地址,224.0.0.0到239.255.255.255 #vrrp_iptables } vrrp_instance VI_1 { state MASTER interface ens0 virtual_router_id 80 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111qwer } virtual_ipaddress { 192.168.7.248 dev ens0 label ens0:0 } } #backup : global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id ha2.example.com vrrp_skip_check_adv_addr # vrrp_strict #严格遵守VRRP协议。 vrrp_garp_interval 0 #ARP报文发送延迟 vrrp_gna_interval 0 #消息发送延迟 vrrp_mcast_group4 224.0.0.18 #组播IP地址,224.0.0.0到239.255.255.255 #vrrp_iptables } vrrp_instance VI_1 { state BACKUP interface ens0 virtual_router_id 80 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 1111qwer } virtual_ipaddress { 192.168.7.248 dev ens0 label ens0:0 } }

非抢占
#设置成双备模式 关闭vip抢占 + nopreempt #hk-master1 vrrp_instance VI_1 { state BACKUP interface ens0 virtual_router_id 80 priority 100 advert_int 1 nopreempt #hk-master2 vrrp_instance VI_1 { state BACKUP interface ens0 virtual_router_id 80 priority 90 advert_int 1 nopreempt

单波配置
unicast_src_ip 本机源IP unicast_peer { 目标主机IP }

通知配置
vim /etc/mail.rc set from=12161xxqq.com set smtp=smtp.qq.com set smtp-auth-user=12161xxqq.com set smtp-auth-password=xxxxxxx set smtp-auth=login set ssl-verify=ignorenopreempt:定义工作模式为非抢占模式 preempt_delay 300:抢占式模式,节点上线后触发新选举操作的延迟时长, 默认模式 定义通知脚本: notify_master |: 当前节点成为主节点时触发的脚本 notify_backup |: 当前节点转为备节点时触发的脚本 notify_fault |: 当前节点转为“失败”状态时触发的脚本 notify |: 通用格式的通知触发机制,一个脚本可完成以上三种状态的转换时的通知

[图片上传失败...(image-79b2d4-1593177183263)]
应用层监控
HTTP_GET|SSL_GET:应用层检测 HTTP_GET|SSL_GET { url { path :定义要监控的URL status_code :判断上述检测机制为健康状态的响应码 } connect_timeout :连接请求的超时时长 nb_get_retry :重试次数 delay_before_retry :重试之前的延迟时长 connect_ip :向当前RS哪个IP地址发起健康状态检测请求 connect_port :向当前RS的哪个PORT发起健康状态检测请求 bindto :发出健康状态检测请求时使用的源地址 bind_port :发出健康状态检测请求时使用的源端口 } #real_server http监测 real_server 192.168.7.103 80 { weight 1 HTTP_GET { url { path /index.html status_code 200 } } connect_timeout 5 nb_get_retry 3 delay_before_retry 3 }3

tcp监控
传输层检测 TCP_CHECK TCP_CHECK { connect_ip :向当前RS的哪个IP地址发起健康状态检测请求 connect_port :向当前RS的哪个PORT发起健康状态检测请求 bindto :发出健康状态检测请求时使用的源地址 bind_port :发出健康状态检测请求时使用的源端口 connect_timeout :连接请求的超时时长 }

脚本监控
分两步:(1) 先定义一个脚本;(2) 调用此脚本 vrrp_script{ script | interval # 间隔时间,单位为秒,默认1秒 timeout # 超时时间 weight # 权重,监测失败后会执行权重+操作 fall #脚本几次失败转换为失败 rise # 脚本连续监测成果后,把服务器从失败标记为成功的次数 user USERNAME [GROUPNAME] # 执行监测的用户或组 init_fail # 设置默认标记为失败状态,监测成功之后再转换为成功状态 }vrrp_instance VI_1 { … track_script { SCRIPT_NAME_1 SCRIPT_NAME_2 } }

配置案例:
#查找配置案例 root@hk-master2:~# find /usr/share/doc/keepalived/ -name keepalived.* /usr/share/doc/keepalived/samples/keepalived.conf.vrrp.routes /usr/share/doc/keepalived/samples/keepalived.conf.fwmark /usr/share/doc/keepalived/samples/keepalived.conf.vrrp.sync /usr/share/doc/keepalived/samples/keepalived.conf.SMTP_CHECK /usr/share/doc/keepalived/samples/keepalived.conf.HTTP_GET.port /usr/share/doc/keepalived/samples/keepalived.conf.vrrp.scripts /usr/share/doc/keepalived/samples/keepalived.conf.SSL_GET /usr/share/doc/keepalived/samples/keepalived.conf.virtual_server_group /usr/share/doc/keepalived/samples/keepalived.conf.virtualhost /usr/share/doc/keepalived/samples/keepalived.conf.vrrp.static_ipaddress /usr/share/doc/keepalived/samples/keepalived.conf.misc_check /usr/share/doc/keepalived/samples/keepalived.conf.vrrp.localcheck /usr/share/doc/keepalived/samples/keepalived.conf.sample /usr/share/doc/keepalived/samples/keepalived.conf.misc_check_arg /usr/share/doc/keepalived/samples/keepalived.conf.IPv6 /usr/share/doc/keepalived/samples/keepalived.conf.quorum /usr/share/doc/keepalived/samples/keepalived.conf.inhibit /usr/share/doc/keepalived/samples/keepalived.conf.track_interface /usr/share/doc/keepalived/samples/keepalived.conf.vrrp.lvs_syncd /usr/share/doc/keepalived/samples/keepalived.conf.vrrp /usr/share/doc/keepalived/samples/keepalived.conf.status_code /usr/share/doc/keepalived/samples/keepalived.conf.vrrp.rules /usr/share/doc/keepalived/keepalived.conf.SYNOPSIS.gz# root@hk-master2:~# vim /etc/keepalived/keepalived.conf #hk-master1与这个配置就routid和优先级不一样其他的都一样! Configuration File for keepalivedglobal_defs { #notification_email { # acassen #} #notification_email_from Alexandre.Cassen@firewall.loc # smtp_server 192.168.200.1 # smtp_connect_timeout 30 router_id LVS_DEVEL_114 }vrrp_instance VI_1 { state BACKUP interface ens33 garp_master_delay 10 #smtp_alert virtual_router_id 51 priority 99 nopreempt advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.200 label ens33:1 } }

haproxy动态上线下线后端服务器
#以上基于hk-master1实现了一个vip-192.168.1.200。 这里基于这个vip做负载均衡配置 #hk-master1: global log /dev/loglocal0 log /dev/loglocal1 notice chroot /var/lib/haproxy nbproc 2 maxconn 65536 stats timeout 30s cpu-map 1 0 cpu-map 2 1 stats socket /run/haproxy/admin.sock1 mode 660 level admin process 1 stats socket /run/haproxy/admin.sock2 mode 660 level admin process 2 nbthread 12 user haproxy group haproxy daemon #ulimit -n 65536defaults logglobal modehttp optionhttplog optiondontlognull timeout connect 5000 timeout client50000 timeout server50000 errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http listen stats mode http bind 192.168.1.113:9999 stats enable log global stats uri /haproxy-status stats auth haadmin:123123listen nginx bind 192.168.1.200:80 mode http server 192.168.1.111 192.168.1.111:80 check inter 2s fall 3 rise 5 server 192.168.1.112 192.168.1.112:80 check inter 2s fall 3 rise 5#升级前下线后端服务器 root@hk-master1:~# cat updatecode.sh #!/bin/bash cpus=`cat /proc/cpuinfo |grep processor |wc -l`for ((i=1; i<=$cpus; i++)); do echo "disable server $1/$2" | socat stdio /run/haproxy/admin.sock$i; done#升级完毕上线后端服务器 root@hk-master1:~# cat percode.sh #!/bin/bash cpus=`cat /proc/cpuinfo |grep processor |wc -l`for ((i=1; i<=$cpus; i++)); do echo "enable server $1/$2" | socat stdio /run/haproxy/admin.sock$i; done

LVS+keepalived 高可用集群 lvs 主要的工作是提供调度算法,把客户端请求按照需求调度在 real 服务器,keepalived 主要的工作是提供 lvs 控制器的一个冗余,并且对 real 服务器做健康检查,发现不健康的 real 服务器,就把它从 lvs 集群中剔除,real 服务器只负责提供服务。
keepalived底层有关于IPVS的功能模块,可以直接在其配置文件中实现LVS的配置,不需要通过ipvsadm命令再单独配置
LVS 负载策略介绍
#IP 负载均衡技术(VS/NAT,VS/TUN,VS/DR): Virtual Server via Network Address Translation(VS/NAT) 通过网络地址转换,调度器重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器;真实服务器的响应报文通过调度器时,报文的源地址被重写,再返回给客户,完成整个负载调度过程。Virtual Server via IP Tunneling(VS/TUN) 采用 NAT 技术时,由于请求和响应报文都必须经过调度器地址重写,当客户请求越来越多时,调度器的处理能力将成为瓶颈。为了解决这个问题,调度器把请求报 文通过 IP 隧道转发至真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。由于一般网络服务应答比请求报文大许多,采用 VS/TUN 技术后,集群系统的最大吞吐量可以提高 10 倍。Virtual Server via Direct Routing(VS/DR) VS/DR 通过改写请求报文的 MAC 地址,将请求发送到真实服务器,而真实服务器将响应直接返回给客户。同 VS/TUN 技术一样,VS/DR 技术可极大地 提高集群系统的伸缩性。这种方法没有 IP 隧道的开销,对集群中的真实服务器也没有必须支持 IP 隧道协议的要求,但是要求调度器与真实服务器都有一块网卡连 在同一物理网段上。

LVS 调度算法
1.轮询:Round Robin,简称rr,分发器按照循环的方式将请求平均的发送给后端的rs2.加权轮询:Weight Round-Robin,简称wrr,增对轮询的优化,会给每台rs定义对应的权重值,权重值大的rs会比权重值小的rs接收到更多分发器转发的请求3.最小连接:Least-Connection,简称lc,分发器向每台rs转发请求时,会记录rs的连接数,根据连接数判断所有rs的情况,将最新的请求转发给连接数最少的rs4.加权最小连接:Weight Least-Connection,简称wlc,增对最小连接的优化,定义每台rs的权重值,分发器将新的请求转发给rs时,会根据权重值判断转发请求给每台rs的比例,分发器可以自动判断rs的情况,动态调整权重值#以上为4中常用调度算法,除此之外还有基于局部性的最小连接、带复制的基于局部性最小连接、目标地址散列调度、源地址散列调度等

LVS NAT模式搭建 测试环境:准备3台机器,1台分发器(dir)和2台rs
dir内网:192.168.1.113 外网:192.168.111.200
rs1内网:192.168.1.111
rs2内网:192.168.1.112
apt install -y iptables #all node systemctl enable iptables --now #all node #设置rs1与rs2的网关为dir的内网ip: root@hk-slave1:/opt# vim /etc/netplan/01-netcfg.yaml root@hk-slave1:/opt# netplan apply root@hk-slave1:/opt# route -n Kernel IP routing table DestinationGatewayGenmaskFlags Metric RefUse Iface 0.0.0.0192.168.1.10.0.0.0UG000 ens33 0.0.0.0192.168.1.1130.0.0.0UG000 ens33 172.17.0.00.0.0.0255.255.0.0U000 docker0 192.168.1.00.0.0.0255.255.255.0U000 ens33 # dir 上创建vip 开启代理后端服务的lvs 模块 root@hk-master1:~# cat/usr/local/sbin/lvs_nat.sh #! /bin/bash # dir上开启路由转发功能 echo 1 > /proc/sys/net/ipv4/ip_forward # 关闭icmp的重定向 echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects echo 0 > /proc/sys/net/ipv4/conf/default/send_redirects # 注意区分网卡名字,两个网卡分别为ens33(内网)和ens37(外网) echo 0 > /proc/sys/net/ipv4/conf/ens33/send_redirects #echo 0 > /proc/sys/net/ipv4/conf/ens37/send_redirects # dir设置nat防火墙 iptables -t nat -F iptables -t nat -X iptables -t nat -A POSTROUTING -s 192.168.1.0/24-j MASQUERADE # 定义ipvsadm路径到变量 IPVSADM='/sbin/ipvsadm' # 清空ipvsadm规则 $IPVSADM -C # 配置lvs,-s 指定调度算法为轮询 $IPVSADM -A -t 192.168.1.200:80 -s rr # -r指定rs1,-w表示模式为nat,-w指定权重值 $IPVSADM -a -t 192.168.1.200:80 -r 192.168.1.111:80 -m -w 1 # 指定rs2 $IPVSADM -a -t 192.168.1.200:80 -r 192.168.1.112:80 -m -w 1 root@hk-master1:~# bash /usr/local/sbin/lvs_nat.sh # 验证代理配置 root@hk-master1:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:PortForward Weight ActiveConn InActConn TCP192.168.1.200:80 rr -> 192.168.1.111:80Masq100 -> 192.168.1.112:80Masq100 #dir 主机 curl 调用虚拟ip 192.168.1.200 root@hk-master1:~# curl 192.168.1.200 192.168.1.112 nginx page root@hk-master1:~# curl 192.168.1.200 192.168.1.111 nginx page root@hk-master1:~# curl 192.168.1.200 192.168.1.112 nginx page root@hk-master1:~# curl 192.168.1.200 192.168.1.111 nginx page root@hk-master1:~#

LVS DR 模式搭建 测试环境:准备3台机器,1台分发器(dir)和2台rs
dir内网:192.168.1.113
rs1内网:192.168.1.111
rs2内网:192.168.1.112
VIP:192.168.1.200
DR模式rs1,与rs2机器的网关不需要配置为dir的ip地址,同样使用iptables工具管理防火墙,也要下载ipvsadm
root@hk-master1:~#iptables -F root@hk-master1:~# ipvsadm -C root@hk-master1:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:PortForward Weight ActiveConn InActConnroot@hk-master1:~# bash /usr/local/sbin/lvs_dr.sh SIOCADDRT: File existsroot@hk-master1:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:PortForward Weight ActiveConn InActConn TCP192.168.1.200:80 rr -> 192.168.1.111:80Route100 -> 192.168.1.112:80Route100root@hk-master1:~# cat /usr/local/sbin/lvs_dr.sh #! /bin/bash # 开启端口转发 echo 1 > /proc/sys/net/ipv4/ip_forward ipv=/sbin/ipvsadm vip=192.168.1.200 rs1=192.168.1.111 rs2=192.168.1.112 # 添加VIP ifconfig ens33:2 $vip broadcast $vip netmask 255.255.255.255 up route add -host $vip dev ens33:2 # 清空ipvsadm规则 $ipv -C # 定义lvs调度算法为轮询 $ipv -A -t $vip:80 -s rr # 指定转发目标rs1,-g表示dr模式,-w定义权重值 $ipv -a -t $vip:80 -r $rs1:80 -g -w 1 # 指定转发目标rs2 $ipv -a -t $vip:80 -r $rs2:80 -g -w 1# rs1和rs2 都执行: root@hk-slave1:/opt# bash /usr/local/sbin/lvs_rs.sh root@hk-slave1:/opt# ip a 1: lo: 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 192.168.1.200/32 brd 192.168.1.200 scope global lo:0 valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/enser 00:0c:29:9f:37:c7 brd ff:ff:ff:ff:ff:ff inet 192.168.1.111/24 brd 192.168.1.255 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe9f:37c7/64 scope link valid_lft forever preferred_lft forever 3: docker0: mtu 1500 qdisc noqueue state DOWN group default link/enser 02:42:d9:b9:ab:13 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:d9ff:feb9:ab13/64 scope link valid_lft forever preferred_lft foreverroot@hk-slave1:/opt# cat /usr/local/sbin/lvs_rs.sh #!/bin/bash netplan apply vip=192.168.1.200 # 把vip绑定在lo上,是为了实现rs直接把结果返回给客户端 ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up route add -host $vip lo:0 # 以下操作为更改arp内核参数,目的是为了让rs顺利发送mac地址给客户端 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

结合keepalive 实现高可用 以上面配置的LVS DR模式为例,使用keepalived+lvs的场景:
1.dir会将收到的请求分发给后端的rs,但是当某台rs宕机的时候,dir不会知道,还会继续分发请求到宕机的rs机器,为了避免该情况出现,可以使用keepalived的避免
#清空规则 root@hk-master1:~# iptables -F root@hk-master1:~# ipvsadm -C #编辑keepalive配置文件 root@hk-master1:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:PortForward Weight ActiveConn InActConn TCP192.168.1.200:80 rr persistent 1 -> 192.168.1.111:80Route10000 -> 192.168.1.112:80Route10000 root@hk-master1:~# vim /etc/keepalived/keepalived.conf root@hk-master1:~# cat /etc/keepalived/keepalived.conf vrrp_instance VI_1 { state BACKUP #绑定vip的网卡 interface ens33 #路由id,需要与backup机器相同 virtual_router_id 51 #定义权重,备用服务器上要小于100 priority 100 advert_int 1 authentication { auth_type PASS auth_pass keepalived123 } virtual_ipaddress { 192.168.1.200 } } virtual_server 192.168.1.200 80 { #每隔10秒查询realserver状态 delay_loop 10 #lvs 算法 lb_algo rr #DR模式 lb_kind DR #同一IP的连续1秒内被分配到同一台rs persistence_timeout 1 #用TCP协议检查rs protocol TCPreal_server 192.168.1.111 80 { #权重 weight 100 TCP_CHECK { #10秒无响应超时 connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.1.112 80 { weight 100 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } }#验证配置 root@hk-master1:~# ip a 1: lo: 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: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/enser 00:0c:29:bb:35:0d brd ff:ff:ff:ff:ff:ff inet 192.168.1.113/24 brd 192.168.1.255 scope global ens33 valid_lft forever preferred_lft forever inet 192.168.1.200/32 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:febb:350d/64 scope link valid_lft forever preferred_lft forever 3: docker0: mtu 1500 qdisc noqueue state DOWN group default link/enser 02:42:c9:56:f7:39 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever root@hk-master1:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:PortForward Weight ActiveConn InActConn TCP192.168.1.200:80 wlc persistent 1 -> 192.168.1.111:80Route10010#浏览器测试 #在rs当中一台服务停的时候会暂时出现访问不了的清空 curl: (7) Failed to connect to 192.168.1.200 port 80: Connection refused root@hk-master2:~# curl 192.168.1.200 curl: (7) Failed to connect to 192.168.1.200 port 80: Connection refused root@hk-master2:~# curl 192.168.1.200 192.168.1.112 nginx page root@hk-master2:~# curl 192.168.1.200

【Haproxy/LVS负载均衡实现+keepalived实现高可用】2.完整的架构dir需要两台,实现高可用,当dir1宕机时,dir2会切换为dir1,接收请求并分发到后端的rs
#配置一台dir的从服务器 scp /etc/keepalived/keepalived.conf 192.168.1.114:/etc/keepalived/ root@hk-master2:~# cat /etc/keepalived/keepalived.conf vrrp_instance VI_1 { state BACKUP #绑定vip的网卡 interface ens33 #路由id,需要与backup机器相同 virtual_router_id 51 #定义权重,备用服务器上要小于100 priority 99 advert_int 1 authentication { auth_type PASS auth_pass keepalived123 } virtual_ipaddress { 192.168.1.200 } } virtual_server 192.168.1.200 80 { #每隔10秒查询realserver状态 delay_loop 10 #lvs 算法 lb_algo wlc #DR模式 lb_kind DR #同一IP的连续1秒内被分配到同一台rs persistence_timeout 1 #用TCP协议检查rs protocol TCPreal_server 192.168.1.111 80 { #权重 weight 100 TCP_CHECK { #10秒无响应超时 connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.1.112 80 { weight 100 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } }#重启 rs 中的一台nginx 测试keepalived root@hk-master1:~# tail -f /var/log/syslog Jun 26 20:55:17 k8s-node3 Keepalived_healthcheckers[46661]: TCP connection to [192.168.1.111]:tcp:80 failed. Jun 26 20:55:17 k8s-node3 Keepalived_healthcheckers[46661]: Check on service [192.168.1.111]:tcp:80 failed after 1 retry. Jun 26 20:55:17 k8s-node3 Keepalived_healthcheckers[46661]: Removing service [192.168.1.111]:tcp:80 to VS [192.168.1.200]:tcp:80 Jun 26 20:56:45 k8s-node3 Keepalived_healthcheckers[46661]: TCP connection to [192.168.1.111]:tcp:80 success. Jun 26 20:56:45 k8s-node3 Keepalived_healthcheckers[46661]: Adding service [192.168.1.111]:tcp:80 to VS [192.168.1.200]:tcp:80 root@hk-master2:~# tail -f /var/log/syslog Jun 26 20:55:15 k8s-node4 Keepalived_healthcheckers[43729]: Check on service [192.168.1.111]:tcp:80 failed after 1 retry. Jun 26 20:55:15 k8s-node4 Keepalived_healthcheckers[43729]: Removing service [192.168.1.111]:tcp:80 to VS [192.168.1.200]:tcp:80 Jun 26 20:56:43 k8s-node4 Keepalived_healthcheckers[43729]: TCP connection to [192.168.1.111]:tcp:80 success. Jun 26 20:56:43 k8s-node4 Keepalived_healthcheckers[43729]: Adding service [192.168.1.111]:tcp:80 to VS [192.168.1.200]:tcp:80#测试 vip 飘逸 root@hk-master1:~# systemctl stop keepalived.service root@hk-master2:~# tail -f /var/log/syslog Jun 26 20:57:36 k8s-node4 Keepalived_vrrp[43730]: VRRP_Instance(VI_1) Transition to MASTER STATE Jun 26 20:57:37 k8s-node4 Keepalived_vrrp[43730]: VRRP_Instance(VI_1) Entering MASTER STATE root@hk-master2:~# ip a 1: lo: 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: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/enser 00:0c:29:0f:45:99 brd ff:ff:ff:ff:ff:ff inet 192.168.1.114/24 brd 192.168.1.255 scope global ens33 valid_lft forever preferred_lft forever inet 192.168.1.200/32 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe0f:4599/64 scope link valid_lft forever preferred_lft forever 3: docker0: mtu 1500 qdisc noqueue state DOWN group default link/enser 02:42:d1:34:f6:db brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever

    推荐阅读