最近我在负责一个统一接入层的建设项目,涉及到 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.1rnHost: 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 管理方案,这个有待继续研究实现,敬请期待!