最近我在负责一个统一接入层的建设项目,涉及到 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 ################################################################### # Haproxy Service Script 1.0.0 Author: Jager <[email protected]> # # 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() { 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,赋可执行权限,如下注册系统服务:
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
全部完成后,最终目录结构如下:
[[email protected]:/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 管理方案,这个有待继续研究实现,敬请期待!
谢谢博主分享,学习到了
张大官人,最近忙啥捏,好久没有来本店坐坐了! :lol:
今日终于赶上更新了,输入的时候一震一震的,我还以为是地震了呢。
看的不是很明白!有点笨
1.Haproxy的进程数可以优化,提高性能;
2.Haproxy的WEB管理方案,可以考虑etcd
哇,锋哥亲自指点,受宠若惊了。
进程数方面有点争议,现网生产环境发现开2个进程以上,进行压测会出现问题,单个进程却没有问题,待深究下。
恩,目前已经在测试etcd+confd的解决方案了。
还有一点。frontend 可配置如下:
frontend http_server
bind :80
bind :443 ssl crt XXX.pem
恩,作为模板得补充下,不过我们这边内部还没实现https