最近我在负责一个统一接入层的建设项目,涉及到 Haproxy 和 ospf 的运维部署,本文分享一下我在部署 Haproxy 之后整理的运维部署规范,并实现了Haproxy 的多配置文件管理方案。
一、部署安装
1、下载源码包
最新 stable 版本下载地址:http://www.haproxy.org/download/1.7/src/haproxy-1.7.9.tar.gz
2、编译安装
1
2
3
4
|
tar zxf haproxy-1.7.9.tar.gz
cd haproxy-1.7.9
make TARGET=linux31 prefix=/usr/local/haproxy
make install PREFIX=/usr/local/haproxy
|
3、创建目录
1
2
3
4
5
6
|
mkdir -p /usr/local/haproxy/conf/ready/tcp
mkdir -p /usr/local/haproxy/conf/ready/http
mkdir -p /usr/local/haproxy/conf/enabled/tcp
mkdir -p /usr/local/haproxy/conf/enabled/http
mkdir -p /usr/local/haproxy/logs
mkdir -p /data/wwwlogs/logs
|
二、软件配置
熟悉 Nginx 和 Apache 的朋友都知道,这两个 Webservice 都支持 include 加载多个配置文件的语法,但是 Haproxy 并不支持!如果现网映射规则非常多,那么 haproxy.cfg 这个配置文件就跟臭袜子一样,又臭又长!
因此,我也是翻遍了国外的各种论坛帖子,终于发现一种变相实现 Haproxy 多配置文件的方案。其实,Hparoxy 是支持多配置文件的,但是不是 include 语法,而是在启动的时候多次使用-f 拼接配置文件,比如:
1
2
|
cd /usr/local/haproxy/sbin
./haproxy -f ../conf/haproxy.cfg -f ../conf/ext1.cfg -f ../conf/ext2.cfg
|
因此,我们可以在配置文件目录以及启动脚本上做点改变,让 Haproxy 支持多配置文件。
1、路径约定:
- 待上线的 tcp 映射规则存放目录:/usr/local/haproxy/conf/ready/tcp
- 待上线的 http 映射规则存放目录:/usr/local/haproxy/conf/ready/http
- 已上线的 tcp 映射规则存放目录:/usr/local/haproxy/conf/enabled/tcp
- 已上线的 http 映射规则存放目录:/usr/local/haproxy/conf/enabled/http
- Ps:本文为多配置模式,enabled 里面的配置为软链接形式,软链接至 ready 对应配置文件,方便管理。
2、配置模板
①、主配置: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
|
#configure haproxy.cfg
global
log 127.0.0.1 local0
maxconn 4096 #最大连接数
chroot /usr/local/haproxy #安装目录
uid 99 #用户nobody
gid 99 #组nobody
daemon #守护进程运行
nbproc 1 #进程数量
pidfile /usr/local/haproxy/logs/haproxy.pid #haproxy pid
defaults
log global
mode http #7层 http;4层tcp 如果要让haproxy支持虚拟主机,mode 必须设为http
option httplog #http 日志格式
log 127.0.0.1 local6
option httpclose #主动关闭http通道
option redispatch #serverId对应的服务器挂掉后,强制定向到其他健康的服务器
retries 1
option dontlognull
maxconn 2000 #最大连接数
timeout connect 3600000 #连接超时(毫秒)
timeout client 3600000 #客户端超时(毫秒)
timeout server 3600000 #服务器超时(毫秒)
frontend default
option httplog
option httpclose
bind 0.0.0.0:80
# 状态页面规则
acl haproxy_stats path_beg /haproxy
use_backend haproxy_stats if haproxy_stats
# 其他
# default_backend default_server
# 提升失败的时候的用户体验
#errorfile 502 /usr/local/haproxy/html/maintain.html
#errorfile 503 /usr/local/haproxy/html/maintain.html
#errorfile 504 /usr/local/haproxy/html/maintain.html
# 状态页面
backend haproxy_stats
stats uri /haproxy
stats enable
stats refresh 60s
#stats auth admin:admin # 状态页面认证配置
stats admin if TRUE
|
②、http 扩展配置文件模板
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
|
frontend demo
option httplog
option httpclose
bind 192.168.1.10:80 # 扩展
# 域名匹配范例
acl is_demo hdr_beg(host) -i demo.oa.com
# 正则范例范例
acl is_demo_rex hdr_reg(host) -i ^demo[0-9].oa.com$
# 路径匹配范例
acl is_demo_path path_beg /demo/path
use_backend demo_oa_com if is_demo || is_demo_rex || is_demo_path
backend http_demo_ext
mode http
# 额外的一些设置,按需使用
option forwardfor
option forwardfor header Client-IP
option http-server-close
option httpclose
#balance roundrobin #负载均衡的方式,轮询方式
#balance leastconn #负载均衡的方式,最小连接
balance source #负载均衡的方式,根据请求的源IP
cookie SERVERID insert nocache indirect # 插入serverid到cookie中,serverid后面可以定义
# 健康检查
option httpchk HEAD /index.html HTTP/1.1\r\nHost:\ demo.oa.com
server x.x.x.x x.x.x.x:80 cookie server1 check inter 2s rise 3 fall 3 weight 3
server x.x.x.x x.x.x.x:80 cookie server1 check inter 2s rise 3 fall 3 weight 3
|
③、tcp 扩展配置文件模板
1
2
3
4
5
|
listen tcp_demo_ext
bind 0.0.0.0:3306
mode tcp
server x.x.x.x x.x.x.x:3306 weight 1 check inter 1s rise 2 fall 2
server x.x.x.x x.x.x.x:3306 weight 1 check inter 1s rise 2 fall 2
|
Ps:多配置模式中,多个 frontend 必须绑定不同的 IP 或者端口,否则数据会串,导致映射到不同的后端而报错。因此,同一个 IP+端口下的映射务必配置到同一个 frontend 模块内。
三、系统服务
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
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
#!/bin/bash
###################################################################
# Haproxy Service Script 1.0.0 Author: Jager <ge@zhangge.net> #
# Common Operations(start|stop|restart|mon|test) #
#-----------------------------------------------------------------#
# For more information please visit http://zhangge.net/5125.html #
# Copyright @2017 zhangge.net. All rights reserved. #
###################################################################
# chkconfig: 35 10 90
export PATH=/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:$PATH
PROCESS_NAME=haproxy
BASE_DIR=/usr/local/haproxy
EXEC=$BASE_DIR/sbin/haproxy
PID_FILE=$BASE_DIR/logs/haproxy.pid
DEFAULT_CONF=$BASE_DIR/conf/haproxy.cfg
MONLOG_PATH="$BASE_DIR/logs/${PROCESS_NAME}_mon.log"
# COLOR print
COLOR_RED=$( echo -e "\e[31;49m" )
COLOR_GREEN=$( echo -e "\e[32;49m" )
COLOR_RESET=$( echo -e "\e[0m" )
info() { echo "${COLOR_GREEN}$*${COLOR_RESET}" ;}
warn() { echo "${COLOR_RED}$*${COLOR_RESET}" ;}
do_log()
{
local log_fpath=$1
local log_content=$2
echo "$(date '+%F %T') $log_content" >> $log_fpath
}
print_usage()
{
echo
info " Usage: $(basename $0) [start|stop|restart|mon|test]"
echo
}
#get Expanding configuration
ext_configs()
{
CONFIGS=
if [[ -d $BASE_DIR/conf/enabled ]];then
for FILE in $(find $BASE_DIR/conf/enabled -type l | sort -n)
do
CONFIGS="$CONFIGS -f $FILE";
done
echo $CONFIGS
else
echo
fi
}
# check process status
check_process()
{
PID=`get_pid`
if ps aux | awk '{print $2}' | grep -qw $PID 2>/dev/null ;then
true
else
false
fi
}
# check Configuration file
check_conf()
{
$EXEC -c -f $DEFAULT_CONF `ext_configs` >/dev/null 2>&1
return $?
}
get_pid()
{
if [[ -f $PID_FILE ]];then
cat $PID_FILE
else
warn " $PID_FILE not found!"
exit 1
fi
}
start()
{
echo
if check_process;then
warn " ${PROCESS_NAME} is already running!"
else
$EXEC -f $DEFAULT_CONF `ext_configs` && \
echo -e " ${PROCESS_NAME} start [ `info OK` ]" || \
echo -e " ${PROCESS_NAME} start [ `warn Failed` ]"
fi
echo
}
stop()
{
echo
if check_process;then
PID=`get_pid`
kill -9 $PID >/dev/null 2>&1
echo -e " ${PROCESS_NAME} stop [ `info OK` ]"
else
warn " ${PROCESS_NAME} is not running!"
fi
echo
}
restart()
{
echo
if check_process;then
:
else
warn " ${PROCESS_NAME} is not running! Starting Now..."
fi
if `check_conf`;then
PID=`get_pid`
$EXEC -f $DEFAULT_CONF `ext_configs` -st $PID && \
echo -e " ${PROCESS_NAME} restart [ `info OK` ]" || \
echo -e " ${PROCESS_NAME} restart [ `warn Failed` ]"
else
warn " ${PROCESS_NAME} Configuration file is not valid, plz check!"
echo -e " ${PROCESS_NAME} restart [ `warn Failed` ]"
fi
echo
}
mon()
{
if check_process;then
info "${PROCESS_NAME} is running OK!"
do_log $MONLOG_PATH "${PROCESS_NAME} is running OK!"
else
start
warn " ${PROCESS_NAME} not running, start it!"
do_log $MONLOG_PATH "${PROCESS_NAME} not running, plz check"
fi
}
if [[ $# != 1 ]]; then
print_usage
exit 1
else
case $1 in
"start"|"START")
start
;;
"stop"|"STOP")
stop
;;
"restart"|"RESTART"|"-r")
restart
;;
"status"|"STATUS")
if check_process;then
info "${PROCESS_NAME} is running OK!"
else
warn " ${PROCESS_NAME} not running, plz check"
fi
;;
"test"|"TEST"|"-t")
echo
if check_conf ;then
info " Configuration file test Successfully."
else
warn " Configuration file test failed."
fi
echo
;;
"mon"|"MON"|"-m")
mon
;;
*)
print_usage
exit 1
esac
fi
|
保存为 /usr/local/haproxy/sbin/ctrl.sh,赋可执行权限,如下注册系统服务:
1
2
3
|
chmod +x /usr/local/haproxy/sbin/ctrl.sh
ln -sf /usr/local/haproxy/sbin/ctrl.sh /etc/init.d/haproxy
chkconfig haproxy on
|
服务控制:
1
2
3
4
5
6
|
启动:service haproxy start
停止:service haproxy stop
重载:service haproxy restart
状态:service haproxy status
检查:service haproxy test
监控:service haproxy mon # 进程自拉起,如有告警通道可自行加入
|
2、配置自拉起
1
|
* * * * * bash /usr/local/haproxy/ctrl.sh mon >/dev/null 2>&1
|
全部完成后,最终目录结构如下:
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
|
[root@locahost:/usr/local/haproxy]# tree
.
├── conf
│ ├── enabled # 正式使用的拓展配置
│ │ ├── http
│ │ │ └── demo.cfg -> /usr/local/haproxy/conf/ready/http/demo.cfg# 此处软链到可以上线的配置
│ │ └── tcp
│ │ └── demo.cfg -> /usr/local/haproxy/conf/ready/tcp/demo.cfg
│ ├── haproxy.cfg
│ └── ready # 存在预发布的拓展配置
│ ├── http
│ │ └── demo.cfg
│ │ └── other.cfg
│ └── tcp
│ └── demo.cfg
│ └── other.cfg
├── doc
│ .....
├── logs
│ └── haproxy.pid
├── sbin
│ ├── ctrl.sh
│ └── haproxy
└── share
└─...
14 directories, 24 files
|
四、日志配置
配置 rsyslog
1
2
3
4
5
6
7
8
9
10
11
12
|
mkdir -p /data/wwwlogs
vim /etc/rsyslog.conf 或 /etc/syslog.conf
#新增配置
local6.* /data/wwwlogs/haproxy.log
#取消如下2行注释
$ModLoad imudp
$UDPServerRun 514
#重启syslog服务
service rsyslog restart
|
五、小结
以上内容就是我对 Haproxy 部署规范的整理,并通过拼接方式变相实现了 Haproxy 的多配置文件管理。当然,略遗憾的是未能实现 Haproxy 的 WEB 管理方案,这个有待继续研究实现,敬请期待!