定义虚拟路由并实现后端检测状态

 

1.定义在状态转换时进行通知

keepalived内部提供了两个配置指令,具体可以man keepalived.conf 进行查找帮助

[root@node1 keepalived]# man keepalived.conf

找到以下说明:

VRRP synchronization group(s)
        #string,  name  of group  of  IPs  that  failover
       together
        vrrp_sync_group VG_1 {
           group {
            inside_network    #  name  of  vrrp_instance
       (below)
            outside_network   # One for each moveable IP.
             ...
           }           #notify scripts and alerts are optional
           #
           # filenames ofscripts to run on transitions
           # can be unquoted(if just filename)
           # or quoted (ifhas parameters)
           # to MASTERtransition
           notify_master/path/to_master.sh
           # to BACKUPtransition
           notify_backup/path/to_backup.sh
           # FAULT transition
           notify_fault"/path/fault.sh VG_1"

           # for ANY statetransition.
           #"notify" script is called AFTER the
           # notify_*script(s) and is executed
           # with 3 argumentsprovided by keepalived
           # (ie don’t include parameters  in  the  notify
       line).
           # arguments
           # $1 ="GROUP"|"INSTANCE"
           # $2 = name ofgroup or instance
           # $3 = targetstate of transition
          #    ("MASTER"|"BACKUP"|"FAULT")          notify /path/notify.sh

           #  Send email notifcation during state transi-
       tion,
           # using addressesin global_defs above.
           smtp_alert
        }

以上明确说明,通常在vrrp_instance{ .. }中可以使用

而指令通常有两种方式:                   

·第一种方式:

     

notify_master /path/to_master.sh
           notify_backup/path/to_backup.sh
           notify_fault"/path/fault.sh VG_1"

从名字上我们即可看出,将一个从节点转为master状态的时候则执行后面的脚本

如果变成backup的状态以此类推

如果脚本带有参数,这个脚本需要用引号引起来,务必要注意这样一点

 

·第二个方式:

使用notify方式进行通知,而不用直接使用状态然后执行脚本进行通知

            

notify /path/notify.sh

但是这时候notify脚本的内容必须能够应付三类状态

# $1 = "GROUP"|"INSTANCE"              #当前组或实例,必须明确指定是group 还是nstance,因为通知机制可以用在group中也可以用在instance中
  # $2 = name of group or instance           #如果是实例的话,实例名称必须定义
  # $3 = target state of transition           #明确说明转换成什么状态并进行通知的

 

编写notify通知脚本:

我们以nginx为例,检测其当前节点如果为master则启动nginx,如果是backup则停止nginx,以此类推

#!/bin/bash
vip=10.0.10.100
contact='root@localhost'

notify() {
    mailsubject="`hostname` to be $1: $vip floating"
    mailbody="`date '+%F %H:%M:%S'`: vrrp transition,`hostname` changed to be $1"
    echo $mailbody | mail -s "$mailsubject" $contact
}

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
    ;;
    *)
        echo 'Usage: `basename $0`{master|backup|fault}'
        exit 1
    ;;
esac

授权

[root@node1 keepalived]# chmod +x notify.sh

 

测试查看将其切换至master

查看邮件是否通知

[root@node1 keepalived]# sh notify.sh backup
 [root@node1 keepalived]# mail
Heirloom Mail version 12.4 7/29/08.  Type ? for help.
"/var/spool/mail/root": 1 message 1new
>N  1 root                  Mon Jun  9 15:06 18/686   "node1 to be backup:10.0.10.100 floating"

 

使其在整个配置中生效

接下来编辑keepalived配置文件使其在整个配置中生效

#找到vrrp_instance参数模块并在大括号内插入参数
   notify_master "/etc/keepalived/notify.sh master"
   notify_backup "/etc/keepalived/notify.sh backup"
   notify_fault "/etc/keepalived/notify.sh fault"
双方都重启keepalived
/etc/init.d/keepalived restart
查看邮件
[root@node1 keepalived]# mail
Heirloom Mail version 12.4 7/29/08.  Type ? for help.
"/var/spool/mail/root": 2 messages1 new
    1root                  Mon Jun  9 15:06 19/697   "node1 to be backup:10.0.10.100 floating"
>N 2 root                  MonJun  9 15:20  18/686  "node1 to be master: 10.0.10.100 floating"

以上通过脚本方式实现通知机制,那么调度外部服务启动也无非是这种方式,万一当前节点故障了监控不到某个服务了,可以将优先级降低,资源转移并且发送通知然后将服务kill掉 即可

 

2.整合keepalived配置ipvs

准备环境:

服务器IP

服务器角色

操作系统

10.0.10.61

Master

CetnOS 6.4

10.0.10.62

Slave

CetnOS 6.4

10.0.10.83

RealServer

CetnOS 6.4

10.0.10.84

RealServer

CetnOS 6.4

 

配置keepalived.conf

[root@node1 keepalived]# vim keepalived.conf

将之前注释的参数开启,并修改,如下所示:

virtual_server 10.0.10.100 80 {
   delay_loop 6
   lb_algo wlc                                #使用的调度算法
   lb_kind DR                                 #使用的模式
   nat_mask 255.255.255.0                     #子网掩码
   persistence_timeout 0                      #持久时间
   protocol TCP                               所使用的网络协议
##而后在其中定义realserver,每个realserver在内都有一realserver模块进行定义
 
   real_server 10.0.10.83 80 {                #第一个realserver
       weight 1                               #权重
#使用的http_get方式,说明对方是http服务器,默认是443,如果是443的话说明对端是https服务,根据需求定义   
       HTTP_GET {
           url {
             path /                           #检测哪个url
             status_code 200                  #检测rul并且返回值是200说明正常
           }
           connect_timeout 3                  #尝试的超时时间
           nb_get_retry 3                     #最少尝试几次
           delay_before_retry 3               #在每次尝试之前等待几秒钟
       }
    }
}
 
   real_server 10.0.10.84 80 {
       weight 1
       HTTP_GET {
           url {
             path /
             status_code 200
           }
           connect_timeout 3
           nb_get_retry 3
           delay_before_retry 3
       }
    }
}

在实现定义realserver的时候还可以定义notify,当然,这是后话了

 

保存配置并重启服务

[root@node1 keepalived]#/etc/init.d/keepalived restart

查看ipvs的状态分发情况

[root@node1 keepalived]# ip add | awk '/inet10.0.10.100/ {print $2}'
10.0.10.100/32
[root@node1 keepalived]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  ->RemoteAddress:Port           ForwardWeight ActiveConn InActConn
TCP 10.0.10.100:80 wlc
  ->10.0.10.83:80                Route   1     0          0         
  ->10.0.10.84:80                Route   1     0          0

而后查看邮件通知

#已看到realsver陆续上线了

[root@node1 keepalived]# mail
Heirloom Mail version 12.4 7/29/08.  Type ? for help.
N 1 Alexandre.Cassen@fir  Mon Jun 9 21:04  17/608   "[LVS_DEVEL] Realserver [10.0.10.84]:80 -UP"

 

可是只有状态,但是没有分发,接下来我们还需要对realserver进行配置:

切换至任意realserver

配置内核参数

echo 1 >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announcesysctl -p

将vip配置在外网接口的别名上

[root@mode ~]# ifconfig eth1:100 10.0.10.100broadcast 10.0.10.100 netmask 255.255.255.255 up
配置lo接口
[root@mode ~]#  ifconfig lo:0 10.0.10.100 broadcast10.0.10.100 netmask 255.255.255.255 up
添加路由信息
#如果ip是10.0.10.100的ip那么则通过lo:0的接口出去,主机路由的优先级是要比网络路由的优先级要高的
[root@mode ~]# route  add -host 10.0.10.100 dev lo:0
[root@mode ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.10.100     0.0.0.0         255.255.255.255 UH    0     0        0 lo
10.0.10.0       0.0.0.0         255.255.255.0   U    0      0        0 eth1
169.254.0.0     0.0.0.0         255.255.0.0     U    0      0        0 eth1
10.0.0.0        0.0.0.0         255.0.0.0       U    0      0        0 eth1

访问测试:

[root@node2 keepalived]# ab -n 100 -c 100 http://10.0.10.100/index.html

查看分发状态

[root@node1 keepalived]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  ->RemoteAddress:Port           ForwardWeight ActiveConn InActConn
TCP 10.0.10.100:80 wlc
  ->10.0.10.83:80                Route   1     0          46        
  ->10.0.10.84:80                Route   1     0          48  
为了方便配置realserver ,这里为大家提供了脚本,只需要更改vip地址即可
#!/bin/bash
VIP=(
     Vip地址在这里填写
     )
 
/etc/rc.d/init.d/functions
 
case "$1" in
start)
       echo "start LVS of REALServer"
 
       for ((i=0; i<`echo ${#VIP[*]}`; i++))
       do
                interface="lo:`echo${VIP[$i]}|awk -F . '{print $4}'`"
                /sbin/ifconfig $interface${VIP[$i]} broadcast ${VIP[$i]} netmask 255.255.255.255 up
       done
       echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
       echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
       echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
       echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
       ;;
stop)
       for ((i=0; i<`echo ${#VIP[*]}`; i++))
       do
                interface="lo:`echo${VIP[$i]}|awk -F . '{print $4}'`"
                /sbin/ifconfig $interface${VIP[$i]} broadcast ${VIP[$i]} netmask 255.255.255.255 down
       done
       echo "close LVS Directorserver"
       echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
       echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
       echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
       echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
       ;;
*)
       echo "Usage: $0 {start|stop}"
       exit 1
esac

 

3.对某特定服务是实现高可用

大致步骤为:

1、在vrrp_script { }中定义监控服务

2、在track_script{ }实例中追踪服务

3、一点监控发现失败的话则降低优先级

 

这里我们以nginx为例,前提必须将两节点安装nginx服务

要借助于通知脚本来完成,必须要实现通知的同时启动服务,一旦对方转换成master则启动backup和fault则stop 

配置nginx 将每个nginx配置页面文件确保其正常

[root@node2 nginx]# curl http://10.0.10.61
node1
[root@node2 nginx]# curl http://10.0.10.62
node2

首先我们来还原配置文件,然后定义其监控服务

接下来让通知脚本发挥作用并且能够在其转换至master的时候将服务顺便启动

更改notify脚本:

#!/bin/bash
vip=10.0.10.100
contact='root@localhost'

notify() {
    mailsubject="`hostname` to be $1: $vip floating"
    mailbody="`date '+%F %H:%M:%S'`: vrrp transition,`hostname` changed to be $1"
    echo $mailbody | mail -s "$mailsubject" $contact
}

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
    ;;
    *)
        echo 'Usage: `basename $0`{master|backup|fault}'
        exit 1
    ;;
esac

先重启keepalived 查看nginx服务是否会随之启动

[root@node1 keepalived]#/etc/init.d/keepalived restart
[root@node1 keepalived]# netstat -lnt | grep80
tcp       0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN

关闭主节点,并在备节点查看

[root@node1 keepalived]#/etc/init.d/keepalived stop
[root@node1 keepalived]# ssh node2 'netstat-lnt | grep 80'
tcp       0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN

添加监控服务脚本

如果不添加监控服务会导致服务没启动但已经故障了,而且资源还没有被转移,所以要监控服务本身的状态

#检测开销最小的是kill -0 的方式,表示测试停止服务是否存在,如果返回值为0为正常 非0为错误

编辑配置文件,再加入vrrp_script,如下所示:

vrrp_script chk_nginx{
  script "killall -0 nginx &> /dev/null && exit 0 ||exit 1 "
  interval 1
  weight -5                      #如果返回值非0,则将权重减5,意味着切换至backup状态
  #fall  2              #如果失败则重新尝试2次
  #rise 1               #认为重试几次为成功
}

使双方的keepalived 重启,并查看主节点是否启动监听端口

[root@node1 keepalived]#/etc/init.d/keepalived restart
[root@node1 keepalived]# netstat  -lnt | grep 80
tcp       0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN

将主节点的nginx关闭,并观察其日志

[root@node1 keepalived]# /etc/init.d/nginxstop

追踪日志

[root@node1 ~]# tail -f /var/log/messages
Jun 10 10:43:51 node1 Keepalived_vrrp[7840]: VRRP_Script(chk_nginx)failed
Jun 10 10:43:53 node1 Keepalived_vrrp[7840]:VRRP_Instance(VI_1) Received higher prio advert
Jun 10 10:43:53 node1 Keepalived_vrrp[7840]:VRRP_Instance(VI_1) Entering BACKUP STATE
Jun 10 10:43:53 node1 Keepalived_vrrp[7840]:VRRP_Instance(VI_1) removing protocol VIPs.
Jun 10 10:43:53 node1Keepalived_healthcheckers[7839]: Netlink reflector reports IP 10.0.10.100removed

可看到,其已切换至backup状态并且将vip从机移除

 

4.使双节点服务同时运行(双主模型)

现在我们定义2个mac地址,2个ip并通过DNS添加多条A记录实现轮询的方式,不同的用户解析不同的主机

我们不要求其绝对的均衡,因为我们前端很可能是提供反向代理的服务,如果是web服务的话尽可能不要使用这样的方案

因此这样一来 两个节点都能分发用户的请求到后端的各上游服务器上去,于是就能实现正常转发

 

双主模型只要定义两个instance并分别为主备即可

还原配置文件,定义双主节点

Node1配置如下:

[root@node1 keepalived]# cat keepalived.conf
! Configuration File for keepalived
 
global_defs {
  notification_email_from admin@localhos {
     root@localhost
   }
 
  notification_email_from Alexandre.Cassen@firewall.loc
  smtp_server 127.0.0.1
  smtp_connect_timeout 30
  router_id LVS_DEVEL
}
 
vrrp_instance VI_1 {
   state MASTER
   interface eth0
   virtual_router_id 61
   priority 100
   advert_int 1
   authentication {
       auth_type PASS
       auth_pass 1111
    }
   virtual_ipaddress {
       10.0.10.100
    }
 
}
virtual_server 10.0.10.100 80 {
   delay_loop 6
    lb_algo rr
   lb_kind DR
   nat_mask 255.255.255.0
   persistence_timeout 0
   protocol TCP
 
   real_server 10.0.10.83 80 {
       weight 1
       HTTP_GET {
           url {
             path /
           status_code 200
           }
           connect_timeout 3
           nb_get_retry 3
           delay_before_retry 3
       }
    }
 
#定义第二个虚拟路由,其状态为备状态
vrrp_instance VI_2 {
   state BACKUP
   interface eth0
   virtual_router_id 62
   priority 99
   advert_int 1
   authentication {
       auth_type PASS
       auth_pass 1112
    }
   virtual_ipaddress {
       10.0.10.110
    }
}
virtual_server 10.0.10.110 80 {
   delay_loop 6
   lb_algo rr
   lb_kind DR
   nat_mask 255.255.255.0
   persistence_timeout 0
   protocol TCP
       
   real_server 10.0.10.83 80 {
       weight 1
       HTTP_GET { 
           url {
             path /
             status_code 200
           }
           connect_timeout 3
           nb_get_retry 3
           delay_before_retry 3
       }
    }

 

Node2配置如下:

[root@node2 keepalived]# cat keepalived.conf
! Configuration File for keepalived
 
global_defs {
  notification_email_from admin@localhos {
     root@localhost
   }
 
  notification_email_from Alexandre.Cassen@firewall.loc
  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 61
   priority 99
   advert_int 1
   authentication {
       auth_type PASS
       auth_pass 1111
    }
   virtual_ipaddress {
       10.0.10.100
    }
}
 
   real_server 10.0.10.83 80 {
       weight 1
       HTTP_GET {
           url {
             path /
             status_code 200
           }
           connect_timeout 3
           nb_get_retry 3
           delay_before_retry 3
       } 
    }
 
vrrp_instance VI_2 {
   state MASTER
   interface eth0
   virtual_router_id 62
   priority 100
   advert_int 1
   authentication {
       auth_type PASS
       auth_pass 1112
    }
   virtual_ipaddress {
       10.0.10.110
    }
 
}
virtual_server 10.0.10.110 80 {
   delay_loop 6
   lb_algo rr
   lb_kind DR
   nat_mask 255.255.255.0
   persistence_timeout 0
   protocol TCP
 
   real_server 10.0.10.83 80 {
       weight 1
       HTTP_GET {
           url {
             path /
           status_code 200
           }
           connect_timeout 3
           nb_get_retry 3
           delay_before_retry 3
       }
    }

接下来只要在DNS后台将其A记录进行解析即可,这里我们由于是实验环境所以只能访问不同的ip进行测试

[root@node2 nginx]# curl http://10.0.10.110
10.0.10.83
[root@node2 nginx]# curl http://10.0.10.100
10.0.10.83

 

END,感谢各位。



转载于:https://blog.51cto.com/yijiu/1424509