一、ACL
1. acl概述
haproxy的ACL用于实现基于请求报文的首部、响应报文的内容或其他的环境状态信息来做出转发决策,这大大增加了其配置弹性。其配置法则一般分为两部,首先定义ACL,既定义一个测试条件,而后在条件得到满足时执行某特定动作,如阻止访问或者转发至某特定的后端。
haproxy配置文件的详解可以看这篇博客:haproxy基础配置文件详解,这里不再赘述。默认以下配置实验中,已经配置了监控和激活日志。
定义ACL的语法格式如下:
acl <aclname> <criterion> [flags] [operator] [<value>] ...
(1)aclname:ACL名称,可使用字母,数字, :, ., -, _ ,区分字符大小写
(2)criterion: 指明检查条件。各种条件 :dst 目标IP,dst_port 目标PORT,src 源IP,src_port 源PORT。
(3)flags:acl支持的标志位。-i:不区分中模式字符的大小写;–:标志符的强制结束标记,在模式中的字符串像标记符时使用;
(4)value:acl测试条件支持的值。有以下几类:整数或整数范围、字符串、正则表达式、IP地址及网络地址等等。
(5)常用的字符串:path,提取请求的URL路径;path_beg 匹配路径开头,path_end 匹配路径结尾;url,提取请求中的URL;url_beg URL开头 匹配协议,url_end URL结尾;hdr_beg()提取在一个HTTP请求报文的首部,hdr_end()提取在一个HTTP请求报文的尾部。
2. acl配置
主机名 | workstation | serverb | server2 | server3 |
---|---|---|---|---|
IP地址 | 192,168.1.104 | 192.168.1.116 | 192.168.1.102 | 192.168.1.103 |
职能 | 外部客户端 | haproxy调度器 | RS节点 | RS节点 |
2.1 基于IP地址的访问控制
通过配置文件中的acl可以让指定IP禁止访问到调度器,并且可以使用关键字errorloc把错误码页面重定向到指定的访问页面。
[root@serverb ~]# vim /etc/haproxy/haproxy.cfg
frontend main *:80
acl blacklist src 192.168.1.104 //定义ACL名为blacklist,设定条件为指定的源IP
block if blacklist //关键词block表示禁止访问,禁止访问的错误码为403
errorloc 403 http://192.168.1.116:8000 //为了用户体验,使用errorloc将错误重定向到指定访问页面
default_backend app
backend app
balance roundrobin
server app1 192.168.1.103:80 check
server app2 192.168.1.102:80 check
[root@serverb ~]# systemctl reload haproxy
[root@serverb ~]# vim /etc/httpd/conf/httpd.conf
Listen 8000
[root@serverb ~]# systemctl start httpd
[root@serverb ~]# cd /var/www/html/
[root@serverb html]# vim index.html
sorry,try again later
2.2 七层请求的访问控制
对于访问请求,也可以通过设置关键词限制访问路径。当遇到禁止访问的403错误码时,也可以使用关键字redirect重定向用户请求。
[root@serverb ~]# vim /etc/haproxy/haproxy.cfg
frontend main *:80
acl blacklist src 192.168.1.104
acl testfile path /test.html //path设定请求路径,(测试时,需要保证节点上此路径存在 并且可以正常访问)
http-request deny if testfile blacklist //关键词http-request表示用户请求,deny表示禁止访问。
redirect location http://www.baidu.com if blacklist //关键字redirect可以重定向访问请求,location设定重定向的目标路径
default_backend app
backend app
balance roundrobin
server app1 192.168.1.103:80 check
server app2 192.168.1.102:80 check
[root@serverb ~]# systemctl reload haproxy
///在后端服务器上编辑test.html,保证访问路径存在///////
[root@server2 ~]# cd /var/www/html/
[root@server2 html]# vim test.html
test //在节点上设定限制的请求路径
2.3 动静分离
根据实际情况客户方访问请求,将不同类型的访问请求调转到不同的后端服务器。一个ACL定义了两个条件,如果用户的请求满足path中带有 /images 这些字符开头的,或者path是以.jpg这些字符结尾的就匹配ACL定义url_static。满足ACL定义的请求为静态请求,被调度到后端的static服务器上,不满足以上两个条件的请求默认调度app服务器上。
///动态站点server3,采用php设置//////
[root@server3 ~]# yum install -y php //安装php模块
[root@server3 ~]# cd /var/www/html/
[root@server3 html]# vim index.php
index.php
<?php
phpinfo()
?>
[root@server3 html]# systemctl restart httpd //重启httpd,加载php模块
设置动态站点,采用的是php,一定要注意的是,编辑完index.php,要重启Apache服务,php模块才能生效。
//////////在haproxy调度器中 编辑配置文件////////
[root@serverb ~]# vim /etc/haproxy/haproxy.cfg
frontend main *:80
acl url_static path_beg -i /images //设定条件
acl url_static path_end -i .jpg
use_backend static if url_static //满足调度到静态站点
default_backend app //不满足就是访问动态站点
backend static
balance roundrobin
server static 192.168.1.102:80 check //添加静态后端服务器。
backend app
balance roundrobin
server app 192.168.1.103:80 check //添加动态后端服务器
[root@serverb ~]# systemctl reload haproxy
2.4 读写分离
当客户写入内容和读取内容的请求会被调转到不同的后端服务器。
配置haproxy
[root@serverb ~]# vim /etc/haproxy/haproxy.cfg
frontend main *:80
acl read_request method GET //method表示“方式”,“读”有两种方式,GET HEAD
acl read_request method HEAD
acl write_request method PUT //“写”的两种方式,PUT POST
acl write_request method POST
use_backend static if read_request //读请求 调度static后端服务器
use_backend app if write_request //写请求 调度app后端服务器
backend static
balance roundrobin
server static 192.168.1.102:80 check
backend app
balance roundrobin
server app 192.168.1.103:80 check
[root@serverb ~]# systemctl reload haproxy
配置后端服务器:
两台服务器都要安装php插件,都使用php编辑“读”时的发布页面和文件写入的信息页面。同时为了验证读写分离,两台后端服务器,均新建上传目录。
[root@server2 ~]# yum install php -y
[root@server2 ~]# cd /var/www/html/
[root@server2 html]# vim index.php //编辑“读”的页面
<html>
<body>
<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
[root@server2 html]# vim upload_file.php //编辑上传的发布页面
<?php
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 2000000))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $_FILES["file"]["name"]);
echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
}
}
}
else
{
echo "Invalid file";
}
?>
[root@server2 html]# mkdir /var/www/html/upload //建立上传目录
[root@server2 html]# chmod 777 /var/www/html/upload //设定目录权限,允许写入
[root@server2 html]# systemctl restart httpd //重启,php模块生效
访问测试
二、haproxy+keepalived实现高可用
haproxy部署了于一个机器,存在单点故障风险,我们可以通过配置keepalived加以高可用,其中一个haproxy宕机以后,通过keepalived实现另外一个haproxy备机接管做高可用。
实验设备:设定VIP为192.168.1.100
主机名 | servera | serverb | server2 | server3 |
---|---|---|---|---|
IP | 192.168.1.136 | 192.168.1.116 | 192.168.1.102 | 192.168.1.103 |
职能 | haproxy keepalived 主机 | haproxy keepalived 备机 | RS服务器 | RS服务器 |
haproxy配置
haproxy在上面的实验中已经配置完成了,只需要在serveras上重复配置即可。这里不在赘述。
[root@servera ~]# yum install -y haproxy
frontend main *:80
default_backend app
backend app
balance roundrobin
server app1 192.168.1.103:80 check
server app2 192.168.1.102:80 check
[root@serverb ~]# scp /etc/haproxy/haproxy.cfg root@servera:/etc/haproxy/
keepalived配置
[root@servera ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_haproxy { //VRRP 脚本声明
script "/opt/check_haproxy.sh" //周期性执行的脚本
interval 2 //运行脚本的间隔时间2秒
weight 0 //权重,priority值减去此值要小于备服务的priority值
}
vrrp_instance VI_1 {
state MASTER //备机只需要在此次改为 state BACKUP
interface ens33
virtual_router_id 51
priority 100 //备机将此处改为priority 50 备机优先级应该低于主机
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script { //脚本监控状态
check_haproxy
}
virtual_ipaddress { //设置虚拟IP地址
192.168.1.100
}
}
编辑周期性可执行脚本
[root@serverb ~]# vim /opt/check_haproxy.sh
#!/bin/bash
systemctl status haproxy &> /dev/null || systemctl restart haproxy &> /dev/null
killall -0 haproxy //判断是否有进程
if [ $? -ne 0 ];then
systemctl stop keepalived
fi
[root@serverb ~]# chmod 755 /opt/check_haproxy.sh //可执行权限
配置完成后,两台服务器都启动keepalived: systemctl start keepalived.service
验证:正常情况下 keepalived主机上存在VIP,当手动破坏主机上haproxy的配置文件,导致主机haproxy无法正常启动时,备机会接管主机上的资源,VIP转移到备机上。而客户端访问时,不受主机还是备机接管资源的影响。