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.113 hk-master1
192.168.1.114 hk-master2
192.168.1.111 hk-slave1
192.168.1.112 hk-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 [<name>] #默认配置项,针对以下的frontend、backend和lsiten生效,可以多个name
• frontend <name> #前端servername,类似于Nginx的一个虚拟主机 server。 • backend <name> #后端服务器组,等于nginx的upstream
• listen <name> #将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 <maxconn>:当前后端server的最大并发连接数
• backlog <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中的<params>部分中的参数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,此处由<name>指定的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 <delay> # 设定自动刷新时间间隔
stats uri <prefix> #自定义stats page uri,默认值:/haproxy?stats
stats realm <realm> #账户认证时的提示信息,示例:stats realm : HAProxy\ Statistics
stats auth <user>:<passwd> #认证时的账号和密码,可使用多次,默认:no authentication
stats admin { if | unless } <cond> #启用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.html
errorloc 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_server
backend 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_server
backend 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-proxy
Nginx配置:
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 ens33--destination 192.168.1.114 --protocol vrrp -j ACCEPT
success
firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 \
--out-interface ens33--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 definitions
VRRP 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,ens33,bond0,br0
virtual_router_id VRID:当前虚拟路由器惟一标识,范围是0-255
priority 100:当前物理节点在此虚拟路由器中的优先级;范围1-254
advert_int 1:vrrp通告的时间间隔,默认1s
authentication { #认证机制
auth_type AH|PASS
auth_pass <PASSWORD> 仅前8位有效
}
virtual_ipaddress { #虚拟IP
<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
192.168.200.17/24 dev eth1
192.168.200.18/24 dev eth2 label eth2:1
}
track_interface { #配置监控网络接口,一旦出现故障,则转为FAULT状态实现地址转移
ens33
ens37
…
}
组播配置
#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 ens33
virtual_router_id 80
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111qwer
}
virtual_ipaddress {
192.168.7.248 dev ens33 label ens33: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 ens33
virtual_router_id 80
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111qwer
}
virtual_ipaddress {
192.168.7.248 dev ens33 label ens33:0
}
}
非抢占
#设置成双备模式 关闭vip抢占 + nopreempt
#hk-master1
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 80
priority 100
advert_int 1
nopreempt
#hk-master2
vrrp_instance VI_1 {
state BACKUP
interface ens33
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=ignore
nopreempt:定义工作模式为非抢占模式
preempt_delay 300:抢占式模式,节点上线后触发新选举操作的延迟时长,
默认模式
定义通知脚本:
notify_master <STRING>|<QUOTED-STRING>:
当前节点成为主节点时触发的脚本
notify_backup <STRING>|<QUOTED-STRING>:
当前节点转为备节点时触发的脚本
notify_fault <STRING>|<QUOTED-STRING>:
当前节点转为“失败”状态时触发的脚本
notify <STRING>|<QUOTED-STRING>:
通用格式的通知触发机制,一个脚本可完成以上三种状态的转换时的通知
![image-20200626143900396](C:\Users\HZY\Documents\Mkdown_Note\haproxy+keepalived 集群高可用集群转发\image-20200626143900396.png)
应用层监控
HTTP_GET|SSL_GET:应用层检测
HTTP_GET|SSL_GET {
url {
path <URL_PATH>:定义要监控的URL
status_code <INT>:判断上述检测机制为健康状态的响应码
}
connect_timeout <INTEGER>:连接请求的超时时长
nb_get_retry <INT>:重试次数
delay_before_retry <INT>:重试之前的延迟时长
connect_ip <IP ADDRESS>:向当前RS哪个IP地址发起健康状态检测请求
connect_port <PORT>:向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS>:发出健康状态检测请求时使用的源地址
bind_port <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 <IP ADDRESS>:向当前RS的哪个IP地址发起健康状态检测请求
connect_port <PORT>:向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS>:发出健康状态检测请求时使用的源地址
bind_port <PORT>:发出健康状态检测请求时使用的源端口
connect_timeout <INTEGER>:连接请求的超时时长
}
脚本监控
分两步:(1) 先定义一个脚本;(2) 调用此脚本
vrrp_script <SCRIPT_NAME> {
script <STRING>|<QUOTED-STRING>
interval <INTEGER> # 间隔时间,单位为秒,默认1秒
timeout <INTEGER> # 超时时间
weight <INTEGER:-254..254> # 权重,监测失败后会执行权重+操作
fall <INTEGER> #脚本几次失败转换为失败
rise <INTEGER> # 脚本连续监测成果后,把服务器从失败标记为成功的次数
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 keepalived
global_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/log local0
log /dev/log local1 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 65536
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
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:123123
listen 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,分发器按照循环的方式将请求平均的发送给后端的rs
2.加权轮询:Weight Round-Robin,简称wrr,增对轮询的优化,会给每台rs定义对应的权重值,权重值大的rs会比权重值小的rs接收到更多分发器转发的请求
3.最小连接:Least-Connection,简称lc,分发器向每台rs转发请求时,会记录rs的连接数,根据连接数判断所有rs的情况,将最新的请求转发给连接数最少的rs
4.加权最小连接: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
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 ens33
0.0.0.0 192.168.1.113 0.0.0.0 UG 0 0 0 ens33
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 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:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.200:80 rr
-> 192.168.1.111:80 Masq 1 0 0
-> 192.168.1.112:80 Masq 1 0 0
#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:Port Forward Weight ActiveConn InActConn
root@hk-master1:~# bash /usr/local/sbin/lvs_dr.sh
SIOCADDRT: File exists
root@hk-master1:~# 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.1.200:80 rr
-> 192.168.1.111:80 Route 1 0 0
-> 192.168.1.112:80 Route 1 0 0
root@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: <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
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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 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: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 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 forever
root@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:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.200:80 rr persistent 1
-> 192.168.1.111:80 Route 100 0 0
-> 192.168.1.112:80 Route 100 0 0
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 TCP
real_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: <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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 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: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 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:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.200:80 wlc persistent 1
-> 192.168.1.111:80 Route 100 1 0
#浏览器测试
#在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
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 TCP
real_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: <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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 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: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 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