Nginx负载均衡

介绍

负载均衡(Server Load Balancer)是将访问流量根据转发策略分发后端多台 ECS 的流量分发控制服务。负载均衡可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 负载均衡主要有如下几个功能点:

  • 负载均衡服务通过设置虚拟服务地址(IP),将位于同一地域(Region)的多台云服务器(Elastic Compute Service,简称ECS)资源虚拟成一个高性能、高可用的应用服务池;根据应用指定的方式,将来自客户端的网络请求分发到云服务器池中。
  • 负载均衡服务会检查云服务器池中ECS的健康状态,自动隔离异常状态的ECS,从而解决了单台ECS的单点问题,同时提高了应用的整体服务能力。在标准的负载均衡功能之外,负载均衡服务还具备TCP与HTTP抗DDoS攻击的特性,增强了应用服务器的防护能力。
  • 负载均衡服务是ECS面向多机方案的一个配套服务,需要同ECS结合使用。

    nginx_http_upstream_module模块

    相关参数:

  • upstream:定义后端服务器组,会引入一个新的上下文

  • server:在upstream上下文中server成员,以及相关参数
  • least_conn:最少连接调度算法,当server拥有不同权重时其为wlc
  • ip_hash:源地址hash调度算法
  • hash:基于key的hash表来实现对请求的调度,此处的key可以是文本、变量或者二者的组合。
  • keepalive connections:为每个worker进程保留的空闲的长连接数量。
  • weight= number:权重,默认为1
  • max_fails=number:失败尝试最大次数,超出此处指定的次数,server将被标记为不可用
  • fail_timeout=time:设置将服务器标记为不可用状态的超时时长
  • max_conns:当前服务器的最大并发连接数
  • backup:将服务器标记为“备用”,即所有服务器均不可用时此服务器才启动;
  • down:标记为不可用

    七层负载均衡实验

    server1作为反向代理服务器
    server2、server3作为web站点。
  1. 准备web站点 ```bash

    安装apache服务

    [root@server2 ~]# yum install httpd -y [root@server3 ~]# yum install httpd -y

启动httpd服务

[root@server2 ~]# systemctl start httpd.service [root@server3 ~]# systemctl start httpd.service

关闭防火墙和selinux

[root@server2 ~]# systemctl stop firewalld [root@server2 ~]# setenforce 0

准备网页内容

[root@server2 ~]# echo server2 > /var/www/html/index.html [root@server3 ~]# echo server3 > /var/www/html/index.html

  1. 2. 配置nginx负载均衡
  2. ```bash
  3. [root@server1 ~]# yum install epel-release.noarch -y
  4. [root@server1 ~]# yum install nginx -y
  5. # 配置负载均衡
  6. [root@server1 ~]# vim /etc/nginx/conf.d/proxy.conf
  7. upstream webservers{
  8. server 192.168.80.129 weight=4;
  9. server 192.168.80.134;
  10. }
  11. server{
  12. listen 8080;
  13. server_name 192.168.80.132:8080;
  14. location / {
  15. proxy_pass http://webservers;
  16. }
  17. }
  18. # 启动nginx并测试
  19. [root@server1 ~]# nginx -t
  20. [root@server1 ~]# systemctl start nginx
  21. [root@server1 ~]# for i in {1..10};do curl 192.168.80.132:8080;done
  22. server2
  23. server2
  24. server3
  25. server3
  26. server3
  27. server2
  28. server2
  29. server3
  30. server3
  31. server2

四层负载均衡实验

  1. 在nginx主配置文件中添加

    1. [root@server1 ~]# vim /etc/nginx/nginx.conf
    2. stream{
    3. upstream sshservers{
    4. server 192.168.80.129:22;
    5. server 192.168.80.134:22;
    6. }
    7. server{
    8. listen 192.168.80.132:22222;
    9. proxy_pass sshservers;
    10. }
    11. }
  2. 关闭防火墙和selinux

    1. [root@server1 ~]# systemctl stop firewalld
    2. [root@server1 ~]# setenforce 0
  3. 测试

ZE7%1BWVIE13)G}SP%GXCFN.png

负载均衡算法

  • 轮询(默认): 每个请求按时间顺序逐一分配到不同的后端服务,如果后端某台服务器死机,自动剔除故障系统,使用户访问不受影响。
  • weight(轮询权值):weight的值越大分配到的访问概率越高,主要用于后端每台服务器性能不均衡的情况下。或者仅仅为在主从的情况下设置不同的权值,达到合理有效的地利用主机资源。
  • ip_hash:每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的session共享问题。
  • fair:比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身不支持fair,如果需要这种调度算法,则必须安装upstream_fair模块。
  • url_hash:按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身不支持url_hash,如果需要这种调度算法,则必须安装Nginx的hash软件包。

    HAproxy负载均衡

    介绍

    HAProxy(高性能-代理)目前是一款使用广泛的软负载均衡器,它可以实现TCP/HTTP的负载均衡。

  • 特性

    • 免费开源
    • 最大并发量能达到5w
    • 支持多种负载均衡算法,同时支持session保持
    • 支持虚拟主机
    • 拥有服务监控页面,可以实时了解系统运行状态
    • 通常不做正向代理,有更好的选择(Squid)
    • 通常不做缓存代理,有更好的选择(Varnish)
    • 不会改变请求和响应报文
    • 不用于web服务器
    • 不是基于数据包的负载均衡器,看不到ip数据包

      安装部署

      1. [root@server1 ~]# yum install haproxy -y
      2. /etc/haproxy/haproxy.cfg # 主配置文件
      3. /usr/lib/systemd/system/haproxy.cfg # 守护进程服务
      4. # 默认配置
      5. [root@server1 ~]# cat /etc/haproxy/haproxy.cfg
  • 全局配置

    1. log 127.0.0.1 local2 # 定义全局的syslog服务器
    2. chroot /var/lib/haproxy # 定义工作目录
    3. pidfile /var/run/haproxy.pid # 指定PID
    4. maxconn 4000 # 定义最大并发数
    5. user haproxy # 用户名
    6. group haproxy # 组名
    7. daemon # 以守护进程的方式工作于后台
  • 默认配置:为所有其他配置字段提供默认参数,配置参数可以由下一个“defaults”所重新设定。

    1. defaults
    2. mode http # 运行模式或者协议
    3. log global # 定义每个实例启用事件和流量日志
    4. option httplog
    5. option dontlognull
    6. option http-server-close
    7. option forwardfor except 127.0.0.0/8
    8. option redispatch
    9. retries 3
    10. timeout http-request 10s
    11. timeout queue 1m
    12. timeout connect 10s
    13. timeout client 1m
    14. timeout server 1m
    15. timeout http-keep-alive 10s
    16. timeout check 10s
    17. maxconn 3000 # 定义最大并发数
  • 前端配置:定义一系列套接字,这些套接字可接受客户端请求并与之建立连接

    1. frontend main *:5000
    2. # 测试请求url是否以指定模式开头
    3. acl url_static path_beg -i /static /images /javascript /stylesheets
    4. # 测试请求url是否以指定模式结尾
    5. acl url_static path_end -i .jpg .gif .png .css .js
    6. use_backend static if url_static
    7. # 当use_backend没能匹配,指定后端的名称
    8. default_backend app
  • 后端配置 ```bash backend static balance roundrobin server static 127.0.0.1:4331 check

backend app balance roundrobin server app1 127.0.0.1:5001 check server app2 127.0.0.1:5002 check server app3 127.0.0.1:5003 check server app4 127.0.0.1:5004 check

  1. <a name="AsgFH"></a>
  2. ## 简单实验
  3. ```bash
  4. [root@server1 ~]# vim /etc/haproxy/haproxy.cfg
  5. global
  6. log 127.0.0.1 local2
  7. chroot /var/lib/haproxy
  8. pidfile /var/run/haproxy.pid
  9. maxconn 4000
  10. user haproxy
  11. group haproxy
  12. daemon
  13. stats socket /var/lib/haproxy/stats
  14. defaults
  15. mode http
  16. log global
  17. option httplog
  18. option dontlognull
  19. option http-server-close
  20. option forwardfor except 127.0.0.0/8
  21. option redispatch
  22. retries 3
  23. timeout http-request 10s
  24. timeout queue 1m
  25. timeout connect 10s
  26. timeout client 1m
  27. timeout server 1m
  28. timeout http-keep-alive 10s
  29. timeout check 10s
  30. maxconn 3000
  31. frontend main *:5000
  32. acl url_static path_beg -i /static /images /javascript /stylesheets
  33. acl url_static path_end -i .jpg .gif .png .css .js
  34. use_backend static if url_static
  35. default_backend app
  36. backend static
  37. balance roundrobin
  38. server static 192.168.10.20:8080 check
  39. backend app
  40. balance roundrobin
  41. server app1 192.168.10.20:80 check # 就改这两行
  42. server app2 192.168.10.30:80 check
  43. [root@server1 ~]# systemctl start haproxy.service
  44. [root@server1 ~]# for i in {1..10};do curl 192.168.80.132:5000;done
  45. server2
  46. server3
  47. server2
  48. server3
  49. server2
  50. server3
  51. server2
  52. server3
  53. server2
  54. server3

LVS

介绍

LB集群原理:当用户的请求过来时,会直接分发到Director Server上,然后它把用户的请求根据设置好的调度算 法,智能均衡地分发到后端真正服务器(real server)上,为了保证用户请求数据一致,需要共享存储。

  • LVS(Linux Virtual Server)Linux虚拟服务器。这是一个由章文嵩博士发起的一个开源项目,并且已经是 Linux 内 核标准的一部分。
  • LVS架构从逻辑上可分为调度层Server集群层共享存储

官方网站: http://www.linuxvirtualserver.org

组成

  • ipvs(ip virtual server):工作在内核空间,是真正生效实现调度的代码。
  • ipvsadm:工作在用户空间,负责为ipvs内核框架编写规则,定义谁是集群服务,而谁是后端真实的服务器(Real Server)
  • 相关术语介绍

    • DS:Directory Server,前端负载均衡节点
    • RS:Real Server,后端真实工作服务器
    • VIP:用户请求目标的IP地址
    • DIP:内部主机通讯的IP地址
    • RIP:后端服务器的IP地址
    • CIP:客户端的IP地址

      NAT模式

  • 当用户访问服务器集群提供的服务时,发往虚拟IP地址的请求数据包(负载均衡器的外部IP地址)到达负载均衡器

  • 负载均衡器检查数据包的目标地址和端口号。
    • 如果根据虚拟服务器规则表匹配虚拟服务器服务,则通过调度算法从集群中选择真实服务器,并将连接添加到记录已建立连接的哈希表中。然后,将目标地址和数据包的端口重写为所选服务器的目标地址和端口,并将数据包转发到服务器。
    • 当传入数据包属于此连接并且可以在哈希表中找到所选服务器时,将重写该数据包并将其转发到所选服务器。当回复数据包返回时,负载均衡器将数据包的源地址和端口重写为虚拟服务的源地址和端口。 连接终止或超时后,连接记录将在哈希表中删除。

@)5TKF(XA)56_S%FO2NS`{Y.png

  • 特点:
    • RS使用私有地址,网关时DIP
    • DIP和RS属于同一网段
    • 请求报文和响应报文都要经过DS(性能瓶颈)
    • 支持端口映射
    • RS可以使用任意操作系统

      DR模式

      (首先知道一个数据包传输是先匹配MAC地址,再匹配IP地址。)

虚拟IP地址由真实服务器和负载均衡器共享。负载均衡器的接口也配置了虚拟IP地址,用于接受请求数据包,并直接将数据包路由到选定的服务器。
所有真实服务器的非arp别名接口都配置了虚拟IP地址(真实服务器配置VIP在环回接口上且不能响应),或者将发往虚拟IP地址的数据包重定向到本地套接字,以便真实服务器可以在本地处理数据包。
负载均衡器和真实服务器必须通过HUB/Switch物理连接其中一个接口,负载均衡器只是将数据帧的MAC地址更改为所选服务器的MAC地址,然后在LAN上重新传输。这就是负载均衡器和每个服务器必须通过同一个LAN(同一个局域网)进行连接的原因。
~H1_%8N0GQCBP2GLQZ)TDDH.png

  • 特点
    • 保证前端路由将目标地址为VIP报文统统发给Director Server(不能发给RS)
    • RS可以使用私有地址;也可以是公网地址,如果使用公网地址,此时可以通过互联网对RIP进行直接访问
    • RS跟Director Server必须在同一个物理网络中(这样才能只修改MAC地址传输数据帧给真实服务器)
    • 所有的请求报文经由Director Server,但响应报文必须不能经过Director Server(直接响应客户端)
    • 不支持地址转换,也不支持端口映射
    • RS的网关绝不允许指向DIP(因为我们不允许他经过director server)
    • RS上的环回接口配置VIP的IP地址

因为ARP广播,想要保证目标地址为VIP报文发给DS,我们就需要只让LVS上响应VIP的arp请求,而real server 不响应, 即:修改RS上内核参数(arp_ignore和arp_announce)将RS上的VIP配置在环回接口的别名上,并限制其不能响应对VIP 地址解析请求。
arp_announce通告:0,1,2级
arp_ignore应答:0-8级

TUN模式

在LVS(NAT)模式的集群环境中,由于所有的数据请求及响应的数据包都需要经过LVS调度器转发,如果后端服务器的数量大于10台,则调度器就会成为整个集群环境的瓶颈。我们知道,数据请求包往往远小于响应数据包的大小。因为响 应数据包中包含有客户需要的具体数据,所以LVS(TUN)的思路就是将请求与响应数据分离,让调度器仅处理数据请求,而让真实服务器响应数据包直接返回给客户端。

IP隧道(IP tunning)是一种数据包封装技术,它可以将原始数据包封装并添加新的包头(内容包括新的源地址及端口、目标地址及端口),从而实现将一个目标为调度器的VIP地址的数据包封装,通过隧道转发给后端的真实服务器(Real Server),通过将客户端发往调度器的原始数据包封装,并在其基础上添加新的数据包头(修改目标地址为调度器选择出来的真实服务器的IP地址及对应端口),LVS(TUN)模式要求真实服务器可以直接与外部网络连接,真实服务器在收到请求数据包后 直接给客户端主机响应数据。
AZ7KAV5QZOEFUZ39P45%_M9.png

  • 特点

    • RIP、VIP、DIP全是公网地址
    • RS的网关不能是DS
    • 所有的请求报文经过DS,所有的响应报文不能经过DS
    • 不支持端口映射,RS的系统必须支持隧道

      LVS实验部署

      LVS/NAT实践

  • 环境准备

    1. DIP:192.168.80.10/24
    2. VIP:172.16.0.10/16
    3. RIP1:192.168.80.20 GATEWAY:192.168.80.10
    4. RIP2:192.168.80.30 GATEWAY:192.168.80.10
  1. 配置虚拟网络编辑器,然后给server1添加一块仅主机的网卡

6DB1WBE{1O~30PAA%HBS}XH.png
]CVSJT_KJ7M12G)P%{43A36.png

  1. 查看所有连接并修改名字

    1. [root@server1 ~]# nmcli connection show
    2. NAME UUID TYPE DEVICE
    3. ens33 36f7dae6-96b5-46e2-8d5a-1371ecd63587 ethernet ens33
    4. 有线连接 1 a37d635a-e62a-3582-9386-d262ca8d48e7 ethernet ens37
    5. [root@server1 ~]# nmcli connection modify 有线连接\ 1 con-name ens37
    6. [root@server1 ~]# nmcli connection show
    7. NAME UUID TYPE DEVICE
    8. ens33 36f7dae6-96b5-46e2-8d5a-1371ecd63587 ethernet ens33
    9. ens37 a37d635a-e62a-3582-9386-d262ca8d48e7 ethernet ens37
  2. 配置IP地址 ```bash [root@server1 ~]# nmcli connection modify ens37 ipv4.addresses 172.16.0.10/24 ipv4.method manual autoconnect yes [root@server1 ~]# nmcli connection modify ens33 ipv4.addresses 192.168.80.10/24 ipv4.dns 114.114.114.114 ipv4.gateway 192.168.80.2 ipv4.method manual autoconnect yes [root@server1 ~]# systemctl restart network [root@server1 ~]# ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo

    1. valid_lft forever preferred_lft forever

    inet6 ::1/128 scope host

    1. valid_lft forever preferred_lft forever

    2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:e6:a1:70 brd ff:ff:ff:ff:ff:ff inet 192.168.80.10/24 brd 192.168.80.255 scope global noprefixroute ens33

    1. valid_lft forever preferred_lft forever

    inet6 fe80::76b5:a9d1:4787:d28c/64 scope link noprefixroute

    1. valid_lft forever preferred_lft forever

    3: ens37: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:e6:a1:7a brd ff:ff:ff:ff:ff:ff inet 172.16.0.10/24 brd 172.16.0.255 scope global noprefixroute ens37

    1. valid_lft forever preferred_lft forever

    inet6 fe80::dac9:802b:fea6:82db/64 scope link noprefixroute

    1. valid_lft forever preferred_lft forever

======================================================================================

[root@server2 ~]# nmcli connection modify ens33 ipv4.addresses 192.168.80.20/24 ipv4.gateway 192.168.80.10 ipv4.dns 114.114.114.114 ipv4.method manual autoconnect yes [root@server2 ~]# systemctl restart network [root@server2 ~]# ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:23:76:7f brd ff:ff:ff:ff:ff:ff inet 192.168.80.20/24 brd 192.168.80.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet6 fe80::f4c9:88e6:9fd6:19e9/64 scope link noprefixroute valid_lft forever preferred_lft forever

=======================================================================================

[root@server3 ~]# nmcli connection modify ens33 ipv4.addresses 192.168.80.30/24 ipv4.gateway 192.168.80.10 ipv4.dns 114.114.114.114 ipv4.method manual autoconnect yes [root@server3 ~]# systemctl restart network [root@server3 ~]# ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:82:d3:10 brd ff:ff:ff:ff:ff:ff inet 192.168.80.30/24 brd 192.168.80.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet6 fe80::76b5:a9d1:4787:d28c/64 scope link tentative noprefixroute dadfailed valid_lft forever preferred_lft forever inet6 fe80::17d9:adf5:ff2b:21d4/64 scope link noprefixroute valid_lft forever preferred_lft forever

  1. - DS部署
  2. 1. 安装ipvsadm工具
  3. ```bash
  4. [root@server1 ~]# yum install ipvsadm -y
  1. 打开转发,配置nat

    1. [root@server1 ~]# echo 1 >> /proc/sys/net/ipv4/ip_forward
    2. [root@server1 ~]# iptables -t nat -F
    3. [root@server1 ~]# iptables -t nat -A POSTROUTING -s 192.168.80.0/24 -o ens37 -j MASQUERADE
  2. 设置wrr策略,添加RS主机

    1. [root@server1 ~]# ipvsadm -A -t 172.16.0.10:80 -s wrr
    2. [root@server1 ~]# ipvsadm -a -t 172.16.0.10:80 -r 192.168.80.20:80 -m -w 1
    3. [root@server1 ~]# ipvsadm -a -t 172.16.0.10:80 -r 192.168.80.30:80 -m -w 1
  3. 查看策略信息

    1. [root@server1 ~]# ipvsadm -ln
    2. IP Virtual Server version 1.2.1 (size=4096)
    3. Prot LocalAddress:Port Scheduler Flags
    4. -> RemoteAddress:Port Forward Weight ActiveConn InActConn
    5. TCP 172.16.0.10:80 wrr
    6. -> 192.168.80.20:80 Masq 1 0 0
    7. -> 192.168.80.30:80 Masq 1 0 0
  • RS部署

开启web服务,准备网页(记得关闭selinux和防火墙)

  1. [root@server2 ~]# echo RS2 > /var/www/html/index.html
  2. [root@server3 ~]# echo RS3 > /var/www/html/index.html
  • 测试
    1. [root@server1 ~]# curl 172.16.0.10
    2. RS2
    3. [root@server1 ~]# curl 172.16.0.10
    4. RS3

    ipvsadm命令

    ipvsadm:
    管理集群服务
    添加:-A -t|u|f service-address [-s scheduler]
    -t:TCP协议的集群
    -u:UDP协议的集群
    -f:FWM,防火墙的标记
    service-address:IP:PORT
    修改:-E
    删除:-D -t|u|f service-address

管理集群服务中的RS
添加:-a -t|u|f service-address -r server-address [-g|i|m] [-w weight]
-t|u|f service-address:事先定义好的某集群服务
r server-address: 某RS的地址,在NAT模型中,可使用IP:PORT实现端口映射;
[-g|i|m]: LVS类型 (-g: DR模型 -i: TUN模型 -m: NAT模型)
[-w weight]: 定义服务器权重
修改:-e
删除:-d -t|u|f service-address -r server-address
查看:-L|l
-n:数字格式显示主机地址和端口
—stats:统计数据
—rate:速率
—timeout:显示tcp、tcpfin和udp的会话超时时长
-c:显示当前ipvs的连接状况
删除所有的集群服务
保存规则
-S
# ipvsadm -S > /path/to/somefile
载入此前的规则:
-R
# ipvsadm -R < /path/form/somefile

LVS/DR实践

  • 环境准备

    1. DIP:192.168.10.10/24
    2. RIP1:192.168.10.20
    3. RIP2:192.168.10.30
    4. VIP:192.168.10.100
  • DS部署

    1. [root@server1 ~]# ifconfig ens33:0 192.168.10.100 broadcast 192.168.10.255 netmask
    2. 255.255.255.0 up
    3. [root@server1 ~]# route add -host 192.168.10.100 dev ens33:0
    4. [root@server1 ~]# ipvsadm -A -t 192.168.10.100:80 -s wrr
    5. [root@server1 ~]# ipvsadm -a -t 192.168.10.100:80 -r 192.168.10.20:80 -m -w 2
    6. [root@server1 ~]# ipvsadm -a -t 192.168.10.100:80 -r 192.168.10.30:80 -m -w 1
  • RS部署

    1. [root@server2 ~]# ifconfig lo:0 192.168.80.100 broadcast 192.168.80.100 netmask 255.255.255.255 up
    2. [root@server2 ~]# route add -host 192.168.80.100 lo:0
    3. [root@server2 ~]#echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
    4. [root@server2 ~]#echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
    5. [root@server2 ~]#echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
    6. [root@server2 ~]#echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
    7. 在所有RS上部署

    调度算法

    轮询调度(RR)

    就是将依次循环的将请求调度到不同服务器上,该算法的最大特点就是简单。轮询算法假设所有服务器处理请求的能力都是一样的,调度器会平均分配给每个真实服务器,不管后端RS的处理能力,非常均衡地分发下去。

    加权轮询调度

    相对于轮询调度增加了权重地概念,可以给RS设置权重,权重越高,分发的请求越多。权重的取值范围1-100,是对rr算法的一种优化补充,LVS会考虑每台RS的性能,并给每台服务器添加权值,如果服务器A的权值为1,服务器B的权值为2,那么服务器B会收到服务器A两倍的请求。权值越高,处理的请求越多。

    目标地址hash

    根据请求的目标IP地址,作为散列键(HashKey)从静态分布的散列表中找出对应的服务器,若该服务器可用且未超载,则将请求发送给该服务器,否则返回空。

    源地址hash

    根据请求的源地址,作为散列键(HashKey)从静态分布的散列表中找出对应的服务器,若该服务器可用且未超载,则将请求发送给该服务器,否则返回空。

    最少链接

    这个算法会根据后端 RS 的连接数来决定把请求分发给谁,比如 RS1 连接数比 RS2 连接数少,那么请求就优先发给 RS1

    加权最少链接(WLC)

    增加权重概念,使连接数与其权值成比例。

    最短延迟调度

    在WLC基础上改进,当请求到达DS,DS会先判断RS的开销:(活动连接数+1)/权重,该算法不考虑非活动连接。+1的目的是为了考虑加权的时候,非活动连接过多缺陷:当权限过大的时候,会倒 置空闲服务器一直处于无连接状态。

    NQ永不排队/最少队列调度

    无需队列。如果有台 realserver的连接数=0就直接分配过去,不需要再进行sed运算,保证不会有一个主机很空闲。
    不考虑非活动连接,才用NQ,对于DNS的UDP不需要考虑非活动连接,而httpd的处于保持状态的服务就需要考虑非活动连接给服务器的压力。

    基于局部性的最少连接

    是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。该算法根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在, 或者该服务器超载且有服务器处于一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器。

    带复制的基于局部性最少连接

    该调度算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。它与LBLC算法的不同之处是它要维护从一个目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。
    该算法根据请求的目标IP地址找出该目标IP地址对应的服务器组,按”最小连接”原则从服务器组中选出一台服务器

  • 若服务器没有超载,将请求发送到该服务器;

  • 若服务器超载,则按“最小连接”原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。
  • 同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。

LVS Nginx HAProxy 对比

  • nginx工作在第七层,注重性能和效率,支持正则(比HAproxy更强大和灵活)、动静分离(前端静态资源和后端请求分离,提升静态资源访问速度,可以把静态资源放入CDN实现用户就近访问);不支持url检测,欠缺session保持和cookie引导。
  • lvs工作在第四层仅作分发使用,抗负载能力最强,工作稳定(自身有完整双机热备方案),不支持正则和动静分离,配置性低(如果网站应用庞大配置及维护就比较复杂)。
  • HAproxy可以工作在4、7层(支持多网段),支持虚拟主机,支持url检测、session保持和cookie引导,和LVS一样本身只是负载均衡器(负载均衡效率比nginx更高);可以对MySQL节点负载均衡,可是当后端MySQL slave节点超过10台时性能不如LVS。

Keepalived

简介

  • Keepalived是Linux下一个轻量级的高可用解决方案,Keepalived起初是为了LVS设计的,用于监控集群系统中服务器节点的状态,如果某个服务器节点出现故障,Keepalived将检测到然后将故障节点从集群系统中剔除。
  • 后来Keepalived又加入了VRRP功能,VRRP(Virtual Router Redundancy Protocol)虚拟路由冗余协议是为了解决静态路由中出现的单点故障问题,通过VRRP可以实现网络不间断稳定运行,因此VRRP一方面具有服务器状态检测和故障隔离功能,另一方面也有HAcluster功能
  • 健康检查失败切换是Keepalived的两大核心功能。所谓健康检查就是通过tcp三次握手、icmp请求、http请求、udp echo请求等方式对负载均衡器后面的实际服务器(通常是承载真实业务的服务器)进行保活;而失败切换主要是应用于配置了主备模式的负载均衡器,利用VRRP维持主备负载均衡器的心跳,当主负载均衡器出现问题时由备负载均衡器承载对应业务,以保证最大限度减少流量损失,并提供稳定服务。
  • 工作原理

    • 网络层:通过ICMP协议向后端服务器集群发送报文
    • 传输层:利用TCP协议的端口连接和扫描技术检测服务器集群是否正常
    • 应用层:自定义Keepalived的工作方式(脚本)

      VRRP协议

  • VRRP是一种容错的主备模式协议,保证当主机的下一条路由出现故障时,由另一台路由器代替出现故障的路由器进行工作。通过VRRP可以在网络出现故障的时候进行透明的设备切换而不影响主机之间的数据通信。

  • 虚拟路由器:VRRP组中所有的路由器,拥有虚拟的IP+MAC(00-00-5e-00-01-VRID)地址
    • 主路由器:虚拟路由器内部通常只有一台物理路由器对外提供服务,主路由器是由选举算法产生的,对外提供各种网络功能。
    • 备份路由器VRRP组中除主路由器以外所有的路由器,不对外提供任何服务,只接受主路由器的通告,当主路由器挂掉后,重新进行选举算法接替master路由器。

C9JG7%$A$H6{48_Y6VRIXDH.png

  • 选举机制
    • 优先级
    • 抢占模式下,优先级高的路由器一旦加入,就直接成为Master
    • 非抢占模式下,只要Master不挂,优先级高的路由器只能等待。
  • 三种状态

    • initialize:系统启动后进入initialize状态
    • Master状态
    • Backup状态

      体系结构

      MF45NE0GX4)W(0NO%SB82S1.png
  • Shceduler - I/O Multiplexer:是一种I/O复用分发调度器,负责安排Keepalived所有内部的任务请求

  • Memory Mngt:是一个内存管理机制,这个框架提供了访问内存的一些通用方法。
  • Control Plane:是keepalived的控制面板,可以实现对配置文件的编译和解析。
  • Core components
    • Watchdog:是计算机领域中极为简单且有效的检测工具,Keepalived正是通过它监控Checkers和VRRP进程的。
    • Checkers:是Keepalived的最基础、最主要的功能,实现对服务器运行状态的检测和故障隔离。
    • VRRP Stack:是keepalive后来引用VRRP的功能,可以实现HA集群中的失败切换,负责负载均衡器之间的失败切换fail over。
    • IPVS wrapper:是IPVS功能的一个实现,IPVS wrapper模块将设置好的IPVS规则发送到内核空间并且提供给IPVS模块,最终实现IPVS的负载功能。
    • Netlink Reflector:用来实现高可用集群失败切换时,虚拟IP(VIP)的设置和切换。
  • keepalived运行时会启动三个进程
    • core:负责主进程的启动,维护和全局配置文件的加载
    • check:健康检查
    • vrrp:实现vrrp协议

小结:keepalived实现了健康检测、故障隔离、失败切换(vrrp==高可用)

keepalived+nginx实验

  • 环境准备

    1. node1Nginx1):192.168.10.10
    2. node2Nginx2):192.168.10.20
    3. node3WEB1):192.168.10.30
    4. node4WEB2):192.168.10.40
    5. VIP192.168.10.100
  • 准备后端真实web服务器 ```bash [root@server3 ~]# yum install httpd -y [root@server3 ~]# systemctl stop firewalld [root@server3 ~]# setenforce 0 [root@server3 ~]# echo “

    This is RS1

    “ > /var/www/html/index.html [root@server3 ~]# systemctl start httpd.service

[root@server4 ~]# yum install httpd -y [root@server4 ~]# systemctl stop firewalld [root@server4 ~]# setenforce 0 [root@server4 ~]# echo “

This is RS2

“ > /var/www/html/index.html [root@server4 ~]# systemctl start httpd.service

  1. - 准备nginx负载均衡节点
  2. ```bash
  3. [root@server1 ~]# yum install epel-release.noarch -y
  4. [root@server1 ~]# yum install nginx -y
  5. [root@server1 ~]# vim /etc/nginx/conf.d/proxy.conf
  6. upstream webservers{
  7. server 192.168.80.30;
  8. server 192.168.80.40;
  9. }
  10. server{
  11. listen 8080;
  12. server_name 192.168.80.10;
  13. location / {
  14. proxy_pass http://webservers;
  15. }
  16. }
  17. [root@server1 ~]# systemctl start nginx
  18. [root@server1 ~]# systemctl stop firewalld
  19. [root@server1 ~]# setenforce 0
  20. [root@server2 ~]# yum install epel-release.noarch -y
  21. [root@server2 ~]# yum install nginx -y
  22. [root@server1 ~]# scp /etc/nginx/conf.d/proxy.conf root@192.168.80.20:/etc/nginx/conf.d/
  23. [root@server2 ~]# vim /etc/nginx/conf.d/proxy.conf
  24. # 将server_name改为192.168.80.20即可
  25. [root@server2 ~]# systemctl stop firewalld
  26. [root@server2 ~]# setenforce 0
  27. [root@server2 ~]# systemctl start nginx
  • keepalived部署

    1. [root@server1 ~]# yum install keepalived -y
    2. [root@server1 ~]# mv /etc/keepalived/keepalived.conf{,.bak}
    3. [root@server1 ~]# vim /etc/keepalived/keepalived.conf
    4. global_defs{
    5. router_id server1 # server2修改
    6. }
    7. vrrp_instance VI_1{
    8. state MASTER # server2节点BACKUP
    9. interface ens33
    10. virtual_router_id 10
    11. priority 100 # server2优先级小于100
    12. advert_int 1
    13. authentication{
    14. auth_type PASS
    15. auth_pass 1111
    16. }
    17. virtual_ipaddress{
    18. 192.168.80.100
    19. }
    20. }
  • 定义脚本检测nginx是否正常 ```bash [root@server1 ~]# vim /usr/local/src/check_nginx_pid.sh

    !/bin/bash

    nginx_process_number=ps -C nginx --no-header | wc -l if [ $nginx_process_number -eq 0 ];then

    systemctl restart nginx

    1. nginx_process_number=`ps -C nginx --no-header | wc -l`
    2. if [ $nginx_process_number -eq 0 ];then
    3. exit 1
    4. else
    5. exit 0
    6. fi

    else

    1. exit 0

    fi [root@server1 ~]# chmod +x /usr/local/src/check_nginx_pid.sh

[root@server1 ~]# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { router_id node1 }

定义script

vrrp_script chk_http_port { script “/usr/local/src/check_nginx_pid.sh” interval 1 weight -2 # 优先级-2 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 10 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 }

  1. # 调用script脚本
  2. track_script {
  3. chk_http_port
  4. }
  5. virtual_ipaddress {
  6. 192.168.80.100
  7. }

}

[root@server1 ~]# systemctl start keepalived [root@server2 ~]# systemctl start keepalived

  1. - 测试
  2. ```bash
  3. [root@server1 ~]# ip a
  4. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  5. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  6. inet 127.0.0.1/8 scope host lo
  7. valid_lft forever preferred_lft forever
  8. inet6 ::1/128 scope host
  9. valid_lft forever preferred_lft forever
  10. 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
  11. link/ether 00:0c:29:e6:a1:70 brd ff:ff:ff:ff:ff:ff
  12. inet 192.168.80.10/24 brd 192.168.80.255 scope global noprefixroute ens33
  13. valid_lft forever preferred_lft forever
  14. inet 192.168.80.100/32 scope global ens33
  15. valid_lft forever preferred_lft forever
  16. inet6 fe80::76b5:a9d1:4787:d28c/64 scope link noprefixroute
  17. valid_lft forever preferred_lft forever
  18. [root@server2 ~]# ip a
  19. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  20. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  21. inet 127.0.0.1/8 scope host lo
  22. valid_lft forever preferred_lft forever
  23. inet6 ::1/128 scope host
  24. valid_lft forever preferred_lft forever
  25. 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
  26. link/ether 00:0c:29:23:76:7f brd ff:ff:ff:ff:ff:ff
  27. inet 192.168.80.20/24 brd 192.168.80.255 scope global noprefixroute ens33
  28. valid_lft forever preferred_lft forever
  29. inet6 fe80::f4c9:88e6:9fd6:19e9/64 scope link noprefixroute
  30. valid_lft forever preferred_lft forever

可以发现server1已经有虚拟IP地址192.168.80.100了。
我们模拟主负载均衡节点挂掉的情况。

  1. [root@server1 ~]# systemctl stop nginx
  2. [root@server1 ~]# /usr/local/src/check_nginx_pid.sh
  3. [root@server1 ~]# echo $?
  4. 1
  5. # 停止server1的nginx服务,执行检测脚本,输出状态码为1,表示上一条命令执行的结果不正常,若正常应该返回0
  6. root@server1 ~]# systemctl status keepalived
  7. [root@server1 ~]# ip a
  8. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  9. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  10. inet 127.0.0.1/8 scope host lo
  11. valid_lft forever preferred_lft forever
  12. inet6 ::1/128 scope host
  13. valid_lft forever preferred_lft forever
  14. 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
  15. link/ether 00:0c:29:e6:a1:70 brd ff:ff:ff:ff:ff:ff
  16. inet 192.168.80.10/24 brd 192.168.80.255 scope global noprefixroute ens33
  17. valid_lft forever preferred_lft forever
  18. inet6 fe80::76b5:a9d1:4787:d28c/64 scope link noprefixroute
  19. valid_lft forever preferred_lft forever
  20. [root@server2 ~]# ip a
  21. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  22. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  23. inet 127.0.0.1/8 scope host lo
  24. valid_lft forever preferred_lft forever
  25. inet6 ::1/128 scope host
  26. valid_lft forever preferred_lft forever
  27. 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
  28. link/ether 00:0c:29:23:76:7f brd ff:ff:ff:ff:ff:ff
  29. inet 192.168.80.20/24 brd 192.168.80.255 scope global noprefixroute ens33
  30. valid_lft forever preferred_lft forever
  31. inet 192.168.80.100/32 scope global ens33
  32. valid_lft forever preferred_lft forever
  33. inet6 fe80::f4c9:88e6:9fd6:19e9/64 scope link noprefixroute
  34. valid_lft forever preferred_lft forever

可以发现虽然server1挂掉了,但是我们虚拟地址192.168.80.100转移到了server2上,所以此时是由server2作为负载均衡器,我们访问192.168.80.100仍然可以查看到RS提供的页面。
image.pngimage.png

keepalived+HAproxy+MySQL双主实验

  • 环境准备

    1. node1HAProxy1):192.168.80.10
    2. node2HAProxy2):192.168.80.20
    3. node3Mysql1):192.168.80.30
    4. node4Mysql2):192.168.80.40
    5. VIP192.168.80.99
  • mysql部署(server3、server4)

  1. 执行脚本
    1. [root@server3 ~]# vim mysql_prepare.sh
    2. #!/bin/bash
    3. Ip_addr="192.168.80.40" # 修改为对端的node地址
    4. User_pwd="000000"
    5. systemctl stop firewalld
    6. setenforce 0
    7. yum install mariadb-server -y
    8. sed -i '/^\[mysqld\]$/a\binlog-ignore = information_schema' /etc/my.cnf.d/server.cnf
    9. sed -i '/^\[mysqld\]$/a\binlog-ignore = mysql' /etc/my.cnf.d/server.cnf
    10. sed -i '/^\[mysqld\]$/a\skip-name-resolve' /etc/my.cnf.d/server.cnf
    11. sed -i '/^\[mysqld\]$/a\auto-increment-increment = 1' /etc/my.cnf.d/server.cnf # 注意node4节点上必须不同
    12. sed -i '/^\[mysqld\]$/a\log-bin = mysql-bin' /etc/my.cnf.d/server.cnf
    13. sed -i '/^\[mysqld\]$/a\auto_increment_offset = 1' /etc/my.cnf.d/server.cnf # 注意node4节点上必须不同
    14. sed -i '/^\[mysqld\]$/a\server-id = 1' /etc/my.cnf.d/server.cnf # 注意node4节点上必须不同
    15. systemctl restart mariadb
    16. mysql -uroot -e "grant replication slave on *.* to 'repuser'@'$Ip_addr'
    17. identified by '$User_pwd';"
    18. [root@server3 ~]# bash mysql_prepare.sh
    server4上也执行脚本文件,IP地址和一些为1的地方修改为2,查看各节点的master状态: ```bash

    在server3上

    MariaDB [(none)]> show master status -> ; +—————————+—————+———————+—————————————+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +—————————+—————+———————+—————————————+ | mysql-bin.000003 | 403 | | mysql,information_schema | +—————————+—————+———————+—————————————+ 1 row in set (0.00 sec)

在server4上

MariaDB [(none)]> show master status; +—————————+—————+———————+—————————————+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +—————————+—————+———————+—————————————+ | mysql-bin.000003 | 408 | | mysql,information_schema | +—————————+—————+———————+—————————————+ 1 row in set (0.01 sec)

  1. 2. server3server4节点执行连接命令
  2. ```bash
  3. # server3
  4. MariaDB [(none)]> change master to master_host='192.168.80.40',master_port=3306,master_user='repuser',master_password='000000',master_log_file='mysql-bin.000003',master_log_pos=408;
  5. MariaDB [(none)]> start slave;
  6. # server4
  7. MariaDB [(none)]> change master to master_host='192.168.80.30',master_port=3306,master_user='repuser',master_password='000000',master_log_file='mysql-bin.000003',master_log_pos=403;
  8. MariaDB [(none)]> start slave;
  1. 查看从节点状态,观察IO和SQL线程是否为YES ```bash

    server3上

    MariaDB [(none)]> show slave status \G; * 1. row *
    1. Slave_IO_State: Waiting for master to send event
    2. Master_Host: 192.168.80.40
    3. Master_User: repuser
    4. Master_Port: 3306
    5. Connect_Retry: 60
    6. Master_Log_File: mysql-bin.000006
    7. Read_Master_Log_Pos: 408
    8. Relay_Log_File: mariadb-relay-bin.000005
    9. Relay_Log_Pos: 692
    10. Relay_Master_Log_File: mysql-bin.000006
    11. Slave_IO_Running: Yes
    12. Slave_SQL_Running: Yes

server4上

MariaDB [(none)]> show slave status \G; * 1. row * Slave_IO_State: Waiting for master to send event Master_Host: 192.168.80.30 Master_User: repuser Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000005 Read_Master_Log_Pos: 403 Relay_Log_File: mariadb-relay-bin.000004 Relay_Log_Pos: 687 Relay_Master_Log_File: mysql-bin.000005 Slave_IO_Running: Yes Slave_SQL_Running: Yes

  1. 4. 测试
  2. ```bash
  3. 在node3上创建mydb数据库
  4. 在node4上在test数据库中创建test表
  5. 最终要实现node3和node4上保持数据同步
  • 部署HAproxy
    1. [root@server1 ~]# yum install haproxy -y
    2. [root@server1 ~]# mv /etc/haproxy/haproxy.cfg{,.bak}
    3. [root@server1 ~]# vim /etc/haproxy/haproxy.cfg
    4. global
    5. log 127.0.0.1 local2
    6. chroot /var/lib/haproxy
    7. pidfile /var/run/haproxy.pid
    8. maxconn 4000
    9. user haproxy
    10. group haproxy
    11. daemon
    12. stats socket /var/lib/haproxy/stats
    13. listen mysql_proxy
    14. bind 0.0.0.0:3306
    15. mode tcp
    16. balance source
    17. server mysqldb1 192.168.80.30:3306 weight 1 check
    18. server mysqldb2 192.168.80.40:3306 weight 2 check
    19. listen stats
    20. mode http
    21. bind 0.0.0.0:8080
    22. stats enable
    23. stats uri /dbs
    24. stats realm haproxy\ statistics
    25. stats auth admin:admin
    26. [root@server1 ~]# systemctl start haproxy
    安装mariadb客户端测试(记得关防火墙和selinux) ```bash [root@server1 ~]# yum install mariadb -y [root@server1 ~]# systemctl start mariadb.service

在服务端授权给客户端可以远程登陆

MariaDB [(none)]> grant all on . to root@’%’ identified by ‘1’; Query OK, 0 rows affected (0.01 sec)

MariaDB [(none)]> flush privileges; Query OK, 0 rows affected (0.00 sec)

[root@server1 ~]# mysql -h 192.168.80.10 -P 3306 -p

  1. server2server1做同样的操作
  2. - 部署keepalived
  3. ```bash
  4. [root@server1 ~]# yum install keepalived -y
  5. [root@server1 ~]# mv /etc/keepalived/keepalived.conf{,.bak}
  6. [root@server1 ~]# vim /etc/keepalived/keepalived.conf
  7. ! Configuration File for keepalived
  8. global_defs {
  9. router_id server1
  10. }
  11. vrrp_script chk_http_port {
  12. script "/root/check_haproxy.sh"
  13. interval 1
  14. weight -2
  15. }
  16. vrrp_instance VI_1 {
  17. state MASTER
  18. interface ens33
  19. virtual_router_id 10
  20. priority 100
  21. advert_int 1
  22. authentication {
  23. auth_type PASS
  24. auth_pass 1111
  25. }
  26. track_script {
  27. chk_http_port
  28. }
  29. virtual_ipaddress {
  30. 192.168.80.100
  31. }
  32. }
  33. [root@server1 ~]# systemctl start keepalived
  34. [root@server1 ~]# ip a
  35. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  36. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  37. inet 127.0.0.1/8 scope host lo
  38. valid_lft forever preferred_lft forever
  39. inet6 ::1/128 scope host
  40. valid_lft forever preferred_lft forever
  41. 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
  42. link/ether 00:0c:29:e6:a1:70 brd ff:ff:ff:ff:ff:ff
  43. inet 192.168.80.10/24 brd 192.168.80.255 scope global noprefixroute ens33
  44. valid_lft forever preferred_lft forever
  45. inet 192.168.80.100/32 scope global ens33
  46. valid_lft forever preferred_lft forever
  47. inet6 fe80::76b5:a9d1:4787:d28c/64 scope link noprefixroute
  48. valid_lft forever preferred_lft forever
  49. [root@server1 ~]# vim check_haproxy.sh
  50. #!/bin/bash
  51. A=`ps -C haproxy --no-header |wc -l`
  52. if [ $A -eq 0 ];then
  53. exit 1
  54. else
  55. exit 0
  56. fi
  57. [root@server1 ~]# chmod +x check_haproxy.sh
  58. [root@server2 ~]# yum install keepalived -y
  59. [root@server2 ~]# mv /etc/keepalived/keepalived.conf{,.bak}
  60. [root@server2 ~]# vim /etc/keepalived/keepalived.conf
  61. ! Configuration File for keepalived
  62. global_defs {
  63. router_id server2
  64. }
  65. vrrp_instance VI_1 {
  66. state MASTER
  67. interface ens33
  68. virtual_router_id 10
  69. priority 99
  70. advert_int 1
  71. authentication {
  72. auth_type PASS
  73. auth_pass 1111
  74. }
  75. virtual_ipaddress {
  76. 192.168.80.100
  77. }
  78. }
  79. [root@server2 ~]# systemctl start keepalived
  • 测试 ```bash

    停止server1上的haproxy服务,模拟故障

    [root@server1 ~]# systemctl stop haproxy.service [root@server1 ~]# systemctl restart keepalived [root@server1 ~]# ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo
    1. valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
    1. valid_lft forever preferred_lft forever
    2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:e6:a1:70 brd ff:ff:ff:ff:ff:ff inet 192.168.80.10/24 brd 192.168.80.255 scope global noprefixroute ens33
    1. valid_lft forever preferred_lft forever
    inet6 fe80::76b5:a9d1:4787:d28c/64 scope link noprefixroute
    1. valid_lft forever preferred_lft forever

[root@server2 ~]# ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:23:76:7f brd ff:ff:ff:ff:ff:ff inet 192.168.80.20/24 brd 192.168.80.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet 192.168.80.100/32 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::f4c9:88e6:9fd6:19e9/64 scope link noprefixroute valid_lft forever preferred_lft forever

  1. 虚拟地址转移到了server2上继续haproxy代理,测试访问数据库
  2. ```bash
  3. [root@server1 ~]# mysql -u root -h 192.168.80.100 -P3306 -p1
  4. Welcome to the MariaDB monitor. Commands end with ; or \g.
  5. Your MariaDB connection id is 7
  6. Server version: 5.5.68-MariaDB MariaDB Server
  7. Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
  8. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  9. MariaDB [(none)]>

keepalived+lvs实验

  • 环境准备

    1. node1DS1):192.168.10.10
    2. node2DS2):192.168.10.20
    3. node3RS1):192.168.10.30
    4. node4RS2):192.168.10.40
    5. VIP192.168.10.99(单主模型)
  • RS部署

    1. [root@server3 ~]# vim rs.sh
    2. #!/bin/bash
    3. yum install net-tools.x86_64 httpd -y
    4. systemctl stop firewalld
    5. setenforce 0
    6. vip="192.168.80.99"
    7. mask="255.255.255.255"
    8. ifconfig lo:0 $vip broadcast $vip netmask $mask up
    9. route add -host $vip lo:0
    10. echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
    11. echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
    12. echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
    13. echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
    14. echo "<h1>This is RS1</h1>" > /var/www/html/index.html
    15. systemctl start httpd
    16. [root@server4 ~]# vim rs.sh
    17. #!/bin/bash
    18. yum install net-tools.x86_64 httpd -y
    19. systemctl stop firewalld
    20. setenforce 0
    21. vip="192.168.80.99"
    22. mask="255.255.255.255"
    23. ifconfig lo:0 $vip broadcast $vip netmask $mask up
    24. route add -host $vip lo:0
    25. echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
    26. echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
    27. echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
    28. echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
    29. echo "<h1>This is RS2</h1>" > /var/www/html/index.html
    30. systemctl start httpd
    31. [root@server4 ~]# bash rs.sh
  • DS部署 ```bash [root@server1 ~]# yum install keepalived -y [root@server1 ~]# yum install ipvsadm -y [root@server1 ~]# mv /etc/keepalived/keepalived.conf{,.bak} [root@server1 ~]# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { router_id server1 # 设置lvs的id,一个网络中应该唯一 } vrrp_instance VI_1 { state MASTER # 指定Keepalived的角色 interface ens33 # 网卡 virtual_router_id 10 # 虚拟路由器ID,主备需要一样 priority 100 # 优先级越大越优,backup路由器需要设置比这小! advert_int 1 # 检查间隔1s authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.80.99 # 定义虚拟IP地址,可以定义多个 } }

    定义虚拟主机,对外服务的IP和port

    virtual_server 192.168.80.99 80 { delay_loop 6 # 设置健康检查时间,单位是秒 lb_algo wrr # 负责调度算法 lb_kind DR # LVS负载均衡机制 persistence_timeout 0 protocol TCP

    指定RS主机IP和port

    real_server 192.168.80.30 80 { weight 2

    定义TCP健康检查

    TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.80.40 80 { weight 1 TCP_CHECK { connect_timeout 10 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } } [root@server1 ~]# systemctl start keepalived.service

    可以发现两台RS权重是不一样的,所以在server2上尝试curl时RS1响应更多

    [root@server1 ~]# ipvsadm IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP server1:http wrr -> 192.168.80.30:http Route 2 0 0
    -> 192.168.80.40:http Route 1 0 0

[root@server2 ~]# for i in {1..10};do curl 192.168.80.99;done

This is RS1

This is RS2

This is RS1

This is RS1

This is RS2

This is RS1

This is RS1

This is RS2

This is RS1

This is RS1

  1. 接下来相应地配置DS2
  2. ```bash
  3. ! Configuration File for keepalived
  4. global_defs {
  5. router_id server2
  6. }
  7. vrrp_instance VI_1 {
  8. state BACKUP
  9. interface ens33
  10. virtual_router_id 10
  11. priority 99
  12. advert_int 1
  13. authentication {
  14. auth_type PASS
  15. auth_pass 1111
  16. }
  17. virtual_ipaddress {
  18. 192.168.80.99
  19. }
  20. }
  21. virtual_server 192.168.80.99 80 {
  22. delay_loop 6
  23. lb_algo wrr
  24. lb_kind DR
  25. persistence_timeout 0
  26. protocol TCP
  27. real_server 192.168.80.30 80 {
  28. weight 2
  29. TCP_CHECK {
  30. connect_timeout 10
  31. nb_get_retry 3
  32. delay_before_retry 3
  33. connect_port 80
  34. }
  35. }
  36. real_server 192.168.80.40 80 {
  37. weight 1
  38. TCP_CHECK {
  39. connect_timeout 10
  40. nb_get_retry 3
  41. delay_before_retry 3
  42. connect_port 80
  43. }
  44. }
  45. }
  46. [root@server2 ~]# systemctl start keepalived
  • 测试,关闭server1的keepalived服务 ```bash [root@server1 ~]# ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo
    1. valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
    1. valid_lft forever preferred_lft forever
    2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:e6:a1:70 brd ff:ff:ff:ff:ff:ff inet 192.168.80.10/24 brd 192.168.80.255 scope global noprefixroute ens33
    1. valid_lft forever preferred_lft forever
    inet 192.168.80.99/32 scope global ens33
    1. valid_lft forever preferred_lft forever
    inet6 fe80::76b5:a9d1:4787:d28c/64 scope link noprefixroute
    1. valid_lft forever preferred_lft forever
    [root@server1 ~]# systemctl stop keepalived [root@server1 ~]# ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo
    1. valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
    1. valid_lft forever preferred_lft forever
    2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:e6:a1:70 brd ff:ff:ff:ff:ff:ff inet 192.168.80.10/24 brd 192.168.80.255 scope global noprefixroute ens33
    1. valid_lft forever preferred_lft forever
    inet6 fe80::76b5:a9d1:4787:d28c/64 scope link noprefixroute
    1. valid_lft forever preferred_lft forever

[root@server2 ~]# ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:23:76:7f brd ff:ff:ff:ff:ff:ff inet 192.168.80.20/24 brd 192.168.80.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet 192.168.80.99/32 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::f4c9:88e6:9fd6:19e9/64 scope link noprefixroute valid_lft forever preferred_lft forever ``` 可以看见原本server1上的虚拟地址在关闭keepalived服务后转移到了server2上。