thinkhk 发表于 2018-12-31 09:43:38

keepalived 实现LVS DR 模型的高可用

  LVS的工作类型:
  lvs-nat
  Network Address Translation
  lvs-dr
  Direct Routing
  lvs-tun
  Tunneling
  nat类型的特性:
  1、RS应用使用私有地址;RS的网关必须指向DIP;
  2、请求和响应都要经过Director;高负载场景中,Director易成为性能瓶颈;
  3、支持端口映射;
  4、RS可以使用任意OS;
  附: 传说这样的工作特性不好,只能带动10台左右的RS,所以生产环境几乎不用.
  dr类型的特性:
  1、保证前端路由将目标地址为VIP的报文统统发往Directory,而不能是RS;
  解决方案:
  (1) 静态地址绑定:在前端路由器上操作
  问题:未必有路由操作权限
  (2) aprtables
  (3) 修改RS上内核参数,将RS上的VIP配置在lo接口的别名上,并限制其不能响应对VIP地址解析请求;
  2、RS可以使用私有地址;但也可以使用公网地址,此时可通过互联网通过RIP对其直接访问;
  3、RS跟Directory必须在同一物理网络中 [容灾功能不好,比如地震,火灾什么的];
  4、请求报文经由Director,但响应报文必须不能经过Director[否则和nat的工作类型有什么区别呢],
  所以得是由 RS直接响应给客户端.
  5、不支持端口映射;
  6、RS可以是大多数常见的OS;
  7、RS的网关绝不允许指向DIP;
  tun类型的特性:
  1、RIP、VIP、DIP全部是公网地址;
  2、RS的网关不会也不可能指向DIP;
  3、请求报文经由Director,但响应报文必须不能经过Director;
  4、不支持端口映射;
  5、RS的OS必须支持隧道功能;
  # grep -i 'VS' /boot/config-VERSION
  静态方法:仅根据调度算法本身进行调度
  rr: round robin,轮流,轮询,轮叫 . 工作时rs节点遂一轮换,做到起点公平,缺点 , 有些服务器性能差,一个任务还没完成,下一个又来了,而有的服务器性能好,一个任务一会处理好,积累到一定时间
  性能差的服务器抗不住了,性能好的服务器还闲得慌.
  wrr: weighted round robin, 加权轮询 , 比rr有进步,但是还是不怎么靠谱,缺点和rr类似, 好不到哪去.
  sh: source hashing,源地址hash,表示来源于同一个CIP的请求将始终被定向至同一个RS;SESSION保持;每一个客户端访问时都会由服务端发一个cookie的标识,下次这个客户端发起访问时
  还是会由同一台服务器进行响应,除非是这台服务器真的忙不过来时,才勉为其难的分发到别的服务器上去.
  dh: destination hashing, 目标地址hash,
  动态方法:根据算法及各RS当前的负载状况进行调度 . 是一种结果公平的调度算法
  lc: least connection,最少连接 ,根据权重计算公式,看谁的计算值最小,下一个处理任务就会分发过来,可问题是一开始,每一个RS都没有任务,计算结果都是0, 来了个业务,很可能会发给性能最差的服务器
  Overhead=Active*256+Inactive
  wlc: weighted lc
  Overhead=(Active*256+Inactive)/weight   ==>根据算法的公式可知, 性能差,权重低的,仍然可能是第一个分配处理任务的
  A: 1,
  B: 5,
  sed: shortest expection delay               ==>很有可能权重高,性能好的服务器都处理了好些任务,而权重低的一个任务都没接
  Overhead=(Active+1)*256/weight
  1: B
  2: B
  3: B
  4: B
  nq: Never Queue==>永不排除的调度方法, 一开始从权重最高的服务器开始,依次每台服务器分发处理请求,保证了每台服务器都有事可做
  lblc: Locality-Based Least Connection 本地最小连接数的
  lblcr:Replicated lblc    带复制功能的lblc
  在这里,我们选用 dr模型来实现,拓普图如下
http://robert1joy.blog.运维网.com/attachment/201409/22/4489523_1411352699do8k.png
  需要注意以下几点.
  1、禁止RealServer响应对VIP的ARP请求;
  2、在RealServer上隐藏VIP,以使得它们无法获知网络上的ARP请求;
  3、基于“透明代理(Transparent Proxy)”或者“fwmark (firewall mark)”;
  4、禁止ARP请求发往RealServers;
  传统认为,解决ARP问题可以基于网络接口,也可以基于主机来实现。Linux采用了基于主机的方式,因为其可以在大多场景中工作良好,但LVS却并不属于这些场景之一,
  因此,过去实现此功能相当麻烦。现在可以通过设置arp_ignore和arp_announce,这变得相对简单的多了。
  Linux 2.2和2.4(2.4.26之前的版本)的内核解决“ARP问题”的方法各不相同,且比较麻烦。幸运的是,2.4.26和2.6的内核中引入了两个新的调整ARP栈的标志(device flags):
  arp_announce和arp_ignore。基于此,在DR/TUN的环境中,所有IPVS相关的设定均可使用arp_announce=2和arp_ignore=1/2/3来解决“ARP问题”了。
  官方文档的参数解释如下
  arp_annouce:Define different restriction levels for announcing the local source IP address from IP packets in ARP requests sent on interface;
  0 - (default) Use any local address, configured on any interface.
  1 - Try to avoid local addresses that are not in the target's subnet for this interface.
  2 - Always use the best local address for this target.
  arp_ignore: Define different modes for sending replies in response to received ARP requests that resolve local target IP address.
  0 - (default): reply for any local target IP address, configured on any interface.
  1 - reply only if the target IP address is local address configured on the incoming interface.
  2 - reply only if the target IP address is local address configured on the incoming interface and both with the sender's IP address are part from same subnet on this interface.
  3 - do not reply for local address configured with scope host, only resolutions for golbal and link addresses are replied.
  4-7 - reserved
  8 - do not reply for all local addresses
  中文翻译如下
  arp_announce :对网络接口上,本地IP地址的发出的,ARP回应,作出相应级别的限制: 确定不同程度的限制,宣布对来自本地源IP地址发出Arp请求的接口
  0 - (默认) 在任意网络接口(eth0,eth1,lo)上的任何本地地址
  1 -尽量避免不在该网络接口子网段的本地地址做出arp回应. 当发起ARP请求的源IP地址是被设置应该经由路由达到此网络接口的时候很有用.此时会检查来访IP是否为所有接口上的子网段内ip之一.如果改来访IP不属于各个网络接口上的子网段内,那么将采用级别2的方式来进行处理.
  2 - 对查询目标使用最适当的本地地址.在此模式下将忽略这个IP数据包的源地址并尝试选择与能与该地址通信的本地地址.首要是选择所有的网络接口的子网中外出访问子网中包含该目标IP地址的本地地址. 如果没有合适的地址被发现,将选择当前的发送网络接口或其他的有可能接受到该ARP回应的网络接口来进行发送.
  arp_ignore:定义对目标地址为本地IP的ARP询问不同的应答模式0
  0 - (默认值): 回应任何网络接口上对任何本地IP地址的arp查询请求
  1 - 只回答目标IP地址是来访网络接口本地地址的ARP查询请求
  2 -只回答目标IP地址是来访网络接口本地地址的ARP查询请求,且来访IP必须在该网络接口的子网段内
  3 - 不回应该网络界面的arp请求,而只对设置的唯一和连接地址做出回应
  4-7 - 保留未使用
  8 -不回应所有(本地地址)的arp查询
  按以上的内容来看,满足我们需要的是 将 arp_announce参数设置为 2 , arp_ignore 参数设置为1.
  # echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore   
# echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore   
# echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce   
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce    这是临时生效的,要想永久有效,得改配置文件
  介绍完了keepalived ,现在来讨论keepalived .因为keepalived可以在配置文件中实现对lvs的配置
  所以无需使用 ipvsadm -A 的方式来定义lvs集群,所以ipvsadm工具,不安装也行, 但是如果想查看由keepalived
  生成的ipvs规则,但装也无妨
  # yum install ipvsadm -y
  keepalived 实现的是一个虚拟容余路由的功能.
  vrrp: virtual redundent routing protocol
  生成路由:
  静态路由
  动态路由:OSPF, RIP2
  LAN客户端判定哪个路由器应该为其到达目标主机的下一跳网关的方式有动态及静态决策两种方式,其中,常见的动态路由发现方式有如下几种:
  1、Proxy ARP —— 客户端使用ARP协议获取其想要到达的目标,而后,由某路由以其MAC地址响应此ARP请求;
  2、Routing Protocol —— 客户端监听动态路由更新(如通过RIP或OSPF协议)并以之重建自己的路由表;
  3、ICMP IRDP (Router Discovery Protocol) 客户端 —— 客户端主机运行一个ICMP路由发现客户端程序;
  动态路由发现协议的不足之处在于它会导致在客户端引起一定的配置和处理方面的开销,并且,如果路由器故障,切换至其它路由器的过程会比较慢。
  解决此类问题的一个方案是为客户端静态配置默认路由设备,这大大简化了客户端的处理过程,但也会带来单点故障类的问题。默认网关故障时,
  LAN客户端仅能实现本地通信。VRRP可以通过在一组路由器(一个VRRP组)之间共享一个虚拟IP(VIP)解决静态配置的问题,此时仅需要客户端以VIP作为其默认网关即可。
  VRRP的优势:
  冗余:可以使用多个路由器设备作为LAN客户端的默认网关,大大降低了默认网关成为单点故障的可能性;
  负载共享:允许来自LAN客户端的流量由多个路由器设备所共享;
  多VRRP组:在一个路由器物理接口上可配置多达255个VRRP组;
  多IP地址:基于接口别名在同一个物理接口上配置多个IP地址,从而支持在同一个物理接口上接入多个子网;
  抢占:在master故障时允许优先级更高的backup成为master;
  通告协议:使用IANA所指定的组播地址224.0.0.18进行VRRP通告;
  VRRP追踪:基于接口状态来改变其VRRP优先级来确定最佳的VRRP路由器成为master;
  IP地址拥有者(IP Address Owner):如果一个VRRP设备将虚拟路由器IP地址作为真实的接口地址,则该设备被称为IP地址拥有者。
  如果IP地址拥有者是可用的,通常它将成为Master。
  介绍完keepalived,我们开始小试牛刀, 在172.16.26.6,和172.16.26.11节点上配置keepalived 高可用
  yum install keepalived -y
  # rpm -ql keepalived         =>查看安装keepalived生成的配置文件   
/etc/keepalived   
/etc/keepalived/keepalived.conf   
/etc/rc.d/init.d/keepalived   
/etc/sysconfig/keepalived   
/usr/bin/genhash   
/usr/sbin/keepalived
  编辑 /etc/keepalived/keepalived.conf 配置文件
  172.16.26.6   主机上的设置
global_defs {   notification_email {    root@127.0.0.1发生改变时通知的邮件地址    }    notification_email_from root
smtp_server 127.0.0.1          =>邮件服务器定义
smtp_connect_timeout 30 =>邮件服务器连接超时时长设置
router_id LVS_DEVEL          =>设置路由节点id
}   vrrp_instance VI_1 {   =>定义策略一
    state MASTER    =>设置为该节点的主服务器
    interface eth0    =>网络接口为网卡eth0
    virtual_router_id 11    =>定义虚拟路由id
    priority 100            =>权重设定为100
    advert_int 1            =>每隔一秒检测一次
    authentication {
      auth_type PASS    =>认证帐户
      auth_pass 1111    =>认证口令
    }
    virtual_ipaddress {
      172.16.26.100/16    =>设定ipvs 规则的虚拟ip
    }
}
virtual_server 172.16.26.100 80 {    =>设定ipvs 虚拟ip中的属性
    delay_loop 6   
    lb_algo rr                  =>轮询的算法
    lb_kind DR                  =>使用ipvs的 DR模型
    nat_mask 255.255.0.0    =>网关掩码
    persistence_timeout 50    =>超时时长
    protocol TCP    =>定义工作模式
sorry_server 127.0.0.1 80    =>如果虚拟节点都无法正常访问,所指向的sorry_server
    real_server 172.16.26.1 80 {    =>ipvs 的节点
      weight 1
      HTTP_GET {
            url {
            path /
            status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 1
      }
    }
    real_server 172.16.26.5 80 {
      weight 1
      HTTP_GET {
            url {
            path /
            status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 1
      }
}
#下面的 第二条规则 , 语法定义解释参照上面的条目
vrrp_instance VI_2 {
    state BACKUP
    interface eth0
    virtual_router_id 12
    priority 99
    advert_int 1
    authentication {
      auth_type PASS
      auth_pass 1111
    }
    virtual_ipaddress {
      172.16.26.101/16
    }
}
virtual_server 172.16.26.101 80 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    nat_mask 255.255.0.0
    persistence_timeout 50
    protocol TCP
sorry_server 127.0.0.1 80
    real_server 172.16.26.1 80 {
      weight 1
      HTTP_GET {
            url {
            path /
            status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 1
      }
    }
    real_server 172.16.26.5 80 {
      weight 1
      HTTP_GET {
            url {
            path /
            status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 1
      }
}  172.16.26.11   主机上的设置
! Configuration File for keepalived   
global_defs {   
notification_email {   
root@127.0.0.1
}   
notification_email_from root   
smtp_server 127.0.0.1   
smtp_connect_timeout 30   
router_id LVS_DEVEL   
}   
vrrp_instance VI_1 {   
state BACKUP   
interface eth0   
virtual_router_id 11   
priority 99   
advert_int 1   
authentication {   
auth_type PASS   
auth_pass 1111   
}   
virtual_ipaddress {   
172.16.26.100/16   
}   
}   
virtual_server 172.16.26.100 80 {   
delay_loop 6   
lb_algo rr   
lb_kind DR   
nat_mask 255.255.0.0   
persistence_timeout 50   
protocol TCP   
sorry_server 127.0.0.1 80   
real_server 172.16.26.1 80 {   
weight 1   
HTTP_GET {   
url {   
path /   
status_code 200   
}   
connect_timeout 3   
nb_get_retry 3   
delay_before_retry 1   
}   
}   
real_server 172.16.26.5 80 {   
weight 1   
HTTP_GET {   
url {   
path /   
status_code 200   
}   
connect_timeout 3   
nb_get_retry 3   
delay_before_retry 1   
}   
}   
vrrp_instance VI_2 {   
state MASTER   
interface eth0   
virtual_router_id 12   
priority 100   
advert_int 1   
authentication {   
auth_type PASS   
auth_pass 1111   
}   
virtual_ipaddress {   
172.16.26.101/16   
}   
}   
virtual_server 172.16.26.101 80 {   
delay_loop 6   
lb_algo rr   
lb_kind DR   
nat_mask 255.255.0.0   
persistence_timeout 50   
protocol TCP   
sorry_server 127.0.0.1 80   
real_server 172.16.26.1 80 {   
weight 1   
HTTP_GET {   
url {   
path /   
status_code 200   
}   
connect_timeout 3   
nb_get_retry 3   
delay_before_retry 1   
}   
}   
real_server 172.16.26.5 80 {   
weight 1   
HTTP_GET {   
url {   
path /   
status_code 200   
}   
connect_timeout 3   
nb_get_retry 3   
delay_before_retry 1   
}   
}  此时,我们先启动 172.16.26.11节点的keepalived的服务
  # tail /var/log/messages             =>查看日志文件   
Sep 21 21:11:06 mode_11 Keepalived_vrrp: VRRP_Instance(VI_2) Entering MASTER STATE   
Sep 21 21:11:06 mode_11 Keepalived_vrrp: VRRP_Instance(VI_2) setting protocol VIPs.   
Sep 21 21:11:06 mode_11 Keepalived_vrrp: VRRP_Instance(VI_2) Sending gratuitous ARPs on eth0 for 172.16.26.101   
Sep 21 21:11:06 mode_11 Keepalived_healthcheckers: Netlink reflector reports IP 172.16.26.101 added   
Sep 21 21:11:07 mode_11 Keepalived_vrrp: VRRP_Instance(VI_1) Transition to MASTER STATE   
Sep 21 21:11:08 mode_11 Keepalived_vrrp: VRRP_Instance(VI_1) Entering MASTER STATE   
Sep 21 21:11:08 mode_11 Keepalived_vrrp: VRRP_Instance(VI_1) setting protocol VIPs.   
Sep 21 21:11:08 mode_11 Keepalived_healthcheckers: Netlink reflector reports IP 172.16.26.100 added                        
Sep 21 21:11:08 mode_11 Keepalived_vrrp: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.16.26.100   
Sep 21 21:11:11 mode_11 Keepalived_vrrp: VRRP_Instance(VI_2) Sending gratuitous ARPs on eth0 for 172.16.26.101
  =>因为只有它自己一个keepalived节点启动, 把172.16.26.100,172.16.26.100都配置到自己的网卡上了
http://robert1joy.blog.运维网.com/attachment/201409/22/4489523_1411352706CSi1.png   
# ipvsadm -Ln   =>查看一下集群条目   
IP Virtual Server version 1.2.1 (size=4096)   
Prot LocalAddress:Port Scheduler Flags   
-> RemoteAddress:Port Forward Weight ActiveConn InActConn   
TCP 172.16.26.100:80 rr persistent 50   
-> 172.16.26.1:80 Route 1 0 0   
-> 172.16.26.5:80 Route 1 0 0   
TCP 172.16.26.101:80 rr persistent 50   
-> 172.16.26.1:80 Route 1 0 0   
-> 172.16.26.5:80 Route 1 0 0      =>集群已然在列
  现在启动 172.16.26.6节点上的 keepalived服务
  # service keepalived start
http://robert1joy.blog.运维网.com/attachment/201409/22/4489523_1411352713KC10.png
  此时,因为上面配置的该节点拥有172.16.26.100 ip的权重高,所以它就把这个ip配置到自己的网卡上了
  172.16.26.1和172.16.26.5上都进行如下操作
  # ifconfig lo:0 172.16.26.100 netmask 255.255.255.255 broadcast 172.16.26.100 up   =>给lo 起两别名, 添加两个虚拟地址   
# ifconfig lo:1 172.16.26.101 netmask 255.255.255.255 broadcast 172.16.26.101 up   
# route add -host 172.16.26.100 dev lo    而且必须是访问 lo口上拥有的ip才能允许报文进来   
# route add -host 172.16.26.101 dev lo
  # echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce   只通告本接口拥有的ip地址
  # echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce   
# echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore =>只响应目标IP地址是来访网络接口本地地址的ARP查询请求   
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
http://robert1joy.blog.运维网.com/attachment/201409/22/4489523_1411352716uwAl.png
http://robert1joy.blog.运维网.com/attachment/201409/22/4489523_1411352720MTkb.png
  访问两个 virtual ip 都能解析到后端主机上,实验OK
  # service keepalived stop =>我们停掉一个节点,测试一下两个vip的访问都是否正常
http://robert1joy.blog.运维网.com/attachment/201409/22/4489523_1411352725V9L8.png
http://robert1joy.blog.运维网.com/attachment/201409/22/4489523_1411352734KjKb.png
  OK,实验完成,实现了高可用.



页: [1]
查看完整版本: keepalived 实现LVS DR 模型的高可用