LVS专题-(3) 虚拟ip理解
1.虚拟IP是什么?
要是单讲解虚拟 IP,理解起来很困难,所以干脆把
动态 IP 、固定 IP 、实体 IP 与虚拟 IP都讲解一下,加深理解和知识扩展
实体 IP:在网络的世界里,为了要辨识每一部计算机的位置,因此有了计算机 IP 位址的定义。一个 IP 就好似一个门牌!例如,你要去微软的网站的话,就要去『 207.46.197.101 』这个 IP 位置!这些可以直接在网际网络上沟通的 IP 就被称为『实体 IP 』了。
虚拟 IP:不过,众所皆知的,IP 位址仅为 xxx.xxx.xxx.xxx 的资料型态,其中, xxx 为 1-255 间的整数,由于近来计算机的成长速度太快,实体的 IP 已经有点不足了,好在早在规划 IP 时就已经预留了三个网段的 IP 做为内部网域的虚拟 IP 之用。这三个预留的 IP 分别为:
A级:10.0.0.0 - 10.255.255.255
B级:172.16.0.0 - 172.31.255.255
C级:192.168.0.0 - 192.168.255.255
上述中最常用的是192.168.0.0这一组。不过,由于是虚拟 IP ,所以当您使用这些地址的时候﹐当然是有所限制的,限制如下:
私有位址的路由信息不能对外散播
使用私有位址作为来源或目的地址的封包﹐不能透过Internet来转送
关于私有位址的参考纪录(如DNS)﹐只能限于内部网络使用
由于虚拟 IP 的计算机并不能直接连上 Internet ,因此需要特别的功能才能上网。不过,这给我们架设IP网络做成很大的方便﹐比如﹕即使您目前的公司还没有连上Internet﹐但不保证将来不会啊。如果使用公共IP的话﹐如果没经过注册﹐等到以后真正要连上网络的时候﹐就很可能和别人冲突了。也正如前面所分析的﹐到时候再重新规划IP的话﹐将是件非常头痛的问题。这时候﹐我们可以先利用私有位址来架设网络﹐等到真要连上intetnet的时候﹐我们可以使用IP转换协定﹐如 NAT (Network Addresss Translation)等技术﹐配合新注册的IP就可以了。
固定 IP 与 动态 IP:基本上,这两个东西是由于近来网络公司大量的成长下的产物,例如,你如果向中华电信申请一个商业型态的 ADSL 专线,那他会给你一个固定的实体 IP ,这个实体 IP 就被称为『固定 IP 』了。而若你是申请计时制的 ADSL ,那由于你的 IP 可能是由数十人共同使用,因此你每次重新开机上网时,你这部计算机的 IP 都不会是固定的!于是就被称为『动态 IP』或者是『浮动式IP』。基本上,这两个都是『实体IP』,只是网络公司用来分配给用户的方法不同而产生不同的名称而已。
自己的理解
我们用路由器时,每个手机或电脑都有一个ip地址,这个IP就是虚拟IP。想象一下,如果世界上的每台设备(电脑手机都算)都有一个实际IP地址,IP地址肯定不够用。但如果每个实际的IP地址再对应几万个虚拟的IP地址(比如 192.168.0.0 - 192.168.255.255),那不就够了吗?
我们给一个路由器分配一个实体IP(只是举个例子),之后每个连接这个路由器的设备给他分配一个虚拟IP(比如 192.168.0.0 -
192.168.255.255
中随机给一个),路由器记下这个虚拟IP和对应的设备,当某个设备访问网络数据时,先经过路由器,然后路由器与网络进行数据交换,因为路由器有实体IP,所以网络可以给路由器发送数据,然后路由器再根据自己分配的虚拟IP发送到相应的设备。
资料来源:http://blog.csdn.net/u014290233/article/details/53635658
2.虚拟IP与arp协议
一、虚拟IP
二、arp协议
三、虚拟IP与arp协议
虚拟IP和arp协议
虚拟IP常用于系统高可用性的场景,那么虚拟IP实现的原理是什么?虚拟能够自由漂浮的原理是什么?
从前文介绍arp协议里面来看,主机与主机的通信过程都会涉及到一个ip地址转换mac地址的过程,那么虚拟IP的通信也不会例外。因此,IP地址在主机通信的过程中其实就是一个逻辑地址。我们知道,每一个主机都存放着网络内一些主机的逻辑地址与物理地址(MAC地址)的映射,问题来了,当虚拟IP VIP在主机A上时,主机A的MAC地址为MAC_A某主机M的arp缓存中存放着一个映射关系:VIP ---à MAC_A;当主机A宕机后,虚拟IPVIP漂浮到了主机B,主机B的MAC地址为MAC_B,那么此时主机M想与虚拟IP通信时,是做不到,因为它的arp高速缓存中的虚拟IP VIP的映射还指向主机A的MAC地址。这个问题解决的思路就是当虚拟IP漂浮后,刷新所有其他主机的arp缓存。
那么虚拟IP是如何实现漂浮后,是如何刷新所有其他主机的arp缓存的呢?
这里就会引入另一个概念,garp()简称无端arp或者免费arp,主要是用来当某一个主机C开机时,用来确认自己的IP地址没有被人占用而做的一个检测。广播发送这个arp,请求得到本机IP地址的MAC地址,主机C并不希望此次arp请求会有arp应答,因为应答意味着IP地址冲突了。当其他主机收到这个arp请求后,会刷新关于这个arp请求源的主机IP地址的映射。
Garp的作用主要有两个:
1. 检测IP地址是否有冲突
2. 刷新其他主机关于本次IP地址的映射关系
集群管理软件Pacemaker里面的资源代理ocf:heartbeat:IPaddr2中,在虚拟IP漂浮后,会向网络内广播发送garp请求,以此来刷新其他主机的arp缓存。
在配置OpenStack控制节点高可用性的时候,出现过虚拟IP切换时,某一个主机不能通信的问题,后来发现是arp缓存没有刷新,有时候由于网络的原因,某些主机没有接收到此garp请求,因此ocf:heartbeat:IPaddr2资源代理中可以配置发送garp的次数,这里建议次数配置得多一点,这样可以保证其他主机成功刷新arp缓存。
资料来源:http://blog.csdn.net/u014532901/article/details/52245138
3. 谈谈VIP漂移那点破事
一直以来都是用nginx的upstream模块做网站最前端的负载均衡,为了防止nginx本身宕机导致网站不能访问,通常都会做两套nginx反向代理,然后用keepalive之类的软件提供VIP。
常见的环境是nginx主节点和从节点各有一个公网IP,一个私有IP,VIP地址也使用公网IP来提供,正常情况下VIP只会在nginx主节点上工作,只有主节点宕机或者网络不可达等情况下,VIP才会漂移到nginx从节点上。如果keepalive配置了非抢占模式,则主节点恢复后,VIP也不会漂移会主节点,而是继续在从节工作。这种配置要求机房网络不做mac地址绑定。
最近做的两套培训系统测试情况如下:
系统一:主从节点做双网卡绑定,都只有一个私有IP,VIP也为私有IP,通过防火墙的NAT转发用户的访问请求。主节点宕机后,VIP可以漂移至从节点,但用户无法访问网站,telnet防火墙公网IP的80端口提示无法连接。
系统二:主从节点各有两张网卡,分别配置一个公网IP和一个私有IP。VIP地址也使用公网IP来提供。
主节点宕机后,VIP可以漂移至从节点,但用户无法ping通VIP,自然网站也就打不开。
于是分别对这两种情况进行排查:
系统二:属于比较常见的配置方案。VIP漂移后无法ping通,第一反应询问机房工作人员,是否相应的设备做了mac地址绑定。得知无绑定策略后继续排查。
发现配置net.ipv4.ip_nonlocal_bind = 1 参数并使其生效后重新测试正常。
系统一:情况有点特殊,按系统二的解决方法尝试无果后,怀疑端口路由器映射上出现问题。于是继续测试VIP漂移,发现VIP漂移到从节点后,防火墙上的arp表中vip对应的mac地址依旧是主节点网卡的mac地址,原来防火墙才是罪魁祸首,坑爹的货。机房使用的防火墙型号华为Quidway Eudemon1000E,据说默认配置下,这个arp地址表自动刷新需要20分钟!
好吧!于是用下面的命名手工刷新后,万事大吉,网站访问也很顺畅,比较郁闷的是当主节点重新抢占VIP后,依然需要手工刷新下,否则防火墙还是把请求转给从节点响应。
# arping -I 网卡地址 -c 3 -s VIP地址 网关地址
后记:
要彻底解决系统一的问题,可以从两方面去着手,首先是考虑去调整防火墙的arp表的自动刷新时间;其次是考虑在从节点上部署一个无限循环的脚本,时时去检测是否抢占到了VIP,若抢占成功,则运行前面的刷新命令,命令成功运行后退出脚本,同时可以用nagios监控该脚本,了解最新的主从切换情况。切记,循环运行一次接受后sleep 1秒,否则会死机的哦!
如果在主节点上也部署类似的脚本,则会对网络带来负担,因而主节点恢复后的刷新手工运行下就好了,如果忘记运行了,从节点依然可以工作,无伤大雅!
资料来源:
http://ylw6006.blog.51cto.com/470441/1314004/
4.HA集群中的虚拟IP原理
高可用性HA(High Availability)指的是通过尽量缩短因日常维护操作(计划)和突发的系统崩溃(非计划)所导致的停机时间,以提高系统和应用的可用性。HA系统是目前企业防止核心计算机系统因故障停机的最有效手段。
实现HA的方式,一般采用两台机器同时完成一项功能,比如数据库服务器,平常只有一台机器对外提供服务,另一台机器作为热备,当这台机器出现故障时,自动动态切换到另一台热备的机器。
怎么实现故障检测的那?
心跳,采用定时发送一个数据包,如果机器多长时间没响应,就认为是发生故障,自动切换到热备的机器上去。
怎么实现自动切换那?
虚IP。何为虚IP那,就是一个未分配给真实主机的IP,也就是说对外提供数据库服务器的主机除了有一个真实IP外还有一个虚IP,使用这两个IP中的 任意一个都可以连接到这台主机,所有项目中数据库链接一项配置的都是这个虚IP,当服务器发生故障无法对外提供服务时,动态将这个虚IP切换到备用主机。
开始我也不明白这是怎么实现的,以为是软件动态改IP地址,其实不是这样,其实现原理主要是靠TCP/IP的ARP协议。因为ip地址只是一个逻辑 地址,在以太网中MAC地址才是真正用来进行数据传输的物理地址,每台主机中都有一个ARP高速缓存,存储同一个网络内的IP地址与MAC地址的对应关 系,以太网中的主机发送数据时会先从这个缓存中查询目标IP对应的MAC地址,会向这个MAC地址发送数据。操作系统会自动维护这个缓存。这就是整个实现 的关键。
下边就是我电脑上的arp缓存的内容。
(192.168.1.219) at 00:21:5A:DB:68:E8 [ether] on bond0
(192.168.1.217) at 00:21:5A:DB:68:E8 [ether] on bond0
(192.168.1.218) at 00:21:5A:DB:7F:C2 [ether] on bond0
192.168.1.217、192.168.1.218是两台真实的电脑,
192.168.1.217为对外提供数据库服务的主机。
192.168.1.218为热备的机器。
192.168.1.219为虚IP。
大家注意红字部分,219、217的MAC地址是相同的。
再看看那217宕机后的arp缓存
(192.168.1.219) at 00:21:5A:DB:7F:C2 [ether] on bond0
(192.168.1.217) at 00:21:5A:DB:68:E8 [ether] on bond0
(192.168.1.218) at 00:21:5A:DB:7F:C2 [ether] on bond0
这就是奥妙所在。当218 发现217宕机后会向网络发送一个ARP数据包,告诉所有主机192.168.1.219这个IP对应的MAC地址是00:21:5A:DB:7F:C2,这样所有发送到219的数据包都会发送到mac地址为00:21:5A:DB:7F:C2的机器,也就是218的机器。
5. 基于keepalived 实现VIP转移,lvs,nginx的高可用
一、Keepalived 高可用集群的解决方案
二、VRRP的有限状态机
三、利用keepalived 实现主从VIP的切换
四、实现在状态转变的时候自定义进行通知,
五、实现负载均衡
六:实现nginx的高可用
一、Keepalived 高可用集群的解决方案
最初的诞生是为ipvs提供高可用的,在后端的realserver接收不到主节点的信息之后,keepalived能够自己调用ipvsadm命令生成规则,能够自动实现,将主节点的VIP以及ipvs规则“拿过来”,应用在从节点上,继续为用户服务。还可以实现对后端realserver的健康状况做检测。
keepalived在一个节点上启动之后,会生成一个Master主进程,这个主进程又会生成两个子进程,分别是VRRP Stack(实现vrrp协议的) Checkers(检测ipvs后端realserver的健康状况检测)
二、VRRP的有限状态机
VRRP双方节点都启动以后,要实现状态转换的,刚开始启动的时候,初始状态都是BACKUP,而后向其它节点发送通告,以及自己的优先级信息,谁的优先级高,就转换为MASTER,否则就还是BACKUP,这时候服务就在状态为MASTER的节点上启动,为用户提供服务,如果,该节点挂掉了,则转换为BACKUP,优先级降低,另一个节点转换为MASTER,优先级上升,服务就在此节点启动,VIP,VMAC都会被转移到这个节点上,为用户提供服务,
实验环境:
虚拟主机版本:
CentOS6.4-i686
两个节点:
node1.limian.com 172.16.6.1
node2.limian.com 172.16.6.10
准备
1、节点一:
同步时间:
[root@node1 ~]# ntpdate 172.16.0.1
安装keepalived
[root@node1 ~]# yum -y install keepalived
2、节点二做同样的工作
三、利用keepalived 实现主从VIP的切换
3.1我们修改下keepalived的配置文件:
1
2
3
|
[root@node1 ~]# cd /etc/keepalived/ [root@node1 keepalived]# cp keepalived.conf keepalived.conf.back //先给配置文件备份一下 [root@node1 keepalived]# vim keepalived.conf |
3.2全局阶段
1
2
3
4
5
6
7
8
9
|
global_defs { notification_email { //定义邮件服务的 root@localhost //定义收件人,这里改为本机,只是测试使用 } notification_email_from kaadmin@localhost //定义发件人, smtp_server 127.0 . 0.1 //定义邮件服务器,一定不能使用外部地址 smtp_connect_timeout 30 //超时时间 router_id LVS_DEVEL } |
3.3定义vrrp阶段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
vrrp_instance VI_1 { //定义虚拟路由,VI_1 为虚拟路由的标示符,自己定义名称 state MASTER //开启后,该节点的优先级比另一节点的优先级高,所以转化为MASTER状态 interface eth0 //所有的通告等信息都从eth0这个接口出去 virtual_router_id 7 //虚拟路由的ID,而且这个ID也是虚拟MAC最后一段的来源,这个ID号一般不能大于255,且这个ID一定不能有冲突 priority 100 //初始优先级 advert_int 1 //通告的个数 authentication { //认证机制 auth_type PASS //认证类型 auth_pass 1111 //密码,应该为随机的字符串 } virtual_ipaddress { //虚拟地址,即VIP 172.16 . 6.100 } } |
这样我们主节点的配置文件就修改好了,需要复制到从节点上,再做适当的修改就可以使用了
1
|
[root@node1 keepalived]# scp keepalived.conf 172.16 . 6.1 :/etc/keepalived/ |
3.4登录到从节点;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[root@node2 ~]# cd /etc/keepalived/ [root@node2 keepalived]# vim keepalived.conf vrrp_instance VI_1 { state BACKUP //修改从节点的状态,主节点为MASTER,从节点就为BACKUP interface eth0 virtual_router_id 7 priority 99 //修改优先级,注意从节点的优先级一定要小于主节点 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.16 . 6.100 } } |
3.5然后在主节点启动服务
1
2
|
[root@node1 keepalived]# service keepalived start [root@node1 ~]# ip addr show //查看我们定义的VIP |
3.6在从节点启动服务
[root@node2 keepalived]# service keepalived start
把主节点上的服务停掉,看VIP会不会到从节点上
[root@node2 ~]# ip addr show
3.7在主节点上启动服务
1
2
|
[root@node1 ~]# service keepalived start [root@node1 ~]# ip addr show //检测结果发现VIP转移到了主节点 |
注:
默认情况下ARRP工作在“抢占模式”下,如果发现一个节点的服务停止了,另一个节点会立即把VIP和VMAC“抢过来”,如果在“非抢占模式”下,无论你的优先级过高,一个节点服务停止,另一个节点也不会“抢”VIP和VMAC,除非这个节点挂了,两一个节点才会“抢”。
四、实现在状态转变的时候自定义进行通知,
4.1这需要依赖于脚本来完成
主节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
[root@node1 ~]# cd /etc/keepalived/ [root@node1 keepalived]# vim notify.sh //编写脚本 #!/bin/bash vip= 172.16 . 6.100 contact= 'root@localhost' thisip=`ifconfig eth0 | awk '/inet addr:/{print $2}' | awk -F: '{print $2}' ` Notify() { mailsubject= "$thisip is to bi $vip master" mailbody= "vrrp transaction, $vip floated to $thisip" echo $mailbody | mail -s "$mailsubject" $contact } case "$1" in master) notify master exit 0 ;; backup) notify backup exit 0 ;; fault) notify fault exit 0 ;; *) echo 'Usage: `basename $0` {master|backup|fault}' exit 1 ;; esac [root@node1 keepalived]# chmod +x notify.sh [root@node1 keepalived]# ./notify.sh master [root@node1 keepalived]# mail //查看有没有收到通知 Heirloom Mail version 12.4 7 / 29 / 08 . Type ? for help. "/var/spool/mail/root" : 1 message 1 new >N 1 root Wed Sep 25 14 : 54 18 / 668 "172.16.6.10 is to bi 172.16.6.100 mas" & |
转换状态查看是否会收到通知
1
2
3
4
5
6
7
8
9
|
[root@node1 keepalived]# ./notify.sh backup [root@node1 keepalived]# ./notify.sh fault [root@node1 keepalived]# mail Heirloom Mail version 12.4 7 / 29 / 08 . Type ? for help. "/var/spool/mail/root" : 3 messages 2 new 1 root Wed Sep 25 14 : 54 19 / 679 "172.16.6.10 is to bi 172.16.6.100 mas" >N 2 root Wed Sep 25 14 : 57 18 / 668 "172.16.6.10 is to bi 172.16.6.100 mas" N 3 root Wed Sep 25 14 : 57 18 / 668 "172.16.6.10 is to bi 172.16.6.100 mas" & |
说明脚本正常工作,那么去编辑配置文件
1
|
[root@node1 keepalived]# vim keepalived.conf |
在全局阶段添加
1
2
3
4
5
|
vrrp_script chk_mantaince_down{ //定义可以手动控制状态的脚本 script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0" interval 1 //检查时间间隔 weight - 2 //如果检测失败,优先级-2 } |
在vrrp阶段添加如下几行
1
2
3
4
5
6
|
track_script { //引用定义的脚本 chk_mantaince_down } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" |
4.2将该脚本复制到另一个节点,
1
|
[root@node1 keepalived]# scp notify.sh 172.16 . 6.1 :/etc/keepalived/ |
并在配置文件中相应的位置添加相同内容
两个节点都重启服务
4.3让主节点变成从节点
1
|
root@node1 keepalived]# touch down |
通过监控,发现主节点立即变成从节点,并收到一封邮件
1
2
|
[root@node1 keepalived]# tail -f / var /log/messages You have new mail in / var /spool/mail/root |
五、实现负载均衡
5.1编辑配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
[root@node1 keepalived]# vim keepalived.conf #####负载均衡阶段################# virtual_server 172.16 . 6.100 80 { //指定VIP和端口 delay_loop 6 //延迟多少个周期再启动服务,做服务检测 lb_algo rr loadbalance 负载均衡调度算法 lb_kind DR 类型 nat_mask 255.255 . 0.0 掩码 persistence_timeout 0 持久连接时间 protocol TCP //协议 real_server 172.16 . 6.11 80 { //定义后端realserver的属性 weight 1 HTTP_GET { //定义检测的方法 url { //检测的URL path / status_code 200 //获取结果的状态码 } connect_timeout 3 //连接超时时间 nb_get_retry 3 //尝试次数 delay_before_retry 3 //每次尝试连接的等待时间 } } real_server 172.16 . 6.12 80 { //定义后端realserver的属性 weight 1 HTTP_GET { //定义检测的方法 url { //检测的URL path / status_code 200 //获取结果的状态码 } connect_timeout 3 //连接超时时间 nb_get_retry 3 //尝试次数 delay_before_retry 3 //每次尝试连接的等待时间 } } } |
5.2、在从节点上做同样的修改
5.3重启服务并用ipvsadm命令检测是否会生成规则
1
2
3
4
5
6
7
|
[root@node1 keepalived]# service keepalived restart [root@node1 keepalived]# ipvsadm -L -n IP Virtual Server version 1.2 . 1 (size= 4096 ) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.16 . 6.100 : 80 rr [root@node1 keepalived]# |
但是为什么没有我们定义的两个realserver呢?那是因为没启动虚拟机呢,健康状况检测没通过,就不会显示了,我们去启动一个虚拟机,并启动服务即可。
并执行如下命令,做lvs负载均衡的DR模型
1
2
3
4
5
6
|
#ifconfig lo: 0 172.16 . 6.11 broadcast 172.16 . 6.11 netmask 255.255 . 255.255 up #route add -host 172.16 . 6.11 dev lo: 0 #echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore #echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore #echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce #echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce |
注:
1、后端的realserver的数量可以添加多台,但是需要在主节点的配置文件中给出相应的配置,并在添加的realserver上执行相关命令即可
2、尽管keepalived可以自行添加ipvs规则,实现负载均衡,但是无法实现动静分离,在生产环境中我们要根据场景选择最佳的方案。
六:实现nginx的高可用
6.1前提
两个节点上都装上nginx服务,并确保httpd没启用
# netstat -tunlp //确保80端口没占用
# service nginx start
6.2为每个节点的nginx编辑一个页面,以便于效果更直观一些
1
2
3
4
|
[root@node1 ~]# vim /usr/share/nginx/html/index.html //节点1 172.16 . 6.10 [root@node2 ~]# vim /usr/share/nginx/html/index.html //节点2 172.16 . 6.1 |
6.3确保nginx可以正常访问
6.4然后停掉服务,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
[root@node1 keepalived]# vim notify.sh //修改脚本,让它可以监测nginx服务,并可以启动或关闭服务 ################## case "$1" in master) notify master /etc/rc.d/init.d/nginx start exit 0 ;; backup) notify backup /etc/rc.d/init.d/nginx stop exit 0 ;; fault) notify fault /etc/rc.d/init.d/nginx stop exit 0 ;; ###################################### |
6.5同步脚本到节点2
1
|
[root@node1 keepalived]# scp notify.sh 172.16 . 6.1 :/etc/keepalived/ |
6.6在主节点上
1
2
3
4
|
[root@node1 keepalived]# touch down [root@node1 keepalived]#ss -tunl //发现80端口未被监听 [root@node1 keepalived]# rm -f down [root@node1 keepalived]#ss -tunl //发现80端口已经被监听 |