0%

Keepalived+Haproxy高可用怎么玩

一、前言

1.1 Haproxy功能特性

  • HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。
  • HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。
  • Haproxy四层负载。将网络流量负载平衡到多个服务器的最简单方法是使用第4层(传输层)负载平衡。以这种方式进行负载均衡将根据IP范围和端口转发用户流量。(常用作四层,这里就着重介绍四层负载均衡)

1.2 准备工具

  • keepalived(yum安装)
  • haproxy-1.9.8-0.el7.x86_64.rpm(官网下载rpm包)
  • 两台Centos7服务器:192.168.10.1、192.168.10.2(两台主从高可用)
  • VIP虚拟IP: 172.16.20.20(keepalived高可用漂移)

haproxy01.png


二、Haproxy安装配置

2.1 安装依赖

  • SSH登陆第一台服务器192.168.10.1
  • 新增www用户,用于启动haproxy服务
1
2
3
ssh  192.168.10.1
yum install gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel lua-devel GeoIP GeoIP-devel GeoIP-data systemd-devel -y
useradd www -s /sbin/nologin

2.2 安装haproxy

  • 拷贝haproxy-1.9.8-0.el7.x86_64.rpm/root/目录下
1
rpm -ivh  haproxy-1.9.8-0.el7.x86_64.rpm

2.3 配置haproxy.cfg

  • 进入主目录/etc/haproxy/
  • vim haproxy.cfg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice //开启日志用的
user www
group www
maxconn 100000

defaults
mode tcp
retries 3
option tcplog
option redispatch
option abortonclose
#option dontlognull
option log-health-checks //开启后端server健康检查日志输出
option httpclose
balance roundrobin //后端server流量轮询
maxconn 100000
timeout connect 3000
timeout client 3600000
timeout server 3600000

listen status //开启haproxy后台管理页面
bind :1080
mode http
log global
stats enable
stats refresh 30s
stats uri /admin
stats realm HAProxy\ Stats
stats hide-version
stats auth root:123456 //配置账户密码
stats admin if TRUE

#####################
配置两组四层服务案例
#####################
frontend MySQL //定义这个服务的名字为MySQL
bind 172.16.20.20:3306 //监听VIP的3306端口
log global

acl ACL_DB-MYSQL-1 dst 172.16.20.20
use_backend DB-MYSQL-1 if ACL_DB-MYSQL-1

frontend redis //定义这个服务的名字为redis
bind 172.16.20.20:10333 //监听的VIP的10333端口
log global
default_backend redis

backend DB-MYSQL-1
log 127.0.0.1 local0 notice //这行必须加上,否则日志不输出健康检查状态
server 192.168.100.20 192.168.100.21:3306 check inter 1000 rise 3 fall 3
server 192.168.100.21 192.168.100.21:3306 check inter 1000 rise 3 fall 3 backup //状态为备机,只要上面一个服务器挂了,健康检查3秒之后下线,然后备机就顶上了

backend redis
log 127.0.0.1 local0 notice
server 192.168.100.22 192.168.100.22:6379 check inter 1000 rise 3 fall 3

2.4 启动服务

1
2
3
4
5
#验证配置有没有语法错误
/etc/haproxy/sbin/haproxy -c -f /etc/haproxy/haproxy.cfg
Configuration file is valid //出现这个表示配置文件没问题
systemctl start haproxy //启动
systemctl reload haproxy //重新载入配置

三、Keepalived安装配置

3.1 yum安装

1
yum install keepalived  -y

3.2 keepalived配置文件

  • keepalived 采用的是非抢占模式(建议)
  • vim /etc/keepalived/keepalived.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
! Configuration File for keepalived
global_defs {
}
#这是第一个脚本,检测haproxy进程是否存在,不存在则结束keepalived,VIP漂移到备用从服务器,实现高可用
vrrp_script check_haproxy {
script "/etc/keepalived/check_haproxy.sh" //脚本存放路径
}
vrrp_instance VI_1 {
state BACKUP //都定义backup为非抢占模式
nopreempt
interface eth0
virtual_router_id 100
priority 100 //主机器权重为100,从机器要比这小,可以配置90
advert_int 1
unicast_src_ip 192.168.10.1 //本机主IP

unicast_peer {
192.168.10.2 //对端从IP,在从机器上,这两个主从IP是反过来的
}

authentication {
auth_type PASS
auth_pass haproxy //这里可以自定义一个字符串,但两边要保证一致
}
virtual_ipaddress {
172.16.20.20/16 //虚拟IP配置在这里
}
#以下是另外一个脚本,在日志里面打印出keepalived服务状态,
notify_master "/etc/keepalived/notify_action.sh MASTER"
notify_backup "/etc/keepalived/notify_action.sh BACKUP"
notify_fault "/etc/keepalived/notify_action.sh FAULT"
notify_stop "/etc/keepalived/notify_action.sh STOP"
garp_master_delay 1
garp_master_refresh 5

track_script {
check_haproxy //调用上面定义的脚本
}
}

3.3 自定义脚本

3.3.1 haproxy状态检测脚本
  • 此脚本的目的是检测haproxy状态,当haproxy主程序挂掉之后,自动杀掉keepalived进程,把vip漂移到备用从服务器,从而实现高可用
  • vim /etc/keepalived/check_haproxy.sh
1
2
3
4
5
6
#!/bin/bash
#检测nginx进程不存在了,尝试启动,发现启动不了则切换到备用机器
A=`ps -C haproxy --no-header |wc -l`
if [ `ps -C haproxy --no-header |wc -l` -eq 0 ];then
systemctl stop keepalived
fi

3.3.2 Keepalived日志输出状态
  • 这个脚本可选,属于我自己自定义的,没有需要可以跳过,并去掉keepalived配置文件里的引用此脚本部分
  • 此脚本目的就是当keepalived状态发生改变,比如服务停止、启动把定义的状态输出到日志上,以便后续排错
  • vim /etc/keepalived/notify_action.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/bash
#/etc/keepalived/notify_action.sh
log_file=/var/log/keepalived.log
log_write()
{
echo "[`date '+%Y-%m-%d %T'`] $1" >> $log_file
}

[ ! -d /var/keepalived/ ] && mkdir -p /var/keepalived/

case "$1" in
"MASTER" )
echo -n "$1" > /var/keepalived/state
log_write " notify_master"
echo -n "0" > /var/keepalived/vip_check_failed_count
;;

"BACKUP" )
echo -n "$1" > /var/keepalived/state
log_write " notify_backup"
;;

"FAULT" )
echo -n "$1" > /var/keepalived/state
log_write " notify_fault"
;;

"STOP" )
echo -n "$1" > /var/keepalived/state
log_write " notify_stop"
;;
*)
log_write "notify_action.sh: STATE ERROR!!!"
;;
esac

3.3.3 脚本添加权限
1
chmod +x check_haproxy.sh  notify_action.sh

3.4 启动keepalived服务

  • 启动服务后,可以通过ip a查看本机ip是否多了一个虚拟ip:172.16.20.20绑定在上面,这样就算成功了
1
2
systemctl start keepalived   //启动
systemctl reload keepalived //变更配置后,一般用这个命令重新加载

3.4 备用从节点服务器操作注意事项

  • 把上面haproxy安装配置和keepalived安装配置照着完全做一份,操作步骤一样,可以安装好把主服务器上配置文件拷贝过去
  • 唯一的区别就是从服务器的keepalived配置文件有稍微区别需要注意,我直接附上配置
  • vim /etc/keepalived/keepalived.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
! Configuration File for keepalived
global_defs {
}
#这是第一个脚本,检测haproxy进程是否存在,不存在则结束keepalived,VIP漂移到备用从服务器,实现高可用
vrrp_script check_haproxy {
script "/etc/keepalived/check_haproxy.sh" //脚本存放路径
}
vrrp_instance VI_1 {
state BACKUP //都定义backup为非抢占模式
nopreempt
interface eth0
virtual_router_id 100 //此ID号保持一致,同一个局域网最好不要有重复的
priority 90 //主机器权重为100,这里设置90,一定要比主的小
advert_int 1
unicast_src_ip 192.168.10.2 //本机主IP

unicast_peer {
192.168.10.1 //对端从IP
}

authentication {
auth_type PASS
auth_pass haproxy //这里可以自定义一个字符串,但两边要保证一致
}
virtual_ipaddress {
172.16.20.20/16 //虚拟IP配置在这里
}
#以下是另外一个脚本,在日志里面打印出keepalived服务状态,
notify_master "/etc/keepalived/notify_action.sh MASTER"
notify_backup "/etc/keepalived/notify_action.sh BACKUP"
notify_fault "/etc/keepalived/notify_action.sh FAULT"
notify_stop "/etc/keepalived/notify_action.sh STOP"
garp_master_delay 1
garp_master_refresh 5

track_script {
check_haproxy //调用上面定义的脚本
}
}

3.5 验证配置

  • 杀掉主服务器上的haproxy程序,看看keepalived是否也紧跟着同时被杀掉了,虚ip被漂移到备用服务器上了
  • 连接虚拟ip的6379端口以及3306端口,看能否正常转发到后端服务器上
  • 访问haproxy管理页面http://172.16.20.20:1080/admin (root/123456)

四、日志开启及切割

  • keepalivedi日志开启,存储到 /var/log/keepalived.log
  • haproxy开启日志,存储到/var/log/haproxy/haproxy.log
  • 每日0点切割日志压缩保存

4.1 开启keepalived日志

  • vim /etc/sysconfig/keepalived
1
KEEPALIVED_OPTIONS="-D -S 0 -d"
  • vim /etc/rsyslog.conf
1
local0.*  /var/log/keepalived.log
  • service rsyslog restart

4.1 开启Haproxy日志

  • vim /etc/rsyslog.conf
1
2
3
4
vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
local0.* /var/log/haproxy/haproxy.log
  • vim /etc/rsyslog.conf
1
local0.*  /var/log/keepalived.log
  • service rsyslog restart

4.3 切割Haproxy日志

  • 如果不设定时间,切割默认是凌晨3点多执行
  • vim /etc/logrotate.d/logrotate_haproxy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/var/log/haproxy/haproxy.log {
su root root
daily
missingok
rotate 15 //默认我设置的是保留15天
compress
notifempty
create 644 root root
dateext
sharedscripts
postrotate
systemctl restart rsyslog
endscript
}
  • 测试切割:
    logrotate -d /etc/logrotate.d/logrotate_haproxy
  • 强制执行切割:
    /usr/sbin/logrotate -f /etc/logrotate.d/logrotate_haproxy

五、额外补充

5.1 Haproxy管理页面参数介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
haproxy页面参数解释:

页面详细参数解释
Queue
Cur: current queued requests //当前的队列请求数量
Max:max queued requests //最大的队列请求数量
Limit: //队列限制数量
Session rate(每秒的连接回话)列表:
scur: current sessions //每秒的当前回话的限制数量
smax: max sessions //每秒的新的最大的回话量
slim: sessions limit //每秒的新回话的限制数量

Sessions
Total: //总共回话量

Cur: //当前的回话
Max: //最大回话
Limit: //回话限制
Lbtot: total number of times a server was selected //选中一台服务器所用的总时间
Bytes
In: //网络的字节数输入总量
Out: //网络的字节数输出总量

Denied
Req: denied requests//拒绝请求量

Resp:denied responses //拒绝回应
Errors
Req:request errors //错误请求
Conn:connection errors //错误的连接
Resp: response errors (among which srv_abrt) ///错误的回应

Warnings
Retr: retries (warning) //重新尝试
Redis:redispatches (warning) //再次发送
Server列表:
Status:状态,包括up(后端机活动)和down(后端机挂掉)两种状态
LastChk: 持续检查后端服务器的时间
Wght: (weight) : 权重
Act: server is active (server), number of active servers (backend) //活动链接数量
Bck: server is backup (server), number of backup servers (backend) //backup:备份的服务器数量
Down: //后端服务器连接后都是down的数量
Downtime: downtime: total downtime (in seconds) //总的downtime 时间
Throttle: warm up status //设备变热状态

5.2 Haproxy配置文件参数介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
haproxy 配置中分成五部分内容,分别如下:
global:  设置全局配置参数,属于进程的配置,通常是和操作系统相关。
defaults:配置默认参数,这些参数可以被用到frontend,backend,Listen组件;
frontend:接收请求的前端虚拟节点,Frontend可以更加规则直接指定具体使用后端的backend;
backend:后端服务集群的配置,是真实服务器,一个Backend对应一个或者多个实体服务器;
Listen :frontend和backend的组合体。
global # 全局参数的设置
log 127.0.0.1 local0 info
# log语法:log <address_1>[max_level_1] # 全局的日志配置,使用log关键字,指定使用127.0.0.1上的syslog服务中的local0日志设备,记录日志等级为info的日志
user haproxy
group haproxy
# 设置运行haproxy的用户和组,也可使用uid,gid关键字替代之
daemon
# 以守护进程的方式运行
nbproc 16
# 设置haproxy启动时的进程数,根据官方文档的解释,我将其理解为:该值的设置应该和服务器的CPU核心数一致,即常见的2颗8核心CPU的服务器,即共有16核心,则可以将其值设置为:<=16 ,创建多个进程数,可以减少每个进程的任务队列,但是过多的进程数也可能会导致进程的崩溃。这里我设置为16
maxconn 4096
# 定义每个haproxy进程的最大连接数 ,由于每个连接包括一个客户端和一个服务器端,所以单个进程的TCP会话最大数目将是该值的两倍。
#ulimit -n 65536
# 设置最大打开的文件描述符数,在1.4的官方文档中提示,该值会自动计算,所以不建议进行设置
pidfile /var/run/haproxy.pid
# 定义haproxy的pid
defaults # 默认部分的定义
mode http
# mode语法:mode {http|tcp|health} 。http是七层模式,tcp是四层模式,health是健康检测,返回OK
log 127.0.0.1 local3 err
# 使用127.0.0.1上的syslog服务的local3设备记录错误信息
retries 3
# 定义连接后端服务器的失败重连次数,连接失败次数超过此值后将会将对应后端服务器标记为不可用
option httplog
# 启用日志记录HTTP请求,默认haproxy日志记录是不记录HTTP请求的,只记录“时间[Jan 5 13:23:46] 日志服务器[127.0.0.1] 实例名已经pid[haproxy[25218]] 信息[Proxy http_80_in stopped.]”,日志格式很简单。
option redispatch
# 当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;而此时,如果后端的服务器宕掉了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常。
option abortonclose
# 当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
option dontlognull
# 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在监听或开放等动作被称为空连接;官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来
option httpclose
# 这个参数我是这样理解的:使用该参数,每处理完一个request时,haproxy都会去检查http头中的Connection的值,如果该值不是close,haproxy将会将其删除,如果该值为空将会添加为:Connection: close。使每个客户端和服务器端在完成一次传输后都会主动关闭TCP连接。与该参数类似的另外一个参数是“option forceclose”,该参数的作用是强制关闭对外的服务通道,因为有的服务器端收到Connection: close时,也不会自动关闭TCP连接,如果客户端也不关闭,连接就会一直处于打开,直到超时。
contimeout 5000
# 设置成功连接到一台服务器的最长等待时间,默认单位是毫秒,新版本的haproxy使用timeout connect替代,该参数向后兼容
clitimeout 3000
# 设置连接客户端发送数据时的成功连接最长等待时间,默认单位是毫秒,新版本haproxy使用timeout client替代。该参数向后兼容
srvtimeout 3000
# 设置服务器端回应客户度数据发送的最长等待时间,默认单位是毫秒,新版本haproxy使用timeout server替代。该参数向后兼容

listen status # 定义一个名为status的部分
bind 0.0.0.0:1080
# 定义监听的套接字
mode http
# 定义为HTTP模式
log global
# 继承global中log的定义
stats refresh 30s
# stats是haproxy的一个统计页面的套接字,该参数设置统计页面的刷新间隔为30s
stats uri /admin?stats
# 设置统计页面的uri为/admin?stats
stats realm Private lands
# 设置统计页面认证时的提示内容
stats auth admin:password
# 设置统计页面认证的用户和密码,如果要设置多个,另起一行写入即可
stats hide-version
# 隐藏统计页面上的haproxy版本信息

frontend http_80_in # 定义一个名为http_80_in的前端部分
bind 0.0.0.0:80
# http_80_in定义前端部分监听的套接字
mode http
# 定义为HTTP模式
log global
# 继承global中log的定义
option forwardfor
# 启用X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IP
acl static_down nbsrv(static_server) lt 1
# 定义一个名叫static_down的acl,当backend static_sever中存活机器数小于1时会被匹配到
acl php_web url_reg /*.php$
#acl php_web path_end .php
# 定义一个名叫php_web的acl,当请求的url末尾是以.php结尾的,将会被匹配到,上面两种写法任选其一
acl static_web url_reg /*.(css|jpg|png|jpeg|js|gif)$
#acl static_web path_end .gif .png .jpg .css .js .jpeg
# 定义一个名叫static_web的acl,当请求的url末尾是以.css、.jpg、.png、.jpeg、.js、.gif结尾的,将会被匹配到,上面两种写法任选其一
use_backend php_server if static_down
# 如果满足策略static_down时,就将请求交予backend php_server
use_backend php_server if php_web
# 如果满足策略php_web时,就将请求交予backend php_server
use_backend static_server if static_web
# 如果满足策略static_web时,就将请求交予backend static_server

backend php_server #定义一个名为php_server的后端部分
mode http
# 设置为http模式
balance source
# 设置haproxy的调度算法为源地址hash
cookie SERVERID
# 允许向cookie插入SERVERID,每台服务器的SERVERID可在下面使用cookie关键字定义
option httpchk GET /test/index.php
# 开启对后端服务器的健康检测,通过GET /test/index.php来判断后端服务器的健康情况
server php_server_1 10.12.25.68:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2
server php_server_2 10.12.25.72:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1
server php_server_bak 10.12.25.79:80 cookie 3 check inter 1500 rise 3 fall 3 backup
# server语法:server [:port] [param*] # 使用server关键字来设置后端服务器;为后端服务器所设置的内部名称[php_server_1],该名称将会呈现在日志或警报中、后端服务器的IP地址,支持端口映射[10.12.25.68:80]、指定该服务器的SERVERID为1[cookie 1]、接受健康监测[check]、监测的间隔时长,单位毫秒[inter 2000]、监测正常多少次后被认为后端服务器是可用的[rise 3]、监测失败多少次后被认为后端服务器是不可用的[fall 3]、分发的权重[weight 2]、最后为备份用的后端服务器,当正常的服务器全部都宕机后,才会启用备份服务器[backup]

backend static_server
mode http
option httpchk GET /test/index.html
坚持原创技术分享,您的支持将鼓励我继续创作!
-------------本文结束感谢您的阅读-------------