最近我在负责一个统一接入层的建设项目,涉及到Haproxy和ospf的运维部署,本文分享一下我在部署Haproxy之后整理的运维部署规范,并实现了Haproxy的多配置文件管理方案。
一、部署安装
1、下载源码包
最新stable版本下载地址:http://www.haproxy.org/download/1.7/src/haproxy-1.7.9.tar.gz
2、编译安装
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、创建目录
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 拼接配置文件,比如:
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
#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 扩展配置文件模板
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 扩展配置文件模板
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脚本,我编写的时候新增了如下实用功能:
- 支持配置文件语法测试
- 支持进程的监控(自拉起)功能
- 重启之前会先检测配置语法,规避因配置错误导致重启后进程挂掉
- 支持多配置文件模式(按照前文约定目录存放拓展配置,脚本将自动识别)
下面是服务脚本代码:
#!/bin/bash
###################################################################
# Common Operations(start|stop|restart|mon|test) #
#-----------------------------------------------------------------#
# For more information please visit https://zhang.ge/5125.html #
# Copyright @2017 zhang.ge. 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()
info " Usage: $(basename $0) [start|stop|restart|mon|test]"
#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)
CONFIGS="$CONFIGS -f $FILE";
echo $CONFIGS
# check process status
check_process()
PID=`get_pid`
if ps aux | awk '{print $2}' | grep -qw $PID 2>/dev/null ;then
false
# 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
warn " $PID_FILE not found!"
exit 1
start()
if check_process;then
warn " ${PROCESS_NAME} is already running!"
$EXEC -f $DEFAULT_CONF `ext_configs` && \
echo -e " ${PROCESS_NAME} start [ `info OK` ]" || \
echo -e " ${PROCESS_NAME} start [ `warn Failed` ]"
stop()
if check_process;then
PID=`get_pid`
kill -9 $PID >/dev/null 2>&1
echo -e " ${PROCESS_NAME} stop [ `info OK` ]"
warn " ${PROCESS_NAME} is not running!"
restart()
if check_process;then
warn " ${PROCESS_NAME} is not running! Starting Now..."
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` ]"
warn " ${PROCESS_NAME} Configuration file is not valid, plz check!"
echo -e " ${PROCESS_NAME} restart [ `warn Failed` ]"
mon()
if check_process;then
info "${PROCESS_NAME} is running OK!"
do_log $MONLOG_PATH "${PROCESS_NAME} is running OK!"
start
warn " ${PROCESS_NAME} not running, start it!"
do_log $MONLOG_PATH "${PROCESS_NAME} not running, plz check"
if [[ $# != 1 ]]; then
print_usage
exit 1
case $1 in
"start"|"START")
start
"stop"|"STOP")
"restart"|"RESTART"|"-r")
restart
"status"|"STATUS")
if check_process;then
info "${PROCESS_NAME} is running OK!"
warn " ${PROCESS_NAME} not running, plz check"
"test"|"TEST"|"-t")
if check_conf ;then
info " Configuration file test Successfully."
warn " Configuration file test failed."
"mon"|"MON"|"-m")
print_usage
exit 1
保存为 /usr/local/haproxy/sbin/ctrl.sh,赋可执行权限,如下注册系统服务:
chmod +x /usr/local/haproxy/sbin/ctrl.sh
ln -sf /usr/local/haproxy/sbin/ctrl.sh /etc/init.d/haproxy
chkconfig haproxy on
服务控制:
启动:service haproxy start
停止:service haproxy stop
重载:service haproxy restart
状态:service haproxy status
检查:service haproxy test
监控:service haproxy mon # 进程自拉起,如有告警通道可自行加入
2、配置自拉起
* * * * * bash /usr/local/haproxy/ctrl.sh mon >/dev/null 2>&1
全部完成后,最终目录结构如下:
[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
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管理方案,这个有待继续研究实现,敬请期待!