Haproxy安装部署文档及多配置文件管理方案

最近我在负责一个统一接入层的建设项目,涉及到 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 <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,赋可执行权限,如下注册系统服务:

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 管理方案,这个有待继续研究实现,敬请期待

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏依乐祝

Net Core集成Exceptionless分布式日志功能以及全局异常过滤

这篇文章有一部分内容翻译自官方文档,[点我阅读][https://github.com/exceptionless/Exceptionless.Net/wiki...

11320
来自专栏草根专栏

使用Identity Server 4建立Authorization Server (1)

本文内容基本完全来自于Identity Server 4官方文档: https://identityserver4.readthedocs.io/ 官方文档很详...

533100
来自专栏逸鹏说道

直传文件到Azure Storage的Blob服务中

题记:为了庆祝获得微信公众号赞赏功能,忙里抽闲分享一下最近工作的一点心得:如何直接从浏览器中上传文件到Azure Storage的Blob服务中。 为什么 如果...

37370
来自专栏CSDN技术头条

资源控制在大数据和云计算平台中的应用

本文针对大数据平台中资源控制这个层面来详细介绍资源控制在不同操作系统上的具体技术实现,以及大数据平台和资源控制的集成。

64480
来自专栏JadePeng的技术博客

K8S集群安装

主要参考 https://github.com/opsnull/follow-me-install-kubernetes-cluster

73820
来自专栏Felix的技术分享

《一个操作系统的实现》笔记(2)--保护模式

40080
来自专栏Android干货

Android项目实战(二十五):Android studio 混淆+打包+验证是否成功

36170
来自专栏互联网杂技

SpringBoot ( 十二 ) :SpringBoot 如何测试打包部署

有很多网友会时不时的问我,spring boot项目如何测试,如何部署,在生产中有什么好的部署方案吗?这篇文章就来介绍一下spring boot 如何开发、调试...

10220
来自专栏沃趣科技

ASM 翻译系列第三十六弹:ACFS磁盘组的重平衡操作

原作者:Bane Radulovic 译者: 魏兴华 审核: 魏兴华 DBGeeK社区联合出品 原文链接:http://asmsupportguy....

375110
来自专栏程序员同行者

Python程序的打包-上传到pypi

14710

扫码关注云+社区

领取腾讯云代金券