0
点赞
收藏
分享

微信扫一扫

第十八周作业

灵魂跑者 2022-05-03 阅读 182

一、简述keepalived工作原理

1.Keepalived 定义

Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以利用其来避免单点故障。一个LVS服务会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候, 备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。Keepalived是VRRP的完美实现,因此在介绍keepalived之前,先介绍一下VRRP的原理。

2.VRRP 协议简介

在现实的网络环境中,两台需要通信的主机大多数情况下并没有直接的物理连接。对于这样的情况,它们之间路由怎样选择?主机如何选定到达目的主机的下一跳路由,这个问题通常的解决方法有二种:

  • 在主机上使用动态路由协议(RIP、OSPF等)

  • 在主机上配置静态路由

很明显,在主机上配置动态路由是非常不切实际的,因为管理、维护成本以及是否支持等诸多问题。配置静态路由就变得十分流行,但路由器(或者说默认网关default gateway)却经常成为单点故障。VRRP的目的就是为了解决静态路由单点故障问题,VRRP通过一竞选(election)协议来动态的将路由任务交给LAN中虚拟路由器中的某台VRRP路由器。

3.VRRP 工作机制

在一个VRRP虚拟路由器中,有多台物理的VRRP路由器,但是这多台的物理的机器并不能同时工作,而是由一台称为MASTER的负责路由工作,其它的都是BACKUP,MASTER并非一成不变,VRRP让每个VRRP路由器参与竞选,最终获胜的就是MASTER。MASTER拥有一些特权,比如,拥有虚拟路由器的IP地址,我们的主机就是用这个IP地址作为静态路由的。拥有特权的MASTER要负责转发发送给网关地址的包和响应ARP请求。

VRRP通过竞选协议来实现虚拟路由器的功能,所有的协议报文都是通过IP多播(multicast)包(多播地址224.0.0.18)形式发送的。虚拟路由器由VRID(范围0-255)和一组IP地址组成,对外表现为一个周知的MAC地址。所以,在一个虚拟路由 器中,不管谁是MASTER,对外都是相同的MAC和IP(称之为VIP)。客户端主机并不需要因为MASTER的改变而修改自己的路由配置,对客户端来说,这种主从的切换是透明的。

在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP通告信息(VRRPAdvertisement message),BACKUP不会抢占MASTER,除非它的优先级(priority)更高。当MASTER不可用时(BACKUP收不到通告信息), 多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常快速的(<1s),以保证服务的连续性。由于安全性考虑,VRRP包使用了加密协议进行加密。

4.VRRP 工作流程

(1).初始化:

路由器启动时,如果路由器的优先级是255(最高优先级,路由器拥有路由器地址),要发送VRRP通告信息,并发送广播ARP信息通告路由器IP地址对应的MAC地址为路由虚拟MAC,设置通告信息定时器准备定时发送VRRP通告信息,转为MASTER状态;否则进入BACKUP状态,设置定时器检查定时检查是否收到MASTER的通告信息。

(2).Master

  • 设置定时通告定时器;

  • 用VRRP虚拟MAC地址响应路由器IP地址的ARP请求;

  • 转发目的MAC是VRRP虚拟MAC的数据包;

  • 如果是虚拟路由器IP的拥有者,将接受目的地址是虚拟路由器IP的数据包,否则丢弃;

  • 当收到shutdown的事件时删除定时通告定时器,发送优先权级为0的通告包,转初始化状态;

  • 如果定时通告定时器超时时,发送VRRP通告信息;

  • 收到VRRP通告信息时,如果优先权为0,发送VRRP通告信息;否则判断数据的优先级是否高于本机,或相等而且实际IP地址大于本地实际IP,设置定时通告定时器,复位主机超时定时器,转BACKUP状态;否则的话,丢弃该通告包;

(3).Backup

  • 设置主机超时定时器;

  • 不能响应针对虚拟路由器IP的ARP请求信息;

  • 丢弃所有目的MAC地址是虚拟路由器MAC地址的数据包;

  • 不接受目的是虚拟路由器IP的所有数据包;

  • 当收到shutdown的事件时删除主机超时定时器,转初始化状态;

  • 主机超时定时器超时的时候,发送VRRP通告信息,广播ARP地址信息,转MASTER状态;

  • 收到VRRP通告信息时,如果优先权为0,表示进入MASTER选举;否则判断数据的优先级是否高于本机,如果高的话承认MASTER有效,复位主机超时定时器;否则的话,丢弃该通告包;

5.ARP查询处理

当内部主机通过ARP查询虚拟路由器IP地址对应的MAC地址时,MASTER路由器回复的MAC地址为虚拟的VRRP的MAC地址,而不是实际网卡的 MAC地址,这样在路由器切换时让内网机器觉察不到;而在路由器重新启动时,不能主动发送本机网卡的实际MAC地址。如果虚拟路由器开启的ARP代理 (proxy_arp)功能,代理的ARP回应也回应VRRP虚拟MAC地址;

二、编译安装haproxy

安装lua环境

1.1 安装依赖包

[root@centos7 ~]# yum install gcc readline-devel

1.2 下线lua源码包并解压

[root@centos7 ~]#wget http://www.lua.org/ftp/lua-5.3.5.tar.gz

[root@centos7 ~]# tar xvf lua-5.3.5.tar.gz -C /usr/local/src

1.3 进行编译

[root@centos7 ~]# cd /usr/local/src/lua-5.3.5

[root@centos7 lua-5.3.5]# make linux test#查看编译安装的版本

[root@centos7 lua-5.3.5]#src/lua -v

Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio

安装haproxy

2.1安装依赖包

[root@centos7 ~]#yum -y install gcc openssl-devel pcre-devel systemd-devel

2.2下载源码包

[root@centos7 ~]#wget https://www.haproxy.org/download/2.2/src/haproxy-2.2.20.tar.gz

[root@cetnos7 ~]#tar xvf haproxy-2.2.20.tar.gz

[root@cetnos7 ~]#cd haproxy-2.2.20/

[root@cetnos7 haproxy-2.2.20]#make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_LUA=1 LUA_INC=/usr/local/src/lua-5.3.5/src/ LUA_LIB=/usr/local/src/lua-5.3.5/src/

[root@cetnos7 haproxy-2.2.20]#make install PREFIX=/apps/haproxy

[root@cetnos7 haproxy-2.2.20]#ln -s /apps/haproxy/sbin/haproxy /usr/sbin/

[root@cetnos7 haproxy-2.2.20]#haproxy -v

HA-Proxy version 2.2.20-6e457a2 2022/01/12 - https://haproxy.org/

Status: long-term supported branch - will stop receiving fixes around Q2 2025.

Known bugs: http://www.haproxy.org/bugs/bugs-2.2.20.html

Running on: Linux 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64

2.3 准备service文件

[root@cetnos7 ~]#vim /usr/lib/systemd/system/haproxy.service[Unit]Description=HAProxy Load Balancer

After=syslog.target network.target

[Service]ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q

ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/lib/haproxy/haproxy.pid

ExecReload=/bin/kill -USR2 $MAINPIDLimitNOFILE=100000

[Install]WantedBy=multi-user.target

2.4 创建配置文件

[root@centos7 ~]# mkdir /etc/haproxy

[root@centos7 ~]# vim /etc/haproxy/haproxy.cfg

global

maxconn 100000

chroot /apps/haproxy

stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin

#uid 99

#gid 99

user haproxy

group haproxy

daemon

#nbproc 4

#cpu-map 1 0

#cpu-map 2 1

#cpu-map 3 2

#cpu-map 4 3

pidfile /var/lib/haproxy/haproxy.pid

log 127.0.0.1 local2 info

defaults

option http-keep-alive

option forwardfor

maxconn 100000

mode http

timeout connect 300000ms

timeout client 300000ms

timeout server 300000ms

listen stats

mode http

bind 0.0.0.0:9999

stats enable

log global

stats uri /haproxy-status

stats auth haadmin:123456 #状态页的登录账户和密码

listen web_port

bind 10.0.0.7:80

mode http

log global

server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5

2.5 启动haproxy

#准备socket文件目录

[root@centos7 ~]# mkdir /var/lib/haproxy

[root@centos7 ~]# useradd -r -s /sbin/nologin -d /var/lib/haproxy haproxy

[root@centos7 ~]# systemctl start haproxy

2.6 查看hapoxy的状态页面

三、总结haproxy各调度算法的实现方式及其应用场景

1.静态算法

1.1 static-rr

基于权重的轮询调度,不支持运行时利用socat进行权重的动态调整(只支持0和1,不支持其它值)及后端服务器慢启动,其后端主机数量没有限制,相当于LVS中的 wrr。

listen web_host

bind 10.0.0.7:80

mode http

log global

balance static-rr

server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5

server web2 10.0.0.27:80 weight 2 check inter 3000 fall 2 rise 5

1.2 first

根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置,此方式使用较少。不支持用socat进行动态修改权重,可以设置0和1,可以设置其它值但无效。

listen web_host

bind 10.0.0.7:80

mode http

log global

balance first

server web1 10.0.0.17:80 maxconn 2 weight 1 check inter 3000 fall 2 rise 5

server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5

2、动态算法

2.1 roundrobin

基于权重的轮询动态调度算法,支持权重的运行时调整,不同于lvs中的rr轮训模式,

HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),其每个后端backend中最多支

持4095个real server,支持对real server权重动态调整,roundrobin为默认调度算法,此算法使用广泛。

listen web_host

bind 10.0.0.7:80

mode http

log global

balance roundrobin

server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5

server web2 10.0.0.27:80 weight 2 check inter 3000 fall 2 rise 5

2.2 leastconn

leastconn加权的最少连接的动态,支持权重的运行时调整和慢启动,即:根据当前连接最少的后端服务器而非权重进行优先调度(新客户端连接),比较适合长连接的场景使用,比如:MySQL等场景。

listen web_host

bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010

mode http

log global

balance leastconn

server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5

server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5

2.3 random

在1.9版本开始增加 random的负载平衡算法,其基于随机数作为一致性hash的key,随机负载平衡对于大型服务器场或经常添加或删除服务器非常有用,支持weight的动态调整,weight较大的主机有更大概率获取新请求。

listen web_host

bind 10.0.0.7:80

mode http

log global

balance random

server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5

server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5

3、其他算法

其它算法即可作为静态算法,又可以通过选项成为动态算法

3.1 source

  • 源地址hash,基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址请求将被转发至同一个后端web服务器。此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器,默认为静态方式,但是可以通过hash-type支持的选项更改

  • 这个算法一般是在不插入Cookie的TCP模式下使用,也可给拒绝会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持cookie和缓存的场景

  • 源地址有两种转发客户端请求到后端服务器的服务器选取计算方式,分别是取模法和一致性hash

3.1.1 map-base 取模法

map-based取模法,对source地址进行hash计算,再基于服务器总权重的取模,最终结果决定将此请求转发至对应的后端服务器。此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度。缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变,hash-type 指定的默认值为此算法。

listen web_host

bind 10.0.0.7:80

mode tcp

log global

balance source

hash-type map-based #不写则默认map-based静态算法

server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 3

server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 3

3.1.2一致性hash

一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动,hash(o)mod n ,该hash算法是动态的,支持使用 socat等工具进行在线权重调整,支持慢启动。

listen web_host

bind 10.0.0.7:80

mode tcp

log global

balance source

hash-type consistent

server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5

server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5

3.4 uri

基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后,根据最终结果

将请求转发到后端指定服务器,适用于后端是缓存服务器场景,默认是静态算法,也可以通过hash-type

指定map-based和consistent,来定义使用取模法还是一致性hash。

listen web_host

bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010

mode http

log global

balance uri

server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5

server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5

3.5 url_param

url_param对用户请求的url中的 params 部分中的一个参数key对应的value值作hash计算,并由服务器

总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同

一个real server,如果无没key,将按roundrobin算法

##url_param取模法配置示例

listen web_host

bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010

mode http

log global

balance url_param userid

server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5

server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5

3.6 hdr

针对用户每个http头部(header)请求中的指定信息做hash,此处由 name 指定的http首部将会被取出并

做hash计算,然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认的轮

询调度。

#hdr取模法配置示例

listen web_host

bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010

mode http

log global

balance hdr(User-Agent)

#balance hdr(host)

server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5

server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5

3.7 rdp-cookie

rdp-cookie对远windows远程桌面的负载,使用cookie保持会话,默认是静态,也可以通过hash-type

指定map-based和consistent,来定义使用取模法还是一致性hash。

#rdp-cookie 取模法配置示例

listen RDP

bind 10.0.0.7:3389

balance rdp-cookie

mode tcp

server rdp0 10.0.0.17:3389 check fall 3 rise 5 inter 2000 weight 1

4、使用场合

四、使用haproxy的ACL实现基于文件后缀名的动静分离

4.1环境准备

3台centos8:

haproxy:10.0.0.28

静态页面:10.0.0.18

动态页面:10.0.0.8

动态页面(10.0.0.8)

部署nginx

yum install -y gcc pcre-devel openssl-devel zlib-devel lrzsz make

useradd -u 80 nginx -s /sbin/nologin

wget https://nginx.org/download/nginx-1.20.1.tar.gz

tar xf nginx-1.20.1.tar.gz

cd nginx-1.20.1/

mkdir /apps/nginx -p

./configure --prefix=/apps/nginx \

--user=nginx \

--group=nginx \

--with-http_ssl_module \

--with-http_v2_module \

--with-http_realip_module \

--with-http_stub_status_module \

--with-http_gzip_static_module \

--with-pcre \

--with-stream \

--with-stream_ssl_module \

--with-stream_realip_module

make -j 4 && make install

echo "PATH=/apps/nginx/sbin/:$PATH" >/etc/profile.d/nginx.sh

. /etc/profile.d/nginx.sh

chown nginx.nginx -R /apps/nginx/

生成service文件

cat > /usr/lib/systemd/system/nginx.service <<EOF

[Unit]

Description=nginx - high performance web server

Documentation=nginx documentation

After=network-online.target remote-fs.target nss-lookup.target

Wants=network-online.target

[Service]

Type=forking

PIDFile=/apps/nginx/run/nginx.pid

ExecStart=/apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf

ExecReload=/bin/kill -s HUP $MAINPID

ExecStop=/bin/kill -s TERM $MAINPID

LimitNOFILE=100000

[Install]

WantedBy=multi-user.target

EOF

修改配置文件

cat > /apps/nginx/conf/nginx.conf<<EOF

user  nginx;

worker_processes  2;

#error_log  logs/error.log;

#error_log  logs/error.log  notice;

#error_log  logs/error.log  info;

pid        logs/nginx.pid;

events {

    worker_connections  1024;

}

http {

    include       mime.types;

    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '

                      '$status $body_bytes_sent "$http_referer" '

                      '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;

    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    server {

        listen       80;

        server_name  wordpress;

        access_log  logs/host.access.log  main;

        location / {

            root   /data/;

            index  index.php index.html index.htm;

        }

    location ~ \.php$ {

        root /data/;

        fastcgi_pass 127.0.0.1:9000;

        fastcgi_index index.php;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        include fastcgi_params;

        }

    location ~ ^/(ping|pm_status)$ {

        include fastcgi_params;

        fastcgi_pass 127.0.0.1:9000;

        fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;

        }

    }

}

EOF

systemctl start nginx

#安装php

yum install -y php-fpm php-mysqlnd php-json

sed -Ei 's#^(listen = )\/run\/php-fpm\/www.sock#\19000#g' /etc/php-fpm.d/www.conf

sed -Ei 's/^(listen.allowed_clients.*)/;\1/g' /etc/php-fpm.d/www.conf

systemctl enable --now php-fpm.service

php测试页

cat >> /data/index.php <<EOF

<?php

phpinfo();

?>

EOF

访问测试页面

10.0.0.8/index.php

静态页面(10.0.0.18)

yum install -y nginx

cat > /usr/share/nginx/html/index.html <<EOF

Server 10.0.0.18

EOF

systemctl restart nginx

编译安装haproxy

1. lua安装

yum -y install gcc curl openssl-devel libnl3-devel net-snmp-devel make pcre-devel systemd-devel

wget http://www.lua.org/ftp/lua-5.4.3.tar.gz

tar zxf lua-5.4.3.tar.gz -C /usr/local/src

cd /usr/local/src/lua-5.4.3

make all test

2. haproxy编译安装

2.1 haproxy安装

mkdir /apps/haproxy -p

mkdir /etc/haproxy/conf.d/ -p

mkdir /var/lib/haproxy -p

wget http://www.haproxy.org/download/2.4/src/haproxy-2.4.7.tar.gz

tar xf haproxy-2.4.7.tar.gz

cd haproxy-2.4.7/

make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_LUA=1 LUA_INC=/usr/local/src/lua-5.4.3/src/ LUA_LIB=/usr/local/src/lua-5.4.3/src/

make install PREFIX=/apps/haproxy/

ln -sf /apps/haproxy/sbin/haproxy /usr/bin/

ln -sf /apps/haproxy/sbin/haproxy /usr/sbin/haproxy

useradd -s /sbin/nologin -d /var/lib/haproxy haproxy

2.2 haproxy service文件配置

cat >/usr/lib/systemd/system/haproxy.service<<EOF

[Unit]

Description=HAProxy Load Balancer

After=syslog.target network.targe

[Service]

ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/ -c -q

ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/ -p /var/lib/haproxy/haproxy.pid

ExecReload=/bin/kill -USR2 $MAINPID

LimitNOFILE=100000

[Install]

WantedBy=multi-user.target

EOF

3. haproxy 配置文件

cat>> /etc/haproxy/haproxy.cfg<<EOF

global

    maxconn 100000

    chroot /apps/haproxy

    stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin

    #uid 99

    #gid 99

    user haproxy

    group haproxy

    daemon

    #nbproc 4

    #cpu-map 1 0

    #cpu-map 2 1

    #cpu-map 3 2

    #cpu-map 4 3

    pidfile /var/lib/haproxy/haproxy.pid

    log 127.0.0.1 local2 info

defaults

    option http-keep-alive

    option forwardfor

    maxconn 100000

    mode http

    timeout connect 300000ms

    timeout client 300000ms

    timeout server 300000ms

listen stats

    mode http

    bind 0.0.0.0:9999

    stats enable

    log global

    stats uri /haproxy-status

    stats auth haadmin:123456

listen web_port

    bind 10.0.0.28:80

    mode http

    log global

    server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5

EOF

#启动服务

systemctl daemon-reload

systemctl start haproxy

配置Haproxy

cat >  /etc/haproxy/conf.d/test.cfg<<EOF

frontend magedu_http_port

    bind 10.0.0.28:80

    mode http

    balance roundrobin

    #log global

    #option httplog

    acl acl_php path_end -i .php

    acl acl_html path_end -i .html

    use_backend php_hosts if acl_php

    use_backend html_hosts if acl_html

backend php_hosts

    mode http

    server 10.0.0.8 10.0.0.8:80 check

backend html_hosts

    mode http

    server 10.0.0.18 10.0.0.18:80 check

EOF

#重启服务并查看端口

systemctl restart haproxy

ss -tnlup

测试

此时访问

10.0.0.28/index.php就会跳转到10.0.0.8/index.php

此时访问

10.0.0.28/index.html就会跳转到10.0.0.18/index.html

举报

相关推荐

0 条评论