使用 Haproxy + Keepalived 构建基于 Docker 的高可用负载均衡服务(一)

适合具有 Docker 和 Bash 相关基础的开发、运维等同学。本文没有太过深入的介绍,也并没有用到一些高级特性,仅适合用来作为一个基础科普文来阅读。

背景

最近在搭新的 Coding 内部测试环境,老大说把以前使用 nginx 插件来做的 LB(Load balancing) 全部换成 HAProxy 来做。经过几天的不断“查阅资料”,简单实现了该服务的动态构建。

本文循序渐进按照以下几个层次来讲:

  • HAProxy 与 Keepalived 的简单介绍
    • HAProxy 介绍

    • Keepalived 介绍

  • 搭建 haproxy + keepalived 服务过程

    • 搭建业务服务

    • 使用 HAProxy 做业务服务的高可用和负载均衡

    • 使用 Keepalived 做 HAProxy 服务的高可用

环境准备:

  • 五台 Linux 主机

未分类

  • 一个虚拟的 IP

192.168.0.146(一个内网没人用的 IP)

HAProxy 与 Keepalived 简单介绍

HAProxy 是一个提供高可用、负载均衡和基于 HTTP/TCP 应用代理的解决方案。

Keepalived 是用 C 编写的路由软件,主要目标是为 Linux 系统及基于 Linux 的设施提供强大的高可用性和负载均衡。

在本文中,HAProxy 我们用来做 HTTP/TCP 应用的 HA + LB 方案,Keepalived 被用来做 HAProxy 的 HA 方案。下边是对两者的简单介绍和简单使用。

HAProxy

关于 HAProxy 的一些概念限于篇幅的原因不再详细说了,可以参考这篇文章: https://www.digitalocean.com/community/tutorials/an-introduction-to-haproxy-and-load-balancing-concepts

下边仅会介绍我们会使用到的一些概念。

HAProxy 的 Proxy 配置可以分为如下几个部分( http://cbonte.github.io/haproxy-dconv/1.7/configuration.html#4 ):

  • defaults []
  • frontend
  • backend
  • listen

其中 defaults 包含一些全局的默认环境变量,frontend 定义了如何把数据 forward 到 backend,backend 描述了一组接收 forward 来的数据的后端服务。listen 则把 frontend 和 backend 组合到了一起,定义出了一个完整的 proxy。

未分类

下面是一段简单的 HAProxy 的配置:

listen app1-cluster
    bind *:4000
    mode http
    maxconn 300
    balance roundrobin
    server server1 192.168.0.189:4004 maxconn 300 check
    server server2 192.168.0.190:4004 maxconn 300 check
    server server3 192.168.0.191:4004 maxconn 300 check

listen app2-cluster
    bind *:5000
    mode http
    maxconn 300
    balance roundrobin
    server server1 192.168.0.189:5555 maxconn 300 check
    server server2 192.168.0.190:5555 maxconn 300 check
    server server3 192.168.0.191:5555 maxconn 300 check

我们在 HAProxy 的配置文件中定义了两个 listen 模块,分别监听在 4000、5000 端口。监听在 4000 端口的模块,使用 roundrobin (轮询)负载均衡算法,把请求分发到了三个后端服务。

Keepalived

关于 Keepalived 的详细介绍可以参考: http://keepalived.readthedocs.io/en/latest/introduction.html

Keepalived 是一个用于负载均衡和高可用的路由软件。

其负载均衡(Load balancing)的特性依赖于 Linux 虚拟服务器(LVS)的 IPVS 内核模块,提供了 Layer 4 负载均衡器(TCP 层级,Layer 7 是 HTTP 层级,即计算机网络中的OSI 七层网络模型与 TCP/IP 四层网络模型)。

Keepalived 实现了虚拟冗余路由协议(VRRP, Virtual Redundancy Routing Protoco),VRRP 是路由故障切换(failover)的基础。

简单来说,Keepalived 主要提供两种功能:

  • 依赖 IPVS 实现服务器的健康检查;
  • 实现 VRRPv2 协议来处理路由的故障切换。

我们接下来会用个简单的配置来描述后者的工作原理:

在 haproxy-master 机器上:

vrrp_script chk_haproxy {
    script "killall -0 haproxy" # verify haproxy's pid existance
    interval 2 # check every 2 seconds
    weight -2 # if check failed, priority will minus 2
}

vrrp_instance VI_1 {
    state MASTER # Start-up default state
    interface ens18 # Binding interface
    virtual_router_id 51 # VRRP VRID(0-255), for distinguish vrrp's multicast
    priority 105 # VRRP PRIO
    virtual_ipaddress { # VIP, virtual ip
        192.168.0.146
    }
    track_script { # Scripts state we monitor
        chk_haproxy              
    }
}

在 haproxy-backup 机器上:

vrrp_script chk_haproxy {
   script "killall -0 haproxy"
    interval 2
    weight -2
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens18
    virtual_router_id 51
    priority 100
    virtual_ipaddress {
        192.168.0.146
    }
    track_script {             
        chk_haproxy              
    }
}

我们为两台机器(master、backup)安装了 Keepalived 服务并设定了上述配置。

可以发现,我们绑定了一个虚拟 IP (VIP, virtual ip): 192.168.0.146,在 haproxy-master + haproxy-backup 上用 Keepalived 组成了一个集群。在集群初始化的时候,haproxy-master 机器的 被初始化为 MASTER。

间隔 2 seconds() 会定时执行 <script>脚本 ,每个 会记录脚本的 exit code。

关于 参数的使用:

  • 检测失败,并且 weight 为正值:无操作
  • 检测失败,并且 weight 为负值:priority = priority – abs(weight)
  • 检测成功,并且 weight 为正值:priority = priority + weight
  • 检测成功,并且 weight 为负值:无操作

weight 默认值为 0,对此如果感到迷惑可以参考:HAProxy github code

故障切换工作流程:

  • 当前的 MASTER 节点 <script> 脚本检测失败后,如果“当前 MASTER 节点的 priority” < “当前 BACKUP 节点的 priority” 时,会发生路由故障切换。
  • 当前的 MASTER 节点脚本检测成功,无论 priority 是大是小,不会做故障切换。

其中有几处地方需要注意:

  • 一个 Keepalived 服务中可以有个 0 个或者多个 vrrp_instance
  • 可以有多个绑定同一个 VIP 的 Keepalived 服务(一主多备),本小节中只是写了两个
  • 注意 ,同一组 VIP 绑定的多个 Keepalived 服务的 必须相同;多组 VIP 各自绑定的 Keepalived 服务一定与另外组不相同。否则前者会出现丢失节点,后者在初始化的时候会出错。

关于 Keepalived 各个参数代表含义的问题,可以同时参考下文与 Github 代码文档来看:

  • keepalived工作原理和配置说明: http://outofmemory.cn/wiki/keepalived-configuration

  • Github keepalived.conf.SYNOPSIS: https://github.com/acassen/keepalived/blob/master/doc/keepalived.conf.SYNOPSIS

搭建 haproxy + keepalived 服务过程

搭建业务服务

我们在 host-1、host-2、host-3 三台机器上,每台机器的 4004、5555 端口分别启起来一个服务,服务打印一段字符串,用来模拟业务集群中的三个实例。

如下所示:

  • 192.168.0.189/host-1

4004 端口:

未分类

5555 端口:

未分类

  • 192.168.0.190/host-2

4004 端口:

未分类

5555 端口:

未分类

  • 192.168.0.191/host-3

4004 端口:

未分类

5555 端口:

未分类

如上所示,我们在三台机器上搭建了两个集群,结构如下图所示:

未分类

使用 HAProxy 做业务服务的高可用和负载均衡

我们现在有两台机器:haproxy-master、haproxy-backup,本小节的目标是在这两台机器上分别搭一套相同的 HAProxy 服务。(为了方便,下边直接用 Docker 做了)

我们直接使用了 haproxy:1.7.9 版本的 Docker 镜像,下边是具体的步骤:

coding@haproxy-master:~/haproxy$ tree .
.
├── Dockerfile
└── haproxy.cfg

0 directories, 2 files

coding@haproxy-master:~/haproxy$ cat Dockerfile
FROM haproxy:1.7.9

COPY haproxy.cfg /usr/local/etc/haproxy/

coding@haproxy-master:~/haproxy$ cat haproxy.cfg
global
    daemon
    maxconn 30000
    log 127.0.0.1 local0 info
    log 127.0.0.1 local1 warning

defaults
    mode http
    option http-keep-alive
    option httplog
    timeout connect 5000ms
    timeout client 10000ms
    timeout server 50000ms
    timeout http-request 20000ms

#  custom your own frontends && backends && listen conf
# CUSTOM

listen app1-cluster
    bind *:4000
    mode http
    maxconn 300
    balance roundrobin
    server server1 192.168.0.189:4004 maxconn 300 check
    server server2 192.168.0.190:4004 maxconn 300 check
    server server3 192.168.0.191:4004 maxconn 300 check

listen app2-cluster
    bind *:5000
    mode http
    maxconn 300
    balance roundrobin
    server server1 192.168.0.189:5555 maxconn 300 check
    server server2 192.168.0.190:5555 maxconn 300 check
    server server3 192.168.0.191:5555 maxconn 300 check

listen stats
    bind *:1080
    stats refresh 30s
    stats uri /stats

在完成上述代码后,我们可以构建我们自己的 Docker 镜像,并运行它:

coding@haproxy-master:~/haproxy$ docker build -t custom-haproxy:1.7.9 .
Sending build context to Docker daemon 3.584kB
Step 1/2 : FROM haproxy:1.7.9
1.7.9: Pulling from library/haproxy
85b1f47fba49: Pull complete
3dee1a596b5f: Pull complete
259dba5307a2: Pull complete
9d51568f5880: Pull complete
d2c6077a1eb7: Pull complete
Digest: sha256:07579aed81dc9592a3b7697d0ea116dea7e3dec18e29f1630bc2c399f46ada8e
Status: Downloaded newer image for haproxy:1.7.9
 ---> 4bb854517f75
Step 2/2 : COPY haproxy.cfg /usr/local/etc/haproxy/
 ---> 4e846d42d719
Successfully built 4e846d42d719
Successfully tagged custom-haproxy:1.7.9

coding@haproxy-master:~/haproxy$ docker run -it --net=host --privileged --name haproxy-1 -d custom-haproxy:1.7.9
fb41ab81d2140af062708e5b84668b7127014eb9ae274e4c2761d06e2f6d7950

通过命令 docker ps -a 我们可以看到,容器已经正常运行了,接下来我们在 web 端打开相应的地址可以看到所有服务的状态:

未分类

我们刚才在 haproxy-master 机器上搭建了一个 haproxy 服务,在其 4000、5000 端口绑定了两个业务集群。我们在浏览器访问:http://192.168.0.144:4000/、http://192.168.0.144:5000/ ,并且重复刷新即可看到会打印不同的 JSON 出来。可以证明我们请求确实是分发到了业务集群的几个实例中。

接下来,还要在 haproxy-backup 上搭建一个一模一样的 HAProxy 服务,步骤同上。

使用 Keepalived 做 HAProxy 服务的高可用

在上一小节中,我们在 haproxy-master、haproxy-backup 两台机器上搭了两套相同的 HAProxy 服务。我们希望在一个连续的时间段,只由一个节点为我们提供服务,并且在这个节点挂掉后另外一个节点能顶上。

本小节的目标是在haproxy-master、haproxy-backup 上分别搭 Keepalived 服务,并区分主、备节点,以及关停掉一台机器后保证 HAProxy 服务仍然正常运行。

使用如下命令安装 Keepalived:

coding@haproxy-master:~$ sudo apt-get install keepalived
coding@haproxy-master:~/haproxy$ keepalived -v
Keepalived v1.2.19 (03/13,2017)

我们在 haproxy-master 机器上,增加如下配置:

coding@haproxy-master:~$ cat /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy {
    script "killall -0 haproxy"
    interval 2                   
}

vrrp_instance VI_1 {
    state MASTER                 
    interface ens18              
    virtual_router_id 51        
    priority 105                
    virtual_ipaddress {         
        192.168.0.146
    }
    track_script {
        chk_haproxy
    }
}

在 haproxy-backup 机器上增加如下配置:

coding@haproxy-backup:~$ cat /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy {
    script "killall -0 haproxy"
    interval 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens18
    virtual_router_id 51
    priority 100
    virtual_ipaddress {
        192.168.0.146
    }
    track_script {
        chk_haproxy
    }
}

在配置结束之后,我们分别重启两台机器上的 Keepalived 服务:

oot@haproxy-master:~# systemctl restart keepalived

(注:不同的发行版命令不同,本文基于 Ubuntu 16.04)

此时我们的 Keepalived 服务就搭建完成了,VIP 是 192.168.0.146。此时我们通过浏览器访问:http://192.168.0.146:1080/stats,即可看到 HAProxy 服务的状态。

我们也可以通过 ssh [email protected] 看目前 MASTER 节点为哪台机器。ssh 后发现目前的 MASTER 节点为 haproxy-master 机器,我现在把这台机器上的 haproxy 服务停掉:

root@haproxy-master:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fb41ab81d214 custom-haproxy:1.7.9 "/docker-entrypoin..." About an hour ago Up 1 second haproxy-1
root@haproxy-master:~# docker stop fb41ab81d214
fb41ab81d214

然后我们访问:http://192.168.0.146:1080/stats,会在稍微停顿下后仍然能显示出来 haproxy 服务的状态。我们再 ssh [email protected] 后,发现我们进入了 haproxy-backup 机器上。此时的 MASTER 节点就是 haproxy-backup 机器。

以此来看,我们已经搭建出来了一个简单的 HAProxy + Keepalived 服务了。整体结构图如下所示:

未分类

结尾

有一点需要注意,容易混淆:

区分主节点、备节点是 Keepalived 服务来做的,HAProxy 在所有节点上的配置应该是相同的。

CentOS 7:使用HAProxy实现Nginx负载均衡

HAProxy是一款功能强大、灵活好用的反向代理的开源软件,它提供了负载均衡、服务器代理的功能。HAProxy是Willy Tarreau使用C语言编写的,它支持SSL、压缩、keep-alive、自定义日志格式和header重写。

HAProxy是轻量级的负载均衡和代理服务软件,占用系统资源较少。很多大型的网站都在使用它,例如Github、StackOverflow。

下面我安装配置HAProxy做为两个Nginx服务器的负载均衡。一共需要使用3个服务器,在一台机器上安装HAProxy,另两台机器安装Nginx服务。

未分类

HAProxy的基本概念

4层和7层

HAProxy可以使用两种模式运行:TCP 4层模式和HTTP 7层模式。TCP模式:HAProxy把原始TCP数据包从客户端转向到应用服务器;HTTP模式:解析http请求,然后转向到web服务器。我们将使用HTTP 7层模式。

负载均衡算法

HAProxy使用负载均衡算法决定把请求发送给哪个服务器,使用的算法:
Roundrobin-轮流算法
这是最简单的负载均衡算法。对每个新连接,总是下一个后端服务器处理。如果到达最后一个后端服务器,从头开始。

Lastconn

有最少连接的后端服务器处理新请求。当请求量较大时非常好。

Source

根据客户端IP决定哪个后端服务器处理。如果IP1是server1处理,那么这个IP1的所有请求都由server1处理。根据IP地址的哈希值决定后端服务器。

系统要求

3个CentOS 7服务器:

  • 处理负载均衡的HAProxy服务器:192.168.0.101

  • Nginx1服务器:192.168.0.108

  • Nginx2服务器:192.168.0.109

第一步

编辑HAProxy服务器(102.168.0.101)的/etc/hosts:

vim /etc/hosts

添加Nginx1和Nginx2的主机名:

192.168.0.108    nginx1.your_domain.com     nginx1
192.168.0.109    nginx2.your_domain.com     nginx2

保存退出。

同样,编辑两个Nginx服务器的/etc/hosts,添加:

192.168.0.101    loadbalancer

在两个Nginx服务器上都要设置。

第二步

在HAProxy服务器上安装HAProxy:

# yum update
# yum install haproxy

haproxy的配置文件位于/etc/haproxy/。为了防止出错,先备份原始配置文件:

# cd /etc/haproxy/
# mv haproxy.cfg haproxy.cfg.backup

编辑配置文件:

# vim haproxy.cfg

写入如下内容:

#---------------------------------------------------------------------
# 全局设置
#---------------------------------------------------------------------
global
log         127.0.0.1 local2     # 日志
chroot      /var/lib/haproxy
pidfile     /var/run/haproxy.pid
maxconn     4000                
user        haproxy             # Haproxy在haproxy用户和组下运行
group       haproxy
daemon
# 开启 stats unix socket
stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# 基本设置
#---------------------------------------------------------------------
defaults
mode                    http
log                     global
option                  httplog
option                  dontlognull
option http-server-close
option forwardfor       except 127.0.0.0/8
option                  redispatch
retries                 3
timeout http-request    10s
timeout queue           1m
timeout connect         10s
timeout client          1m
timeout server          1m
timeout http-keep-alive 10s
timeout check           10s
maxconn                 3000
#---------------------------------------------------------------------
# HAProxy Monitoring 配置
#---------------------------------------------------------------------
listen haproxy3-monitoring *:8080                # Haproxy Monitoring 的使用端口:8080
mode http
option forwardfor
option httpclose
stats enable
stats show-legends
stats refresh 5s
stats uri /stats                            # HAProxy monitoring的网址
stats realm Haproxy Statistics
stats auth testuser:test1234                # 登录Monitoring的用户和密码
stats admin if TRUE
default_backend app-main
#---------------------------------------------------------------------
# FrontEnd 配置
#---------------------------------------------------------------------
frontend main
bind *:80
option http-server-close
option forwardfor
default_backend app-main
#---------------------------------------------------------------------
# 使用roundrobin做为负载均衡算法
#---------------------------------------------------------------------
backend app-main
balance roundrobin                                    # 使用的负载均衡算法
option httpchk HEAD / HTTP/1.1rnHost: localhost    # 检查nginx服务器是否连通- 200状态码
server nginx1 192.168.0.108:80 check                  # Nginx1 
server nginx2 192.168.0.109:80 check                  # Nginx2
配置rsyslog

我们需要使用rsyslog记录HAProxy的日志,编辑rsyslog.conf配置文件,打开UDP的514端口:

# vim /etc/rsyslog.conf

去掉如下行的注释:

$ModLoad imudp
$UDPServerRun 514

如果你想指定特定IP,可以更改如下行:

$UDPServerAddress 127.0.0.1

保存退出。

创建rsyslog配置文件:

# vim /etc/rsyslog.d/haproxy.conf

写入如下内容:

local2.=info     /var/log/haproxy-access.log    # 访问日志
local2.notice    /var/log/haproxy-info.log      # haproxy执行信息

重启rsyslog:

# systemctl restart rsyslog

启动HAProxy:

# systemctl start haproxy
# systemctl enable haproxy

第三步

安装配置Nginx。

Nginx1和Nginx2服务器配置方法相同。

安装epel-release:

# yum install epel-release

安装Nginx:

# yum install nginx

创建index.html测试文件,Nginx1(192.168.0.108):

# cd /usr/share/nginx/html/
# echo "<h1>nginx1.your_domain.com</h1>" > index.html
Nginx2(192.168.0.109):
# cd /usr/share/nginx/html/
# echo "<h1>nginx2.your_domain.com</h1>" > index.html

启动Nginx服务:

# systemctl enable nginx
# systemctl start nginx

测试

测试nginx1、2,使用浏览器访问:

192.168.0.108
192.168.0.109

正常访问网站:http://192.168.0.101,如果有域名,指向这个IP。
登录HAProxy web管理页面:

http://192.168.0.101:8080/stats

你应该可以看到nginx、http请求的转发信息。

反向代理之haproxy安装及简单配置tcp代理

一、简介

HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且
可靠的一种解决方案。

HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。

HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单
安全的整合进您当前的架构中,同时可以保护你的web服务器不被暴露到网络上。

HAProxy实现了一种事件驱动, 单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接
事件驱动模型因为在有更好的资源和时间管理的用户空间(User-Space) 实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。

这就是为什么他们必须进行优化以 使每个CPU时间片(Cycle)做更多的工作。

二、安装

1. 环境准备

环境设置:

web-node1:
[root@web-node1 src]# uname -r
3.10.0-229.el7.x86_64
[root@web-node1 src]# uname -m
x86_64
[root@web-node1 src]# cat /etc/hostname 
web-node1
[root@web-node1 src]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.64    zabbix_master
10.0.0.65    web-node1
10.0.0.66    web-node2
web-node2:
[root@web-node2 src]# uname -r
3.10.0-229.el7.x86_64
[root@web-node2 src]# uname -m
x86_64
[root@web-node2 src]# cat /etc/hostname 
web-node2
[root@web-node2 src]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.64    zabbix_master
10.0.0.65    web-node1
10.0.0.66    web-node2

2. 安装haproxy

目前haproxy最高版本是1.7.8,本次实验使用1.7.5

下载地址:http://www.haproxy.org/download/1.7/

web-node1:

[root@web-node1 haproxy-1.7.5]#    cd /usr/local/src
[root@web-node1 ]# wget http://www.haproxy.org/download/1.7/src/haproxy-1.7.5.tar.gz
[root@web-node1 haproxy-1.7.5]#  tar -zxf  haproxy-1.7.5.tar.gz 
[root@web-node1 haproxy-1.7.5]#  cd haproxy-1.7.5
[root@web-node1 haproxy-1.7.5]#   make TARGET=linux2628 PREFIX=/usr/local/haproxy-1.7.5
[root@web-node1 haproxy-1.7.5]# make install PREFIX=/usr/local/haproxy-1.7.5
[root@web-node1 haproxy-1.7.5]# cp /usr/local/sbin/haproxy /usr/sbin/
[root@web-node1 local]# ln -s /usr/local/haproxy-1.7.5 /usr/local/haproxy
[root@web-node1 haproxy-1.7.5]# haproxy -v
HA-Proxy version 1.7.5 2017/04/03
Copyright 2000-2017 Willy Tarreau <[email protected]>
#参数说明
TARGET=linux26 #内核版本,使用uname -r查看内核,如:2.6.18-371.el5,此时该参数就为linux26;kernel 大于2.6.28的用:TARGET=linux2628
PREFIX=/usr/local/haprpxy #/usr/local/haprpxy为haprpxy安装路径

3. 编辑Haproxy启动脚本

[root@web-node1 haproxy-1.7.5]# cp /usr/local/src/haproxy-1.7.5/examples/haproxy.init /etc/init.d/haproxy
[root@web-node1 haproxy-1.7.5]# chmod +x /etc/init.d/haproxy

4. 创建haproxy相关目录

[root@web-node1 haproxy-1.7.5]# useradd -r haproxy  ##创建系统用户
[root@web-node1 haproxy-1.7.5]# mkdir /etc/haproxy
[root@web-node1 haproxy-1.7.5]# mkdir /var/lib/haproxy
[root@web-node1 haproxy-1.7.5]# mkdir /var/run/haproxy

5. 修改配置文件

[root@web-node1 haproxy-1.7.5]# cat /etc/haproxy/haproxy.cfg 
global
   log 127.0.0.1 local3 warning
   chroot /var/lib/haproxy
   user haproxy
   group haproxy
   nbproc  1
   maxconn 65535 
   daemon
defaults
   log global
   option dontlognull
   timeout connect 5000
   timeout client 50000
   timeout server 50000
listen test
 bind 10.0.0.65:8080
 mode tcp
 #balance roundrobin
 timeout server 15s
 timeout connect 15s
 server web01 10.0.0.66:22 check port 22 inter 5000 fall 5 

6. 启动haproxy

检查语法:
/usr/sbin/haproxy  -f /etc/haproxy/haproxy.cfg -c
[root@web-node1 haproxy-1.7.5]# /etc/init.d/haproxy start
查看进程:
[root@web-node1 haproxy-1.7.5]# ps -ef|grep haproxy
haproxy   11126      1  0 16:20 ?        00:00:00 /usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid
root      11183   2633  0 16:32 pts/1    00:00:00 grep --color=auto haproxy

三、测试tcp代理是否成功

未分类

上述可以看出已经成功了。

配置Haproxy代理实现MySQL从服务器的负载均衡

之前的文章配置过haproxy以及简单使用,具体可以参考《Centos系统环境下进行负载均衡软件Haproxy安装及配置》(http://www.21yunwei.com/archives/5111), 今天文章记录下通过配置Haproxy代理实现MySQL从服务器的负载均衡。

haproxy本身支持TCP协议的负载均衡转发,对于各种基于tcp的软件进行负载均衡比如mysql,之前配置的web负载均衡都是基于应用层,今天记录下tcp的。

环境准备:

  • centos 6.x三台,具体如下:
    • IP:192.168.1.104 角色:haproxy,mysql_master
    • IP:192.168.1.122 角色:mysql_slave
    • IP:192.168.1.123 角色:mysql_slave
  • 说明:
    • mysql主从安装这里不单独配置写出,配置非常简单,可以参考之前的博客文章《Linux系统如何设置mysql数据库主从以及互为主从》(http://www.21yunwei.com/archives/1035)
    • 由于1.104已经配置了mysql_master占用了3306端口,haproxy我们启用3307端口测试。

一、配置haproxy

global                                                     
    log         127.0.0.1 local2                     
    chroot      /usr/share/haproxy
    pidfile     /var/run/haproxy.pid         
    maxconn     4000                                
    user        haproxy
    group       haproxy                        
    daemon                                               
defaults
        mode tcp               #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
        retries 2               #两次连接失败就认为是服务器不可用,也可以通过后面设置
        option redispatch       #当serverId对应的服务器挂掉后,强制定向到其他健康的服务器
        option abortonclose     #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
        maxconn 4096            #默认的最大连接数
        timeout connect 5000ms  #连接超时
        timeout client 30000ms  #客户端超时
        timeout server 30000ms  #服务器超时
        #timeout check 2000      #=心跳检测超时
        log 127.0.0.1 local0 err #[err warning info debug]
listen test1
        bind 192.168.1.104:3307
        mode tcp
        #maxconn 4086
        #log 127.0.0.1 local0 debug
        server s1 192.168.1.122:3306
        server s2 192.168.1.123:3306

二、测试mysql的负载均衡

利用navicat连接192.168.1.104的3307端口,理论上我们会连接到后端的122或者123的mysql上,为了区别,我们分别从mysql_slave单独建立两个库以便区分:

  • 192.168.1.122 mysql_slave建立测试数据库web122;
  • 192.168.1.123 mysql_slave建立测试数据库web123;

(具体sql语句:create database web122/123 default charset utf8;)

连接测试:

未分类

连接进入查看:

未分类

查看我们连接到了192.168.1.123 mysql_slave,看到了建立的测试库web123.

断开连接,重新连接:

未分类

查看我们连接到了192.168.1.122 mysql_slave,看到了建立的测试库web122.

总结,配置Haproxy代理实现MySQL从服务器的负载均衡已经完成。后续需要根据配置文件进行一些参数的优化或者架构的优化,比如配置keepalive实现高可用、根据mysql_slave配置分配权重等等,具体情况具体分析。

如何通过haproxy配置多个独立站点

通过之前的文章《Centos系统环境下进行负载均衡软件Haproxy安装及配置》(http://www.21yunwei.com/archives/5111) 记录下如何安装haproxy,当时测试的比较简单,不过还是里边配置了几个站点,这里单独拿出来进行一下站点配置说明。

配置目的:对三个站点lvs.21yunwei.com、21yunwei.21yunwei.com、bbs.21yunwei.com进行单独设置web后端节点以及设置节点的权重,实现访问每个域名,都访问具体自己设置的站点节点以及自己的网站内容。没有配置站点ID的,则访问设置好的默认站点。

1、配置haproxy

说白了,就是针对haproxy进行配置后重启。根据配置目的,haproxy配置文件如下:

global                                                     
    log         127.0.0.1 local2                     
    chroot      /usr/share/haproxy
    pidfile     /var/run/haproxy.pid         
    maxconn     4000                                
    user        haproxy
    group       haproxy                        
    daemon                                               
defaults
    mode                    http                      
    log                        global   
    option                  httplog      

    option                  dontlognull          
    option http-server-close                  
    option forwardfor       except 127.0.0.0/8    
    option                  redispatch        
    retries                 3                             
    timeout http-request    10s             
    timeout queue           1m                
    timeout connect         10s                
    timeout client          1m                   
    timeout server          1m                   
    timeout http-keep-alive 10s           
    timeout check           10s                 
    maxconn                 3000                
frontend  http_default_80
    bind 0.0.0.0:80
    mode http
    log  global
    option  httplog
    option  httpclose
    option  forwardfor
    acl 21yunwei_site  hdr(host) -i 21yunwei.21yunwei.com
    acl lvs_site hdr(host) -i   lvs.21yunwei.com
    acl bbs_site  hdr(host) -i bbs.21yunwei.com
    use_backend   web_21yunwei  if 21yunwei_site
    use_backend   web_lvs   if lvs_site
    use_backend   web_bbs   if bbs_site
    default_backend             web_21yunwei
frontend www
   bind :81
   monitor-uri   /haproxy 
backend static                                                
    balance     roundrobin                             
    server      static 127.0.0.1:80 check            
backend web_21yunwei          
    mode    http                       
    balance roundrobin                              
    cookie SERVERID 
    option httpchk GET /index.html
    server  21web1 192.168.1.123:80  check inter 2000 fall 3 weight 1             
    server  21web2 192.168.1.122:80  check inter 2000 fall 3 weight 1
backend web_lvs
    mode    http
    balance roundrobin    
    cookie SERVERID
    option httpchk GET /index.html
    server  lvsweb1 192.168.1.123:80  check inter 2000 fall 3 weight 1 
    server  lvsweb2 192.168.1.122:80  check inter 2000 fall 3 weight 3  
backend web_bbs
    mode    http
    balance roundrobin
    cookie SERVERID
    option httpchk GET /ok.php
    server  21web1 192.168.1.123:80  check inter 2000 fall 3 weight 1
    server  21web2 192.168.1.122:80  check inter 2000 fall 3 weight 1

listen  admin_stats 0.0.0.0:88
        option httplog
         stats refresh 30s
         stats uri /admin
         stats realm Haproxy Manager
         stats auth admin:admin

大如上边配置文件,我们配置了一个的frontend 指定前端访问虚拟节点和三个backend后端集群。
说明:

  • frontend里边包含了网站的端口、模式、日志以及acl规则,这里主要是acl规则,访问每个域名都指定访问哪个后端集群,不在acl访问控制规则里边的则访问到默认站点。

  • backend主要是配置对应的后端集群,包含模式、指定算法、健康检测url以及对应后端的真实server节点,节点包含具体IP以及端口、检测以及权重。

  • 补充内容:haproxy作为一款负载均衡软件,本身还是支持动静分离的,可以通过acl规则设置动静分离,分别走独立配置的backend后端集群。比如这样配置可以设置动静分离(本博客这里没这样设置,有实际需要的时候可以针对设置):

   acl url_static       path_beg       -i /static /images /javascript /stylesheets
   acl url_static       path_end       -i .jpg .jpeg .gif .png .css .js .html
   acl url_php          path_end       -i .php

   use_backend static_servers          if url_static
   use_backend dynamic_servers         if url_php
   default_backend dynamic_servers

2、测试

由于设置了监控页面,可以先进入监控页面看下节点是否都正常:

未分类

查看节点没异常,这里分别访问三个域名进行测试:

访问bbs.21yunwei.com效果:

未分类

访问21yunwei.21yunwei.com效果:

未分类

访问lvs.21yunwei.com效果:

未分类

可见设置是正确的,没问题。 同时安装了论坛或者其他有session会话保持的系统的,可以进行session会话保持测试。 单独停掉其中的一个web节点,会话保持不受影响,依旧可以进行正常登陆操作。

安装配置HAProxy实现RabbitMQ的负载均衡

HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案,包括Twitter,Reddit,StackOverflow,GitHub在内的多家知名互联网公司在使用。HAProxy实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。

安装HAProxy

首先需要去HAProxy的官网下载HAProxy的安装文件,目前最新的版本为:haproxy-1.7.8.tar.gz。下载地址为http://www.haproxy.org/#down,相关文档地址为http://www.haproxy.org/#doc1.7。

将haproxy-1.7.8.tar.gz拷贝至/opt目录下,与RabbitMQ存放在同一个目录中。之后解压缩:

[root@node1 opt]# tar zxvf haproxy-1.7.8.tar.gz

将源码解压之后,需要运行make来将HAProxy编译为可执行程序。在执行make之前需要先选择目标平台,通常对于UNIX系的操作系统可以选择TARGET=generic。下面是详细操作:

[root@node1 opt]# cd haproxy-1.7.8
[root@node1 haproxy-1.7.8]# make TARGET=generic
gcc -Iinclude -Iebtree -Wall  -O2 -g -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv      
-DTPROXY -DENABLE_POLL  
-DCONFIG_HAPROXY_VERSION="1.7.8" 
-DCONFIG_HAPROXY_DATE="2017/07/07" 
          -DBUILD_TARGET='"generic"' 
          -DBUILD_ARCH='""' 
          -DBUILD_CPU='"generic"' 
          -DBUILD_CC='"gcc"' 
          -DBUILD_CFLAGS='"-O2 -g -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv"' 
          -DBUILD_OPTIONS='""' 
           -c -o src/haproxy.o src/haproxy.c
gcc -Iinclude -Iebtree -Wall  -O2 -g -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv...
...
gcc  -g -o haproxy src/haproxy.o src/base64.o src/protocol.o src/uri_auth.o ...

编译完目录下有名为“haproxy”的可执行文件。之后再/etc/profile中加入haproxy的路径,内容如下:

export PATH=$PATH:/opt/haproxy-1.7.8/haproxy

最后执行source /etc/profile让此环境变量生效。

配置HAProxy

HAProxy使用单一配置文件来定义所有属性,包括从前端IP到后端服务器。下面展示了用于3个RabbitMQ节点组成集群的负载均衡配置。这3个节点的IP地址分别为192.168.02、192.168.0.3、192.168.0.4,HAProxy运行在192.168.0.9这台机器上。

#全局配置
global
        #日志输出配置,所有日志都记录在本机,通过local0输出
        log 127.0.0.1 local0 info
        #最大连接数
        maxconn 4096
        #改变当前的工作目录
        chroot /opt/haproxy-1.7.8
        #以指定的UID运行haproxy进程
        uid 99
        #以指定的GID运行haproxy进程
        gid 99
        #以守护进程方式运行haproxy #debug #quiet
        daemon
        #debug
        #当前进程pid文件
        pidfile /opt/haproxy-1.7.8/haproxy.pid

#默认配置
defaults
        #应用全局的日志配置
        log global
        #默认的模式mode{tcp|http|health}
        #tcp是4层,http是7层,health只返回OK
        mode tcp
        #日志类别tcplog
        option tcplog
        #不记录健康检查日志信息
        option dontlognull
        #3次失败则认为服务不可用
        retries 3
        #每个进程可用的最大连接数
        maxconn 2000
        #连接超时
        timeout connect 5s
        #客户端超时
        timeout client 120s
        #服务端超时
        timeout server 120s

#绑定配置
listen rabbitmq_cluster 5671
        #配置TCP模式
        mode tcp
        #简单的轮询
        balance roundrobin
        #RabbitMQ集群节点配置
        server rmq_node1 192.168.0.2:5672 check inter 5000 rise 2 fall 3 weight 1
        server rmq_node2 192.168.0.3:5672 check inter 5000 rise 2 fall 3 weight 1
        server rmq_node3 192.168.0.4:5672 check inter 5000 rise 2 fall 3 weight 1

#haproxy监控页面地址
listen monitor :8100
        mode http
        option httplog
        stats enable
        stats uri /stats
        stats refresh 5s

在上面的配置中“listen rabbitmq_cluster bind 192.168.0.9.5671”这里定义了客户端连接IP地址和端口号。这里配置的负载均衡算法是roundrobin,注意这里的roundrobin是加权轮询。和RabbitMQ最相关的是“ server rmq_node1 192.168.0.2:5672 check inter 5000 rise 2 fall 3 weight 1”这种,它定义了RabbitMQ服务,每个RabbitMQ服务定义指令包含6个部分:

server <name>:定义RabbitMQ服务的内部标示,注意这里的“rmq_node”是指包含有含义的字符串名称,不是指RabbitMQ的节点名称。
<ip>:<port>:定义RabbitMQ服务的连接的IP地址和端口号。
check inter <value>:定义了每隔多少毫秒检查RabbitMQ服务是否可用。
rise <value>:定义了RabbitMQ服务在发生故障之后,需要多少次健康检查才能被再次确认可用。
fall <value>:定义需要经历多少次失败的健康检查之后,HAProxy才会停止使用此RabbitMQ服务。
weight <value>:定义了当前RabbitMQ服务的权重。

最后一段配置定义的是HAProxy的数据统计页面。数据统计页面包含各个服务节点的状态、连接、负载等信息。在调用:

[root@node1 haproxy-1.7.8]# haproxy -f haproxy.cfg

运行HAProxy之后可以在浏览器上输入http://192.168.0.9:8100/stats来加载相关的页面,如下图所示:

未分类

配置haproxy在http请求头添加后端用户真实IP

在haproxy的配置文件中的前端bind下添加如下配置:

http-request set-header ZXTMIP %[src]

ps:其中ZXTMIP是自定义的字段 %[src]是取得IP

测试结果:

spacer.gif在浏览器中打开测试域名后的输出如下:

Array ( [TEMP] => /var/tmp [TMPDIR] => /var/tmp [TMP] => /var/tmp [PATH] => /usr/local/bin:/usr/bin:/bin [HOSTNAME] => mptest.okooo.com [USER] => web [HOME] => /var/webroot [FCGI_ROLE] => RESPONDER [SCRIPT_FILENAME] => /home/oae/web/wwwroot/public/index.php [QUERY_STRING] => [REQUEST_METHOD] => GET [CONTENT_TYPE] => [CONTENT_LENGTH] => [SCRIPT_NAME] => /index.php [REQUEST_URI] => / [DOCUMENT_URI] => /index.php [DOCUMENT_ROOT] => /home/oae/web/wwwroot/public [SERVER_PROTOCOL] => HTTP/1.1 [GATEWAY_INTERFACE] => CGI/1.1 [SERVER_SOFTWARE] => nginx/1.6.2 [REMOTE_ADDR] => 192.168.1.231 [REMOTE_PORT] => 6824 [SERVER_ADDR] => 192.168.1.235 [SERVER_PORT] => 80 [SERVER_NAME] => mptest.okooo.com [REDIRECT_STATUS] => 200 [HTTP_HOST] => mptest.okooo.com [HTTP_UPGRADE_INSECURE_REQUESTS] => 1 [HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36 [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 [HTTP_ACCEPT_ENCODING] => gzip, deflate [HTTP_ACCEPT_LANGUAGE] => zh-CN,zh;q=0.8 [HTTP_COOKIE] => LastUrl=; __utma=56961525.524112254.1501123742.1501123742.1501123742.1; __utmz=56961525.1501123742.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none) [HTTP_ZXTMIP] => 111.200.213.110 [HTTP_X_FORWARDED_FOR] => 111.200.213.110 [HTTP_CONNECTION] => close [PHP_SELF] => /index.php [REQUEST_TIME_FLOAT] => 1501644453.5864 [REQUEST_TIME] => 1501644453 )

saltstack自动安装配置HAproxy

下载haproxy1.6.2.tar.gz

下载地址:http://www.haproxy.org/download/1.6/src/

1、编写功能模块

1.1 首先编写依赖安装模块

# mkdir -p /srv/salt/prod/pkg /srv/salt/prod/haproxy /srv/salt/prod/haproxy/files 
# cd /srv/salt/prod/pkg

# cat pkg-init.sls 
pkg-init:
pkg.installed:
- names:
- gcc
- gcc-c++
- glibc
- make
- autoconf
- openssl
- openssl-devel

1.2 编写HAproxy状态模块

如何写状态模块?
安装一遍,记录安装步骤

手动安装步骤:

安装依赖

# yum install gcc gcc-c++ glibc make autoconf openssl openssl-devel
cd /usr/local/
tar -zxf haproxy-1.6.2.tar.gz
cd /usr/local/haproxy-1.6.2

2、将配置文件,启动文件等拷贝到/srv/salt/prod/haproxy/files下

2.1 获取启动脚本,并copy到/srv/salt/prod/haproxy/files/

# mv haproxy-1.6.2.tar.gz /srv/salt/prod/haproxy/files/
# cd /srv/salt/prod/haproxy/files/
# tar zxf haproxy-1.6.2.tar.gz
# cd haproxy-1.6.2/examples/
# vim haproxy.init
BIN=/usr/local/haporxy/sbin/$BASENAME

# cp haproxy.init /srv/salt/prod/haproxy/files/

# cd /srv/salt/prod/haproxy/files
# rm -rf haproxy-1.6.2

2.1 编写install.sls

不在这里写配置文件,是为了解耦。因为安装和启动时原子操作,在哪都必须,但是配置文件,在不同环境下是不一样的

# cd /srv/salt/prod/haproxy/
# vim install.sls

include:
- pkg.pkg-init
haproxy-install: 
file.managed: 
- name: /usr/local/src/haproxy-1.6.2.tar.gz
- source: salt://haproxy/files/haproxy-1.6.2.tar.gz
- user: root
- group: root
- mode: 755
cmd.run:
- name: cd /usr/local/src && tar zxf haproxy-1.6.2.tar.gz && cd haproxy-1.6.2 && make TARGET=linux26 PREFIX=/usr/local/haproxy && make install PREFIX=/usr/local/haproxy
- unless: test -d /usr/local/haproxy
- require:
- pkg: pkg-init
- file: haproxy-install
haproxy-init:
file.managed:
- name: /etc/init.d/haproxy
- source: salt://haproxy/files/haproxy.init
- user: root
- group: root
- mode: 755
- require:
- cmd: haproxy-install
cmd.run:
- name: chkconfig --add haproxy
- unless: chkconfig --list | grep haproxy
- require:
- file: /etc/init.d/haproxy
net.ipv4.ip_nonlocal_bind:
sysctl.present:
- value: 1
haproxy-config-dir:
file.directory:
- name: /etc/haproxy
- user: root
- group: root
- mode: 755

# salt '*' state.sls haproxy.install env=prod

注:
直接拷贝上面的配置文件执行可能会出错,建议进入vim状态后,使用set list命令,确保$符号和配置之间没有空格
并且层级关系是2、4、6个空格
建议先执行测试然后再实际配置修改

# salt '*' state.sls haproxy.install env=prod test=True

3、编写业务引用

3.1 HAproxy配置文件

# mkdir -p /srv/salt/prod/cluster/files
# cd /srv/salt/prod/cluster/files/ 
# vim /srv/salt/prod/cluster/files/haproxy-outside.cfg
global
maxconn 100000
chroot /usr/local/haproxy
uid 99 
gid 99
daemon
nbproc 1
pidfile /usr/local/haproxy/logs/haproxy.pid
log 127.0.0.1 local3 info
defaults
option http-keep-alive
maxconn 100000
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen stats
mode http
bind 0.0.0.0:8888
stats enable
stats uri /haproxy-status
stats auth haproxy:saltstack
frontend frontend_www_example_com
bind 192.168.3.11:80
mode http
option httplog
log global
default_backend backend_www_example_com
backend backend_www_example_com
option forwardfor header X-REAL-IP
option httpchk HEAD / HTTP/1.0
balance source
server web-node1 192.168.3.12:8080 check inter 2000 rise 30 fall 15
server web-node2 192.168.3.19:8080 check inter 2000 rise 30 fall 15

# cd ..
# vim /srv/salt/prod/cluster/haproxy-outside.sls
include:
- haproxy.install
haproxy-service:
file.managed:
- name: /etc/haproxy/haproxy.cfg
- source: salt://cluster/files/haproxy-outside.cfg
- user: root
- group: root
- mode: 644
service.running:
- name: haproxy
- enable: True
- reload: True
- require:
- cmd: haproxy-init
- watch:
- file: haproxy-service

# cd /srv/salt/base/
# vim top.sls
base:
'*':
- init.env_init
prod:
'*':
- cluster.haproxy-outside

执行安装配置

# salt '*' state.highstate

4、Web查看服务状态

从web登陆192.168.3.12:8888/haproxy-status
用户名和密码在/srv/salt/prod/cluster/files/haproxy-outside.cfg中

# grep 'auth' /srv/salt/prod/cluster/files/haproxy-outside.cfg
stats auth haproxy:saltstack

至此haproxy的配置完成

未分类

haproxy配置https负载均衡

本实验全部在haproxy1.5.19版本进行测试通过,经过测试1.7.X及haproxy1.3版本以下haproxy配置参数可能不适用,需要注意版本号。

一、业务要求

现在根据业务的实际需要,有以下几种不同的需求。如下:

1.1 http跳转https

把所有请求http://www.chinasoft.com的地址全部跳转为https//:www.chinasoft.com这个地址

1.2 http与https并存

服务器同时开放http://www.chinasoft.com和https://www.chinasoft.com的访问形式

1.3 服务器环境准备

未分类

node1即haproxy所在服务器的处理

安装依赖

yum install -y openssl openssl-devel readline-devel pcre-devel libssl-dev libpcre3

# 下载安装包,
tar zxf haproxy-1.5.19.tar.gz
cd haproxy-1.5.19
# 加入支持ssl的编译参数

make TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_CRYPT_H=1 USE_LIBCRYPT=1
cp /usr/local/sbin/haproxy /usr/sbin/
make install PREFIX=/usr/local/haproxy
cp /usr/local/sbin/haproxy /usr/sbin/
cp examples/haproxy.init /etc/init.d/haproxy

# 修改启动脚本(可能会报错)为如下
vim /etc/init.d/haproxy
26 [[ ${NETWORKING} = "no" ]] && exit 0

后端web01(192.168.3.200)服务器apache配置,需要配置虚拟主机域名为:www.chinasoft.com否则无法正常处理

[root@node2 ~]# egrep -v '#|^$' /etc/httpd/conf/httpd.conf 
ServerRoot "/etc/httpd"
Listen 8080
Include conf.modules.d/*.conf
User apache
Group apache
ServerAdmin root@localhost
<Directory />
Options FollowSymLinks
AllowOverride none
Allow from all
</Directory>
DocumentRoot "/var/www/html/chinasoft"
<Directory "/var/www">
AllowOverride None
Require all granted
</Directory>
<Directory "/var/www/html/chinasoft">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
<IfModule dir_module>
DirectoryIndex index.php index.html
</IfModule>
<Files ".ht*">
Require all denied
</Files>
ErrorLog "logs/error_log"
LogLevel warn
<IfModule log_config_module>
LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined
LogFormat "%h %l %u %t "%r" %>s %b" common
<IfModule logio_module>
LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i" %I %O" combinedio
</IfModule>
CustomLog "logs/access_log" combined
</IfModule>
<IfModule alias_module>
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>
<Directory "/var/www/cgi-bin">
AllowOverride None
Options None
Require all granted
</Directory>
<IfModule mime_module>
TypesConfig /etc/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
</IfModule>
AddDefaultCharset UTF-8
<IfModule mime_magic_module>
MIMEMagicFile conf/magic
</IfModule>
EnableSendfile on
IncludeOptional conf.d/*.conf

[root@node2 ~]# cat /etc/httpd/conf.d/vhost.conf 
NameVirtualHost *:8080
<VirtualHost *:8080>
DocumentRoot /var/www/html/
ServerName 192.168.3.200:8080
</VirtualHost>

<Directory "/var/www/html/chinasoft/">
php_admin_value open_basedir "/var/www/html/chinasoft/:/tmp/"
Options Includes ExecCGI FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
<VirtualHost *:8080>
DocumentRoot /var/www/html/chinasoft/
ServerName www.chinasoft.com:8080
</VirtualHost>

1.4 证书的处理,需要将网站的根证书和key简单的合并在一起:

cat chinasoft.com.pem chinasoft.com.key | tee chinasoft.pem

否则会报错

'bind *:443' : unable to load SSL private key from PEM file

1.5 域名的指向及处理

将www.chinasoft.com指向haproxy负载均衡器所在的服务器IP地址,此处是192.168.3.198

二、配置haproxy并测试业务需求

现在我们根据业务的需求,我们来配置haproxy一一达到其需求。

2.1 http跳转https配置

http跳转https的haproxy配置文件内容,如下:

[root@node1 haproxy]# cat /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local3 info
chroot /var/lib/haproxy
maxconn 4096
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
stats timeout 2m
tune.ssl.default-dh-param 2048

defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.1
option redispatch
retries 3
option redispatch
maxconn 2000
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s

listen admin_stats
bind 0.0.0.0:1080
mode http
option httplog
maxconn 10
stats refresh 30s
stats uri /haproxy?stats
stats auth admin:admin
stats hide-version

frontend weblb
bind *:80
acl is_http hdr_beg(host) www.chinasoft.com
redirect scheme https if !{ ssl_fc }
bind *:443 ssl crt /etc/haproxy/chinasoft.pem
use_backend httpserver if is_http

backend httpserver
balance source
server web1 192.168.3.200:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3



# 配置好之后先检查语法是否正确
[root@node1 haproxy]# /etc/init.d/haproxy check
Configuration file is valid

在以上配置文件中,需要注意的选项如下:

tune.ssl.default-dh-param 2048因为我们的SSL密钥使用的是2048bit加密,所以在此进行声明。

acl is_http hdr_beg(host) www.chinasoft.com
redirect scheme https if !{ ssl_fc }
bind *:443 ssl crt /etc/haproxy/chinasoft.pem

这三行表示把所有访问www.chinasoft.com这个域名的请求,全部转发到https://www.chinasoft.com这个连接

管理页面

未分类

2.2 测试http跳转https

http跳转https配置完毕后,我们选择来测试其跳转。如下:

未分类

你会发现在浏览器中,无论你输入的是www.chinasoft.com,还是http://www.chinasoft.com亦或是https://www.chinasoft.com,都会自动跳转到https://www.chinasoft.com。

这样就达到了,把所有的http请求跳转到https的目的。

2.3 http与https并存配置

haproxy要实现http和https并存的话,配置也很简单,只需要把haproxy分别监控不同的端口就行,配置文件如下:

[root@node1 haproxy]# cat haproxy.cfg
global
log 127.0.0.1 local3 info
chroot /var/lib/haproxy
maxconn 4096
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
stats timeout 2m
tune.ssl.default-dh-param 2048

defaults
log global
mode http
option httplog
option dontlognull
option redispatch
retries 3
option redispatch
maxconn 2000
timeout connect 10s
timeout client 1m
timeout server 1m
timeout check 10s

listen admin_stats
bind 0.0.0.0:1080
mode http
option httplog
maxconn 10
stats refresh 30s
stats uri /haproxy?stats
stats auth admin:admin
stats hide-version

frontend weblb
bind *:80
acl is_http hdr_beg(host) www.chinasoft.com
use_backend httpserver if is_http

backend httpserver
balance source
server web1 192.168.3.200:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3

frontend weblb443
bind *:443 ssl crt /etc/haproxy/chinasoft.pem
acl is_443 hdr_beg(host) www.chinasoft.com
use_backend httpserver443 if is_443

backend httpserver443
balance source
server web1 192.168.3.200:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3

在以上配置文件中,我们定义了两个前端,一个前端用于监听80端口,也就是http协议。另外一个前端监听443端口,也就是https协议。

此时haproxy会根据客户端请求的协议进行分发,如果发现客户端请求的是http协议,则把该请求分发到监听80端口的前端。如果发现客户端请求的是https协议,则把该请求分发到监听443端口的前端。如此就达到了haproxy让http和https并存的要求。

2.4 测试http与https并存

http与https并存配置完毕后,我们选择来测试其跳转。如下:

未分类

未分类

通过测试你会发现,在浏览器中如果你输入的是http://www.chinasoft.com或者是www.chinasoft.com都会直接跳转到http://www.chinasoft.com,而输入的是https://www.chinasoft.com,则只会跳转到https://www.chinasoft.com。

如此就到达了,我们业务的要求实现http和https并存。

使用HAProxy Keepalived实现主备及负载均衡

HAProxy提供高可用性负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。根据官方数据,其最高极限支持10G的并发。

HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中,同时可以保护你的web服务器不被暴露到网络上。其支持从4层至7层的网络交换,即覆盖所有的TCP协议。就是说,Haproxy甚至还支持Mysql的负载均衡。如果说在功能上,能以proxy反向代理方式实现WEB均衡负载,这样的产品有很多。包括Nginx,ApacheProxy,lighttpd,Cheroke等。但要明确一点的,Haproxy并不是Http服务器。以上提到所有带反向代理均衡负载的产品,都清一色是WEB服务器。简单说,就是他们能自个儿提供静态(html,jpg,gif..)或动态(php,cgi..)文件的传输以及处理。而Haproxy仅仅,而且专门是一款的用于均衡负载的应用代理。其自身并不能提供http服务。开始Haproxy主备高可用测试

未分类

测试系统:

  • CentOS6.7/Ubuntu15.04

IP信息:

  • 主Haproxy:192.168.15.132

  • 备Haproxy:192.168.15.133

  • VIP:192.168.15.135(www.test.com/img.test.com)

  • Real1:192.168.15.128

  • Real2:192.168.15.130

  • Real3:192.168.15.140

主LB与备LB均配置

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf         #开启数据包转发

echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf   #允许监听非本地地址

sysctl -p

安装haproxy

cd /usr/local/src

CentOS系统:

yum install wget gcc gcc-c++ autoconf automake make

Ubuntu系统:

sudo apt-get install build-essential  libtool

wget http://pkgs.fedoraproject.org/repo/pkgs/haproxy/haproxy-1.4.24.tar.gz/86422620faa9759907563d5e0524b98c/haproxy-1.4.24.tar.gz

tar -xvzf haproxy-1.4.24.tar.gz

cd haproxy-1.4.24

make TARGET=linux2628 && make install  

#kernel版本大于2.6.28的,使用"TARGET=linux2628",否则使用"TARGET=linux26"。

添加haproxy用户:

useradd -d /var/lib/haproxy -s /bin/false haproxy

创建配置文件

mkdir -p /etc/haproxy 

cp -r  /usr/local/src/haproxy-1.4.24/examples/errorfiles  /etc/haproxy/errorfiles

cp /usr/src/haproxy-1.4.24/examples/haproxy.cfg /etc/haproxy  #拷贝示例文件

cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak      #备份示例文件

负载均衡①:

vi /etc/haproxy/haproxy.cfg
global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 notice
        maxconn 5000
        chroot /var/lib/haproxy
        user haproxy
        group haproxy
        daemon
defaults
        log     global
        mode    http          #所处理的类别 (#7层 http;4层tcp  )
        option  httplog
        option  httpclose
        option  dontlognull   #不记录健康检查的日志信息
        option  forwardfor    #后端服务器需要获得客户端真实ip时配置的参数,可以从Http Header中获得客户端ip
        option  redispatch    #serverId对应的服务器挂掉后,强制定向到其他健康的服务器
        retries 3
        maxconn 4000
        contimeout      8000
        clitimeout      80000
        srvtimeout      80000
listen Web_LB  
      bind *:80
      mode http   #7层:http;4层:tcp
      cookie Web_LB  insert
      balance roundrobin
      option httpclose
      option forwardfor
      #option httpchk GET /index.html #心跳检测的文件
      server Real1 192.168.15.128:80 cookie Real1 check inter 1500 rise 3 fall 3 weight 1
      server Real2 192.168.15.130:80 cookie Real2 check inter 1500 rise 3 fall 3 weight 1
      server Real3 192.168.15.140:80 cookie Real3 check inter 1500 rise 3 fall 3 weight 1
      #服务器定义,"cookie Real1"表示serverid为Real1,"check inter 1500"是检测心跳频率,"rise 3"是3次正确认为服务器可用,"fall 3"是3次失败认为服务器不可用,weight代表权重
      srvtimeout 30000 
listen stats  192.168.15.135:9999
    mode http
    stats enable
    stats refresh 5s
    stats hide-version
    stats realm Haproxy Statistics #监控页面提示信息
    stats uri /haproxy-status
    stats auth test:123456
    acl allow src 192.168.15.0/16
    stats admin if TRUE  #手动启用/禁用后端服务器(haproxy-1.4.9以后版本)
    errorfile 403 /etc/haproxy/errorfiles/403.http
    errorfile 500 /etc/haproxy/errorfiles/500.http
    errorfile 502 /etc/haproxy/errorfiles/502.http
    errorfile 503 /etc/haproxy/errorfiles/503.http
    errorfile 504 /etc/haproxy/errorfiles/504.http

负载均衡②:

vi /etc/haproxy/haproxy.cfg
global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 notice
        maxconn 5000
        chroot /var/lib/haproxy
        user haproxy
        group haproxy
        daemon
defaults
        log     global
        mode    http 
        option  httplog
        option  httpclose
        option  dontlognull  
        option  forwardfor   
        option  redispatch   
        retries 3
        maxconn 4000
        contimeout      8000
        clitimeout      80000
        srvtimeout      80000
listen stats  192.168.15.135:9999
    mode http
    stats enable
    stats refresh 5s
    stats hide-version
    stats realm Haproxy Statistics 
    stats uri  /haproxy-status
    stats auth test:123456
    acl allow src 192.168.15.0/16
    stats admin if TRUE
frontend www
    bind *:80
    acl web hdr_reg(host) -i ^(www.test.com|test.com)$
    #acl后面是规则名称。如果请求的域名满足正则表达式中的2个域名返回true(-i是忽略大小写),则分发请求至webserver的作用域。
    acl img hdr(host) -i img.test.com
    #如果访问img.test.com就分发到imgserver这个作用域。
    use_backend webserver if web
    use_backend imgserver if img
    default_backend webserver

backend webserver
    mode http
    balance roundrobin               #默认的负载均衡方式
    #balance source                  #类似Nginx的ip_hash,balance source 保存session值
    #balance leastconn               #最小连接
    cookie  SERVERID insert indirect
    option  httpchk /index.php   
    server Real1 192.168.15.128:80 cookie Real1 check inter 1500 rise 3 fall 3 weight 1
    server Real2 192.168.15.130:80 cookie Real2 check inter 1500 rise 3 fall 3 weight 1
    server Real3 192.168.15.140:80 cookie Real3 check inter 1500 rise 3 fall 3 weight 1
    #服务器定义,"cookie Real1"表示serverid为Real1,"check inter 1500"是检测心跳频率,"rise 3"是3次正确认为服务器可用,"fall 3"是3次失败认为服务器不可用,weight代表权重

backend imgserver
    mode http
    balance  roundrobin  
    option  httpchk /index.php
    server Real1 192.168.15.128:80 check inter 1500 rise 3 fall 3 weight 1
    server Real2 192.168.15.130:80 check inter 1500 rise 3 fall 3 weight 1
    server Real3 192.168.15.140:80 check inter 1500 rise 3 fall 3 weight 1

    errorfile 403 /etc/haproxy/errorfiles/403.http
    errorfile 500 /etc/haproxy/errorfiles/500.http
    errorfile 502 /etc/haproxy/errorfiles/502.http
    errorfile 503 /etc/haproxy/errorfiles/503.http
    errorfile 504 /etc/haproxy/errorfiles/504.http

动静分离:

global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 notice
        maxconn 5000
        chroot /var/lib/haproxy
        user haproxy
        group haproxy
        daemon
defaults
        log     global
        mode    http 
        option  httplog
        option  httpclose
        option  dontlognull  
        option  forwardfor   
        option  redispatch   
        retries 3
        maxconn 4000
        contimeout      8000
        clitimeout      80000
        srvtimeout      80000
listen stats  192.168.15.135:9999
    mode http
    stats enable
    stats refresh 5s
    stats hide-version
    stats realm Haproxy Statistics 
    stats uri  /haproxy-status
    stats auth test:123456
    acl allow src 192.168.15.0/16
    stats admin if TRUE
frontend  main *:80       #前端代理
    acl url_static     path_beg   -i  /static /images /javascript /stylesheets
    acl url_static     path_end   -i  .jpg .gif .png .css .js
    acl url_dynamic    path_end   -i  .php
    use_backend static_servers    if url_static
    default_backend           dynamic_servers 
backend static_servers   #后端的静态请求响应
    balance     roundrobin
    server      static 192.168.15.128:80 inter 3000 rise 2 fall 3 check maxconn 5000
backend dynamic_servers  #后端的动态请求响应
    balance     roundrobin
    server  dynamic1 192.168.15.130:80 inter 3000 rise 2 fall 3 check maxconn 5000
    server  dynamic2 192.168.15.140:80 inter 3000 rise 2 fall 3 check maxconn 5000

    errorfile 403 /etc/haproxy/errorfiles/403.http
    errorfile 500 /etc/haproxy/errorfiles/500.http
    errorfile 502 /etc/haproxy/errorfiles/502.http
    errorfile 503 /etc/haproxy/errorfiles/503.http
    errorfile 504 /etc/haproxy/errorfiles/504.http

启动haproxy

cp /usr/local/src/haproxy-1.4.24/examples/haproxy.init  /etc/rc.d/init.d/haproxy

chmod +x  /etc/rc.d/init.d/haproxy

chkconfig haproxy on

cp /usr/local/src/haproxy-1.4.24/haproxy /usr/sbin/haproxy

/etc/init.d/haproxy start

设置HAProxy日志

“/etc/rsyslog.d”目录下创建haproxy日志配置文件

local0.=info -/var/log/haproxy.log         #haproxy.log保存http日志

local0.notice -/var/log/haproxy-status.log #haproxy-status.log记录haproxy状态变更

vi /etc/rsyslog.d/haproxy.conf

$ModLoad imudp       #imudp是模块名,支持UDP协议
$UDPServerRun 514   #允许514端口接收使用UDP和TCP协议转发过来的日志,rsyslog在默认情况下在514端口监听UDP
$template Haproxy,"%msg%n"
local0.=info -/var/log/haproxy.log;Haproxy
local0.notice -/var/log/haproxy-status.log;Haproxy
### keep logs in localhost ##
local0.* ~

vim /etc/sysconfig/rsyslog

SYSLOGD_OPTIONS="-c 2 -r -m 0"
#各参数作用:
#-c 指定运行兼容模式。
#-r 接收远程日志
#-x 在接收客户端消息时,禁用DNS查找。需和-r参数配合使用。
#-m 标记时间戳。单位是分钟,为0时,表示禁用该功能。

重启rsyslog服务

service rsyslog restart

日志轮转配置

vim /etc/logrotate.d/haproxy

/var/log/haproxy.log {
    missingok
    notifempty
    sharedscripts
    rotate 5
    daily
    compress
    postrotate
        reload rsyslog &gt;/dev/null 2&gt;&amp;1 ||truep;true
    endscript
}

创建定时任务:

59 23 * * * root /usr/sbin/logrotate -f /etc/logrotate.conf &gt;/dev/null 2&gt;&amp;1
service crond restart

配置keepalived

wget http://www.keepalived.org/software/keepalived-1.2.15.tar.gz

tar -zxvf keepalived-1.2.15.tar.gz

cd keepalived-1.2.15

./configure --sysconf=/etc/  --with-kernel-dir=/usr/src/kernels/2.6.32-573.8.1.el6.x86_64

make &amp;&amp; make install

ln -s /usr/local/sbin/keepalived  /sbin/  

配置keepalived.conf:

主:

! Configuration File for keepalived
global_defs {
   notification_email {
    [email protected]
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id Haprxoy_Master    
}
vrrp_script check_haproxy {
  script "/usr/local/src/check_haproxy.sh"
  interval 4
  weight 2
}
vrrp_instance VI_1 {
 #state MASTER
  state BAKCUP
  nopreempt 
  interface bond0
  smtp_alert
  virtual_router_id 66
  priority 100
  advert_int 1
  authentication {
  auth_type PASS
  auth_pass 1111
 }
 track_script {
  check_haproxy
 }
 virtual_ipaddress {
  192.168.15.135/24 broadcast 192.168.15.255 dev bond0 label bond0:1
 }
}

备:

! Configuration File for keepalived
global_defs {
   notification_email {
     [email protected]
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id Haprxoy_BACKUP   
}
vrrp_script check_haproxy {
 script "/usr/local/src/check_haproxy.sh"
 interval 4
 weight 2
}
vrrp_instance VI_1 {
  state BACKUP
  interface bond0
  smtp_alert
  virtual_router_id 66
  priority 88
  advert_int 1
  authentication {
  auth_type PASS
  auth_pass 1111
 }
 track_script {
  check_haproxy
 }
 virtual_ipaddress {
  192.168.15.135/24 broadcast 192.168.15.255 dev bond0 label bond0:1
 }
}

为防止haproxy异常关闭导致keepalived不自动切换

#!/bin/bash
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
     /etc/init.d/haproxy  start
fi
sleep 3
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
       /etc/init.d/keepalived stop
fi

chmod +x /usr/local/src/check_haproxy.sh

Keepalived.conf配置完毕,启动keepalived服务:/etc/init.d/keepalived start

关闭其中任何一个服务,访问正常,测试OK。

未分类

未分类

未分类

遇到的问题:

备机启动报错“Starting proxy LOADBAL: cannot bind socket”,原因为nginx进程占用80端口造成,停止nginx后正常。如果“ip_nonlocal_bind”未设置为1(启动haproxy的时候,允许忽视VIP的存在)也会造成相同问题

启动keepalived后日志出现“didn’t respond to SIGTERM”,需将“interval”时间设置相对较长(同时检查iptables状态)