基于keepalived实现高可用集群

HA Cluster的实现方案

vrrp协议的实现:keepalived
VRRP协议的目的就是为了解决静态路由单点故障问题;VRRP通过竞选(election)协议来动态的将路由任务交给LAN中虚拟路由器中的某台VRRP路由器。

vrrp协议

(Virtual Redundant Routing Protocol):虚拟冗余路由协议

vrrp中的术语
VR 虚拟路由器
VRID 虚拟路由器的标识号(0-255)
Master(Active) 主路由器(活动节点)
Backup(Passive) 备份路由器(被动节点)
VIP 虚拟IP地址;流动(浮动)IP
VMAC VIP对应的虚拟MAC地址(48位);00-00-5E-00-01-{VRID}
优先级 初始化过程中就决定了优先级
gracious arp 免费arp广播
vrrp工作方式
  • 抢占式:如果 Backup 路由器工作在抢占方式下,当它收到 VRRP 报文后会将自己的优先级与通告报文中的优先级进行比较。如果自己的优先级比当前的 Master 路由器的优先级高就会主动抢占成为 Master 路由器否则将保持 Backup 状态。
  • 非抢占式:如果 Backup 路由器工作在非抢占方式下则只要 Master 路由器没有出现故障Backup 路由器即使随后被配置了更高的优先级也不会成为Master 路由器。
vrrp认证方式与工作模式

认证方式

  • 无认证
  • 简单字符串认证:预共享密钥
  • md5认证

工作模式

  • master-backup模式
  • master-master模式
vrrp工作原理
  • 一个VRRP路由器有唯一的标识:VRID,范围为0-255,该路由器对外表现为唯一的虚拟MAC地址,地址的格式为00-00-5E- 00-01-[VRID],主控路由器负责对ARP请求用该MAC地址应答,保证给终端设备的是唯一一致的IP和MAC地址,减少了切换对终端设备的影响。

  • VRRP控制报文只有一种:
    VRRP通告(advertisement)使用IP多播数据包进行封装,组地址为224.0.0.18,发布范围只限于同一局域网内。这保证了VRID在不同网络中可以重复使用。

  • 在VRRP路由器组中按优先级选举主控路由器

  • 为了保证VRRP协议的安全性,提供了两种安全认证措施:明文认证和IP头认证

vrrp优势
  • 负载共享:允许来自LAN客户端的流量由多个路由器设备所共享;
  • 多VRRP组:在一个路由器物理接口上可配置多达255个VRRP组;
  • 抢占:在master故障时允许优先级更高的backup成为master;
  • 通告协议:使用IANA所指定的组播地址224.0.0.18进行VRRP通告;
  • VRRP追踪:基于接口状态来改变其VRRP优先级来确定最佳的VRRP路由器成为master;
  • 冗余:可以使用多个路由器设备作为LAN客户端的默认网关,大大降低了默认网关成为单点故障的可能性;
  • 多IP地址:基于接口别名在同一个物理接口上配置多个IP地址,从而支持在同一个物理接口上接入多个子网;

keepalived

Keepalived是基于VRRP协议实现的保证集群高可用的一个服务软件,运行在LVS之上,它的主要功能是实现真机的故障隔离及负载均衡器间的失败切换FailOver,可以防止单点故障。LVS结合keepalived,就实现了3层、4层、5/7层交换的功能

ka能够根据配置文件中定义自动生成ipvs规则(增、删),并能够对各RS的健康状态进行检测;
支持vrrp_script接口,vrrp_track;
通过编写vrrp脚本,通过vrrp_track跟踪各种服务;

keepalived组件
keepalived架构
  • 控制面板(组件):配置文件分析器,内存管理,IO复用

  • 核心组件:vrrp stack,checker,ipvs wrapper,watch dog,smtp接口

只支持简单字符串认证

组件
vrrp stack 实现vrrp协议
smtp 发送通知邮件;可在地址流动时发邮件,还可根据checkers检查后把宕机从从ipvs规则中移除,发出此邮件
checkers 检测后端RS健康状态,可基于tcp、htp、ssl、misc检测;发现宕机就从ipvs规则中移除
watchdog 实现监控vrrp stack和checkers的健康
ipvs wrapper checkers通过调用该包装器,来实现在ipvs中添加、删除或修改规则
HA Cluster配置的前提:(各调度器)

(1)各节点时间同步
基于ntp协议同步,chrony(centos 7)

(2)确保iptables及selinux不会阻碍
心跳信息传递:3种方式

  • 单播
  • 广播
  • 组播:最佳使用方式;组播地址:224.0.0.0-239.0.0.0

(3)各节点之间可通过主机名相互通信(对ka并非必须,ka是无所谓的)
名称解析服务的解析结果必须与“uname -n”命令的结果一致;
如果是主机名通信,dns解析名必须与真实主机名一致;

(4)各节点之间的root用户可以基于密钥认证的sh通信,(对ka并非必须,ka无所谓)

配置示例

准备两台centos7主机,先做时间同步:

[root@node1 ~]# ntpdate 172.18.0.1

创建自动计划任务,向时间服务器每5分钟同步一次时间

[root@node1 ~]# crontab -e
*/5 * * * * /usr/sbin/ntpdate 172.18.0.1 &> /dev/null

安装keepalived并配置

[root@node1 ~]# yum -y install keepalived
...
Complete!
[root@node1 ~]# rpm -ql keepalived
/etc/keepalived
/etc/keepalived/keepalived.conf
/etc/sysconfig/keepalived
/usr/bin/genhash
/usr/lib/systemd/system/keepalived.service
/usr/libexec/keepalived
/usr/sbin/keepalived
...
[root@node1 ~]# cd /etc/keepalived/
[root@node1 keepalived]# cp keepalived.conf{,.bak}
[root@node1 keepalived]# vim /etc/keepalived/keepalived.conf
:set nohlsearch 
:.,$s/^/#/g
#先只配置全局段和虚拟路由实例段,其它都注释;
global_defs {  #全局配置段
   notification_email {  #接收通告邮件的地址,收件人
     root@localhost 
   }
   notification_email_from kaadmin@magedu.com  #发件人
   vrrp_iptables #不自动生产iptables规则
   smtp_server 127.0.0.1  #配置邮件服务器,要求能在互联网上正反解析;
   smtp_connect_timeout 30  #邮件服务器的超时时长
   router_id node1  #定义当前路由器设备的ID号,一般为主机名;
   vrrp_mcast_group4  224.0.11.18  #组播地址,默认为224.0.0.18,但是集群里的所有节点都有使用此地址;表示同一个组播域;
}

vrrp_instance VI_1 {  #虚拟路由器配置段,实例名称为VI_1,也可自定义;
    state MASTER  #当前节点在此虚拟路由器中的初始状态;表示为主节点;取值为:MASTER|BACKUP;
    interface eno16777736  #表示vrrp发送通告的接口;
    virtual_router_id 11  #虚拟路由器ID,范围0-255;
    priority 100  #当前物理节点在此虚拟路由器中的优先级;
    advert_int 1  #表示vrrp的通告的时间间隔;为1秒;
    authentication {  #认证方式
        auth_type PASS  #使用简单密码认证
        auth_pass vHFHLlTA  #随机随机字符串,可使用openssl rand -base64 10生成,前8位字符有效;;
    }
    virtual_ipaddress {  #定义虚拟IP,不指明则为前面的interface指明的接口地址;
        172.18.11.66  #网卡别名地址,可写为172.18.11.66 dev eno16777736 label eno16777736:0
    }
}

配置文件复制到另一调度器172.18.11.121上

[root@node1 ~]# scp keepalived.conf root@172.18.11.121:/etc/keepalived

在172.18.11.121编辑该配置文件

[root@node2 ~]# vim /etc/keepalived/keepalived.conf
修改:
state BACKUP #修改为备用
priority 50 #修改小优先级;
#密码、router_id、vrrp_mcast_group4要保存一致;

在两个调度器上开启keepalived服务

[root@node1 ~]# systemctl start keepalived.service
[root@node2 ~]# systemctl start keepalived.service

分别查看两个调度器,VIP地址是否自动在主服务器的接口别名上:

[root@node1 ~]# ip addr l
[root@node2 ~]# ip addr l
[root@node1 ~]# tail /var/log/messages
[root@node2 ~]# tail /var/log/messages

手动使172.18.11.111主用服务器停止keepalived服务,再查看

[root@node1 ~]# ip addr l]# systemctl stop keepalived.service

用另一终端查看日志信息不退出

[root@centos7 ~]# tail -f /var/log/messages
显示部分内容:
May 10 05:25:01 localhost systemd: Stopping LVS and VRRP High Availability Monitor...
May 10 05:25:01 localhost Keepalived_vrrp[4258]: VRRP_Instance(VI_1) sending 0 priority 发送优先级为0的报文;
May 10 05:25:01 localhost Keepalived_vrrp[4258]: VRRP_Instance(VI_1) removing protocol VIPs. 移除VIP的协议
May 10 05:25:01 localhost Keepalived_healthcheckers[4257]: Netlink reflector reports IP 172.18.11.66 removed 移除VIP
May 10 05:25:01 localhost systemd: Stopped LVS and VRRP High Availability Monitor

在另一调度器172.18.11.121上,查看日志

[root@node2 ~]# tail  /var/log/messages
May  9 08:09:21 localhost Keepalived_vrrp[3881]: VRRP_Instance(VI_1) Transition to MASTER STATE 称为主用服务器
May  9 08:09:22 localhost Keepalived_vrrp[3881]: VRRP_Instance(VI_1) Entering MASTER STATE 确认主用状态
May  9 08:09:22 localhost Keepalived_vrrp[3881]: VRRP_Instance(VI_1) setting protocol VIPs. 设置
May  9 08:09:22 localhost Keepalived_vrrp[3881]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eno16777736 for 172.18.11.66 发送免费ARP报文
May  9 08:09:22 localhost Keepalived_healthcheckers[3880]: Netlink reflector reports IP 172.18.11.66 added 获得VIP地址
May  9 08:09:27 localhost Keepalived_vrrp[3881]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eno16777736 for 172.18.11.66
May  9 08:10:01 localhost systemd: Started Session 58 of user root.
May  9 08:10:01 localhost systemd: Starting Session 58 of user root.
May  9 08:10:01 localhost systemd: Started Session 59 of user root.
May  9 08:10:01 localhost systemd: Starting Session 59 of user root.

再手动使172.18.11.111主用服务器上线:

[root@node1 ~]# systemctl start keepalived.service
#默认工作在抢占模式;优先级高的会自动成为主用服务器;

这就是keepalived自动完成地址浮动;

修改两个调度器的VIP别名:

[root@node1 ~]# vim /etc/keepalived/keepalived.conf
virtual_ipaddress{
172.18.11.66 dev eno16777736 label eno16777736:0
}

把两个调度器停止keepalived服务:
先启动优先级低的服务器:172.18.11.121:

[root@node2 ~]# systemctl start keepalived.service

此时使用ifconfig命令,engine查看网卡别名,已经自动加上了;

再启动优先级高的服务器:172.18.11.111:

[root@node1 ~]# systemctl start keepalived.service

vrrp有两种工作模型:主/备主/主
为了提高利用率,就使用主/主工作模型;
即A主B从,B主A从;这样AB都能发挥作用;在外部都称为主时,可在前端dns配置A记录把两个ip都配置在一个主机名上即可;
但在有些场景中,AB都称为主时不是配置在同一网卡上的两个不同的别名,而是分别配置在两块网卡上;
AB每个主机都有两块网卡,一块网卡面向外网,一块网卡面向内网通信;期望通信时,这两个地址都是VIP,只不过,前面外网是虚拟路由器1,内网是虚拟路由器2;
里面的别名配置在内网网卡上,外面的别名配置在外网网卡上;当外网其中一个线路掉线时,可自动切换到另一个外网网卡的服务器上,要求而也要内网同样要切换;要求内外通信使用VIP,所以没有必要切换的内网也要切换;
这种把两个虚拟路由器,配置为只能对一个设备是主服务器,同进同退,这种就叫做一个同步组;

安装keepalived
  • Centos6.4+,程序包已经在base源中提供;

  • centos 7
    主配置文件:/etc/keepalived/keepalived.conf
    Unit file:/usr/lib/systemd/system/keepalived.service
    配置文件:/etc/sysconfig/keepalived

配置文件内容块:

GLOBAL CONFIGURATION 
#全局配置段,对所有vvrp实例虚拟服务器都是生效;
global_defs {
        ...
}

VRRPD CONFIGURATION  #虚拟路由器同步组配置段
      vrrp_sync_group VG_1 {
       ...
}

VRRP instance(s)  #虚拟路由器实例配置段
     vrrp_instance INST_NAME {
         ...
}

LVS CONFIGURATION  #集群配置段
        virtual_server_group <STRING> {  #虚拟服务器组配置段
         ...
}

Virtual server(s)  #虚拟服务器配置段
       virtual_server IP port |
       virtual_server fwmark int { #十进制的整数,(实际最终用的是十六进制数)
         protocol TCP  #注意:keepalived只支持tcp;
        ...
real_server <IPADDR> <PORT>{  #真实后端服务器配置段
       ...
                                }
                            }
全局配置段示例
global_defs {
    notification_email {    #用于指定报警邮件发往的邮箱地址
        root@localhost
    }
    notification_email_from keepalived@localhost    #用于指定报警邮件的发件人
    smtp_server 127.0.0.1    #用于指定邮件服务器的地址
    smtp_connect_timeout 30    #用于指定邮件服务器的连接超时时长
    router_id node1    #路由器的标识
    vrrp_mcast_group4 224.0.100.19    #用于设置vrrp的广播地址,在同一个HA cluster中的机器,要确保其广播地址一致才能接受到相应的vrrp报文
    vrrp_strict    #执行严格的vrrp协议检查,某些情况下会禁止到vip的访问。
}

Static routes/address/rules:用于配置keepalived中不会被VRRP移除的静态地址、路由或者规则,一般不会使用。

VRRP相关配置段示例
vrrp_instance <STRING> {
    state MASTER|BACKUP    #用于指定此虚拟路由器在vrrp组的角色状态
    interface eno16777736    #用于绑定当前虚拟路由器所使用的物理接口
    virtual_router_id 14    #用于指定当前虚拟路由器在vrrp组的唯一标识id,范围为0-255
    priority 100    #用于设置当前虚拟路由器在vrrp组里面的优先级,范围为1-254;
    advert_int 1    #用于设置虚拟路由器发送vrrp通告的时间间隔
    nopreempt|preempt    #定义工作模式为非抢占或抢占模式;
    preempt_delay 300    #定义在抢占式模式下,节点上线后触发新选举操作的延迟时长;
    authentication {    #用于设置vrrp组协商的方式及密码
        auth_type PASS    #定义认证类型为简单密码认证
        auth_pass 571f97b2    #定义密码串,最长不超过8个字符
    }
    virtual_ipaddress {    #用于指定需要在绑定的物理接口上添加的虚拟ip地址
        #<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
        172.18.11.66/16 dev eno16777736
    }
    track_interface {    #配置需要监控的网络接口,一旦接口出现故障,此虚拟路由器转为FAULT状态
      eth0
      eth1
      ...
     }
    track_script {    #用于调用在vrrp_script中定义的脚本,然后根据脚本的来进行监控调整
       <SCRIPT_NAME>
       <SCRIPT_NAME> weight <-254..254>
    }

    notify_master <STRING>|<QUOTED-STRING>    #当前节点成为主节点时触发的通知脚本;
    notify_backup <STRING>|<QUOTED-STRING>    #当前节点转为备节点时触发的通知脚本;
    notify_fault <STRING>|<QUOTED-STRING>    #当前节点转为“失败”状态时触发的通知脚本;
    notify_stop <STRING>|<QUOTED-STRING>     #当前节点停止时所触发的通知脚本
}

VRRP script(s):用于定义周期性执行的脚本,可定义调用用于检查相应的服务或Ip的状态的脚本。

vrrp_script <SCRIPT_NAME> {    #定义周期执行的脚本,此脚本的退出码决定了当前监控的vrrp组的运行状态
    script <STRING>|<QUOTED-STRING>    #定义执行脚本的存放路径
    interval INT     #定义调用执行脚本的周期,默认为1s。
    timeout <INTEGER>   # 脚本执行超时时间,脚本执行超时后,则被认为失败
    rise <INTEGER>              # 定义脚本检查成功多少次,才认可当前的状态为正常
    fall <INTEGER>              #定义检查失败多少次,才认为当前状态为失败
}
LVS配置段示例

Virtual server(s):用于定义虚拟服务器的设置,虚拟服务器可以用Ip端口、fwmark或virtual server group来定义。

virtual_server IP port | virtual_server fwmark <int>  |virtual_server group string

{
    delay_loop <INT>    #=服务轮询的时间间隔;
    lb_algo rr|wrr|lc|wlc|lblc|sh|dh    #定义调度方法;
    lb_kind NAT|DR|TUN    #集群的类型;
    persistence_timeout <INT>    #持久连接时长;
    protocol TCP|UDP|SCTP    #服务协议;
    sorry_server <IPADDR> <PORT>    #备用服务器地址;
    real_server <IPADDR> <PORT>{
        weight <INT>    #设置real server的权重
        notify_up <STRING>|<QUOTED-STRING>    #当出现匹配字符串时,就认为服务是up的
        notify_down <STRING>|<QUOTED-STRING>    #当出现匹配字符串时,就认为服务是down的
        HTTP_GET|SSL_GET {    #对real server作应用层检测
            url {
                path <URL_PATH>    #定义要监控的URL;
                status_code <INT>    #判断上述检测机制为健康状态的响应码;
                digest <STRING>    #判断上述检测机制为健康状态的响应的内容的校验码;
            }
            nb_get_retry <INT>    #重试次数;
            delay_before_retry <INT>    #重试之前的延迟时长;
            connect_ip <IP ADDRESS>    #向当前RS的哪个IP地址发起健康状态检测请求
            connect_port <PORT>    #向当前RS的哪个PORT发起健康状态检测请求
            bindto <IP ADDRESS>    #发出健康状态检测请求时使用的源地址;
            bind_port <PORT>    #发出健康状态检测请求时使用的源端口;
            connect_timeout <INTEGER>    #连接请求的超时时长;
        }
        
         TCP_CHECK {
            connect_ip <IP ADDRESS>    #向当前RS的哪个IP地址发起健康状态检测请求
            connect_port <PORT>    #向当前RS的哪个PORT发起健康状态检测请求
            bindto <IP ADDRESS>    #发出健康状态检测请求时使用的源地址;
            bind_port <PORT>    #发出健康状态检测请求时使用的源端口;
            connect_timeout <INTEGER>    #连接请求的超时时长;
        }
    }
}
高可用的ipvs集群
! Configuration File for keepalived

global_defs {
    notification_email {
        root@localhost
    }
    notification_email_from keepalived@localhost
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id node1
    vrrp_mcast_group4 224.0.100.19
}

vrrp_instance VI_1 {
    state MASTER
    interface eno16777736
    virtual_router_id 14
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 571f97b2
    }
    virtual_ipaddress {
        10.1.0.93/16 dev eno16777736
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}

virtual_server 10.1.0.93 80 {
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP

    sorry_server 127.0.0.1 80

    real_server 10.1.0.69 80 {
        weight 1
        HTTP_GET {
        url {
            path /
            status_code 200
        }
        connect_timeout 1
        nb_get_retry 3
        delay_before_retry 1
        }
    }
    real_server 10.1.0.71 80 {
        weight 1
        HTTP_GET {
        url {
            path /
            status_code 200
        }
        TCP_CHECK {
            nb_get_retry 3
            delay_before_retry 2
            connect_timeout 3
        }
    }
}
双主模型

主机配置:

global_defs {
    notification_email {
        root@localhost
    }
    notification_email_from keepalived@localhost
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id node1
    vrrp_mcast_group4 224.0.100.19
}

vrrp_instance VI_1 {
    state MASTER
    interface eno16777736
    virtual_router_id 14
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 571f97b2
    }
    virtual_ipaddress {
        172.18.11.66/16 dev eno16777736
    }
}

vrrp_instance VI_2 {
    state BACKUP
    interface eno16777736
    virtual_router_id 15
    priority 98
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 578f07b2
    }
    virtual_ipaddress {
        172.18.11.66/16 dev eno16777736
    }
}

备机配置:

global_defs {
    notification_email {
        root@localhost
    }
    notification_email_from keepalived@localhost
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id node2
    vrrp_mcast_group4 224.0.100.19
}

vrrp_instance VI_1 {
    state BACKUP
    interface eno16777736
    virtual_router_id 16
    priority 98
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 571f97b2
    }
    virtual_ipaddress {
        172.18.11.66/16 dev eno16777736
    }
}

vrrp_instance VI_2 {
    state MASTER
    interface eno16777736
    virtual_router_id 17
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 578f07b2
    }
    virtual_ipaddress {
        172.18.11.66/16 dev eno16777736
    }
}
通告脚本

可定义短信网关、微信网关、邮件服务器等方式发送;
此处,仅以本地邮件服务编写脚本;

[root@node1 ~]# vim notify.sh
#!/bin/bash
#
contact='root@localhost'
 
notify(){
    mailsuject="$(hostname) to be $1:vip floating"
    mailbody="$(date +'%F %T'):vrrp transition,$(hostname) change to be $1"
    echo $mailbody |mail -s "$mailsubject" $contact
}
 
case $1 in
master)
    notify master
    ;;
backup)
    notify bakcup
    ;;
fault)
    notify fault
    ;;
*)
    echo "Usage :$(basename $0) {master|backup|fault}"
    ;;
esac
[root@node1 ~]# chmod +x notify.sh 
[root@node1 ~]# ./notify.sh master
[root@node1 ~]# mail
显示:
Heirloom Mail version 12.5 7/5/10.  Type ? for help.
"/var/spool/mail/root": 1 message 1 new
>N  1 root                  Tue May 10 05:55  18/682   ""
& 1 输入1查看邮件1
部分内容:
2016-05-10 05:55:33:vrrp transition,localhost.localdomain change to be master
exit 退出邮件

把通告脚本复制给另一调度器上

[root@node1 ~]# scp notify.sh root@172.18.11.121:/etc/keepalived

在两个调度器上配置通告脚本

[root@node2 ~]# vim /etc/keepalived/keepalived.conf
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"

把两个调度器停止keepalived服务器

[root@node1 ~]# systemctl stop keepalived.service
[root@node2 ~]# systemctl stop keepalived.service
[root@node1 ~]# mail
[root@node2 ~]# mail
删除已有邮件,为后续清空环境;
d 1
d 2

再先后启动两个调度器keepalived服务器
先启动优先级低的备用调度器:

[root@node2 ~]# systemctl start keepalived.service
[root@node2 ~]# mail
显示:刚启动发一个邮件为backup的,因为只有一个调度器,过一会又收到一个邮件成为master;

再启动优先级高的调度器:

[root@node1 ~]# mail
则查看,显示也收到2条邮件,均为master信息;

通告脚本示例:

#!/bin/bash
#
contact='root@localhost'
                 
notify(){
    mailsuject="$(hostname) to be $1:vip floating"
    mailbody="$(date +'%F %T'):vrrp transition,$(hostname) change to be $1"
    echo $mailbody |mail -s "$mailsubject" $contact
}
                 
case $1 in
master)
    notify master
    ;;
backup)
    notify bakcup
    ;;
fault)
    notify fault
    ;;
*)
    echo "Usage :$(basename $0) {master|backup|fault}"
    ;;
esac

调用方法:

vrrp_instanace <STRING>{
  ...
  notify_master "/etc/keepalived/notify.sh master"
  notify_backup "/etc/keepalived/notify.sh backup"
  notify_fault "/etc/keepalived/notify.sh fault"
}

注意:脚本路径要使用双引号;

示例:keepalived的主从架构

搭建RS1和RS2
首先安装nginx程序:

[root@RS1 ~]# yum install -y epel-release
[root@RS1 ~]# yum install -y nginx

然后编辑/etc/hosts文件:

[root@RS1 ~]# vim /etc/hosts
192.168.0.81 DR1.ilinux.io DR1
192.168.0.87 DR2.ilinux.io DR2
192.168.0.83 RS1.ilinux.io RS1
192.168.0.84 RS2.ilinux.io RS2

随后修改/usr/share/nginx/html/index.html 内容为如下:

[root@RS1 ~]# vim /usr/share/nginx/html/index.html
<h1>This is RS1 192.168.0.83</h1>

启动nginx:

[root@RS1 ~]# systemctl start nginx

关闭firewalld和修改selinux的状态为permissive:

[root@RS1 ~]# systemctl stop firewalld
[root@RS1 ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@RS1 ~]# setenforce 0

接着在RS1上配置lvs-dr的配置,首先创建rs脚本:

[root@RS1 ~]# vim RS.sh
#/bin/bash
vip=192.168.0.99
mask='255.255.255.255'

case $1 in
start)
        echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
        echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
        echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
        echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

        ifconfig lo:0 $vip netmask $mask broadcast $vip up
        route add -host $vip dev lo:0
        ;;
stop)
        ifconfig lo:0 down
        echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
        echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
        echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
        echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
        ;;

*)
        echo "Usage $(basename $0) start|stop "
        exit 1
        ;;
esac

随后执行RS脚本:

[root@RS1 ~]# bash -x RS.sh start
+ vip=192.168.0.99
+ mask=255.255.255.255
+ case $1 in
+ echo 1
+ echo 1
+ echo 2
+ echo 2
+ ifconfig lo:0 192.168.0.99 netmask 255.255.255.255 broadcast 192.168.0.99 up
+ route add -host 192.168.0.99 dev lo:0

重复以上步骤并结合相应的信息搭建RS2。

搭建DR1
首先yum安装keepalived和ipvsadm程序包:

[root@DR1 ~]# yum install -y ipvsadm keepalived

然后编辑/etc/hosts文件:

[root@DR1 ~]# vim /etc/hosts
192.168.0.81 DR1.ilinux.io DR1
192.168.0.87 DR2.ilinux.io DR2
192.168.0.83 RS1.ilinux.io RS1
192.168.0.84 RS2.ilinux.io RS2

随后编辑/etc/keepalived/keepalived.conf文件:

global_defs {
   notification_email {
        root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id DR1 
   vrrp_mcast_group4 224.0.0.0.20
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state MASTER
    interface eno16777736
    virtual_router_id 1
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ^&IUYH*&
    }
    virtual_ipaddress { 
        192.168.0.99/24 dev eno16777736 label eno16777736:0
    }
}

virtual_server 192.168.0.99 80 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    protocol TCP
    
    real_server 192.168.0.83 80 {
        weight 1 
        HTTP_GET {
            url {
              path /index.html
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }   
        real_server 192.168.0.84 80 {
                weight 1 
                HTTP_GET {
                        url {
                                path /index.html
                                status_code 200
                        }
                }
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
        }
}

启动keepalived,查看ipvsadm和接口的状态:

[root@DR1 ~]# systemctl start keepalived
[root@DR1 ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.0.99:http rr
  -> 192.168.0.83:http            Route   1      1          4         
  -> 192.168.0.84:http            Route   1      1          80        
[root@DR1 ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.81  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::20c:29ff:fe21:59b9  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:21:59:b9  txqueuelen 1000  (Ethernet)
        RX packets 62277  bytes 72099132 (68.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 21742  bytes 2744670 (2.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eno16777736:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.99  netmask 255.255.255.0  broadcast 0.0.0.0
        ether 00:0c:29:21:59:b9  txqueuelen 1000  (Ethernet)

关闭firewalld和修改selinux的状态为permissive:

[root@DR1 ~]# systemctl stop firewalld
[root@DR1 ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@DR1 ~]# setenforce 0

搭建DR2
首先yum安装keepalived和ipvsadm程序包:

[root@DR2 ~]# yum install -y ipvsadm keepalived

然后编辑/etc/hosts文件:

[root@DR2 ~]# vim /etc/hosts
192.168.0.81 DR1.ilinux.io DR1
192.168.0.87 DR2.ilinux.io DR2
192.168.0.83 RS1.ilinux.io RS1
192.168.0.84 RS2.ilinux.io RS2

随后编辑/etc/keepalived/keepalived.conf文件:

global_defs {
   notification_email {
        root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id DR2
   vrrp_mcast_group4 224.0.0.0.20
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 1
    priority 98
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ^&IUYH*&
    }
    virtual_ipaddress {
        192.168.0.99/24 dev ens33 label ens33:0
    }
}

virtual_server 192.168.0.99 80 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    protocol TCP

    real_server 192.168.0.83 80 {
        weight 1
        HTTP_GET {
            url {
              path /index.html
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
        real_server 192.168.0.84 80 {
                weight 1
                HTTP_GET {
                        url {
                                path /index.html
                                status_code 200
                        }
                }
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
        }
}

最后启动keepalived并查看ipvsadm的状态:

[root@DR2 ~]# systemctl start keepalived
[root@DR2 ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.0.99:80 rr
  -> 192.168.0.83:80              Route   1      0          0         
  -> 192.168.0.84:80              Route   1      0          0         
[root@DR2 ~]# ifconfig    #因为DR2的角色为BACKUP,因此不会创建Ip为192.168.0.99的子接口
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.87  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::5e4b:719d:3781:43a0  prefixlen 64  scopeid 0x20<link>
        inet6 fe80::4c6e:8b7e:2dcd:665d  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:26:a3:20  txqueuelen 1000  (Ethernet)
        RX packets 34041  bytes 27376635 (26.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14131  bytes 2169836 (2.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1  (Local Loopback)
        RX packets 101  bytes 8902 (8.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 101  bytes 8902 (8.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

关闭firewalld和修改selinux的状态为permissive:

[root@DR2 ~]# systemctl stop firewalld
[root@DR2 ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@DR2 ~]# setenforce 0

测试访问
在客户端上测试访问vip所提供的服务:

[root@client ~]# for i in {1..10} ; do curl http://192.168.0.99; done
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>

此时DR1为主机,DR2为备机,两者都工作正常,因此请求连接是由DR1来处理。
那么我们模拟DR1宕机,把DR1的服务停用后,再来观察DR2的状态和客户端的访问情况。
DR2的keepalived状态:

[root@DR2 ~]# systemctl status keepalived
● keepalived.service - LVS and VRRP High Availability Monitor
   Loaded: loaded (/usr/lib/systemd/system/keepalived.service; disabled; vendor preset: disabled)
   Active: active (running) since Tue 2018-05-29 14:34:08 CST; 1h 29min ago
  Process: 11808 ExecStart=/usr/sbin/keepalived $KEEPALIVED_OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 11809 (keepalived)
   CGroup: /system.slice/keepalived.service
           ├─11809 /usr/sbin/keepalived -D
           ├─11810 /usr/sbin/keepalived -D
           └─11811 /usr/sbin/keepalived -D

May 29 16:03:06 DR2 Keepalived_vrrp[11811]: VRRP_Instance(VI_1) removing protocol VIPs.
May 29 16:03:47 DR2 Keepalived_vrrp[11811]: VRRP_Instance(VI_1) Transition to MASTER STATE
May 29 16:03:48 DR2 Keepalived_vrrp[11811]: VRRP_Instance(VI_1) Entering MASTER STATE
May 29 16:03:48 DR2 Keepalived_vrrp[11811]: VRRP_Instance(VI_1) setting protocol VIPs.
May 29 16:03:48 DR2 Keepalived_vrrp[11811]: Sending gratuitous ARP on ens33 for 192.168.0.99
May 29 16:03:48 DR2 Keepalived_vrrp[11811]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on ens33 for 192.168.0.99
May 29 16:03:48 DR2 Keepalived_vrrp[11811]: Sending gratuitous ARP on ens33 for 192.168.0.99
May 29 16:03:48 DR2 Keepalived_vrrp[11811]: Sending gratuitous ARP on ens33 for 192.168.0.99
May 29 16:03:48 DR2 Keepalived_vrrp[11811]: Sending gratuitous ARP on ens33 for 192.168.0.99
May 29 16:03:48 DR2 Keepalived_vrrp[11811]: Sending gratuitous ARP on ens33 for 192.168.0.99

DR2检测到DR1的宕机,主动变成了MASTER状态。
在客户端的访问情况:

[root@client ~]# for i in {1..10} ; do curl http://192.168.0.99; done
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>

此时DR1模拟为宕机状态,DR2为MASTER,客户端的访问不受影响。

示例:Keepalived的主主架构

此处以上面主从架构的拓扑为例,将主从架构更改为主主架构,首先我们需更改DR1和DR2的keepalived的配置,然后要在RS1和RS2上添加lvs-dr中与192.168.0.98虚拟IP相关的配置。

DR模式开启ip转发

[root@DR1 ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1

修改DR1
编辑/etc/keepalived/keepalived.conf文件

[root@DR1 ~]# vim /etc/keepalived/keepalived.conf
#添加如下配置
vrrp_instance VI_2 {
    state BACKUP
    interface eno16777736
    virtual_router_id 2
    priority 98
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass POM123(*
    }
    virtual_ipaddress {
        192.168.0.98/24 dev eno16777736 label eno16777736:1
    }
}
#添加虚拟服务器组backend
virtual_server_group backend {
        192.168.0.99 80
        192.168.0.98 80
}

#修改虚拟服务器调用虚拟服务器组
virtual_server group backend {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    protocol TCP

    real_server 192.168.0.83 80 {
        weight 1
        HTTP_GET {
            url {
              path /index.html
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
        real_server 192.168.0.84 80 {
                weight 1
                HTTP_GET {
                        url {
                                path /index.html
                                status_code 200
                        }
                }
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
        }
}

停用再启动keepalived:

[root@DR1 ~]# systemctl stop keepalived
[root@DR1 ~]# systemctl start keepalived

此时ipvsadm和接口的状态为:

[root@DR2 ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.0.98:80 rr
  -> 192.168.0.83:80              Route   1      0          0         
  -> 192.168.0.84:80              Route   1      0          0         
TCP  192.168.0.99:80 rr
  -> 192.168.0.83:80              Route   1      0          0         
  -> 192.168.0.84:80              Route   1      0          0           
[root@DR1 ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.81  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::20c:29ff:fe21:59b9  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:21:59:b9  txqueuelen 1000  (Ethernet)
        RX packets 63844  bytes 72282542 (68.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 23654  bytes 2934901 (2.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eno16777736:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.99  netmask 255.255.255.0  broadcast 0.0.0.0
        ether 00:0c:29:21:59:b9  txqueuelen 1000  (Ethernet)

修改DR2
编辑/etc/keepalived/keepalived.conf文件:

[root@DR2 ~]# vim /etc/keepalived/keepalived.conf
#添加如下配置
vrrp_instance VI_2 {
    state MASTER
    interface ens33
    virtual_router_id 2
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass POM123(*
    }   
    virtual_ipaddress {
        192.168.0.98/24 dev ens33 label ens33:1
    }           
}
#添加虚拟服务器组backend
virtual_server_group backend {
        192.168.0.99 80
        192.168.0.98 80
}
#修改虚拟服务器调用虚拟服务器组
virtual_server group backend {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    protocol TCP

    real_server 192.168.0.83 80 {
        weight 1
        HTTP_GET {
            url {
              path /index.html
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
        real_server 192.168.0.84 80 {
                weight 1
                HTTP_GET {
                        url {
                                path /index.html
                                status_code 200
                        }
                }
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
        }
}

停用再启动keepalived:

[root@DR2 ~]# systemctl stop keepalived
[root@DR2 ~]# systemctl start keepalived

此时ipvsadm和接口的状态为:

[root@DR2 ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.0.98:80 rr
  -> 192.168.0.83:80              Route   1      0          0         
  -> 192.168.0.84:80              Route   1      0          0         
TCP  192.168.0.99:80 rr
  -> 192.168.0.83:80              Route   1      0          0         
  -> 192.168.0.84:80              Route   1      0          0         
[root@DR2 ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.87  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::5e4b:719d:3781:43a0  prefixlen 64  scopeid 0x20<link>
        inet6 fe80::4c6e:8b7e:2dcd:665d  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:26:a3:20  txqueuelen 1000  (Ethernet)
        RX packets 39989  bytes 28047325 (26.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20816  bytes 2894556 (2.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.98  netmask 255.255.255.0  broadcast 0.0.0.0
        ether 00:0c:29:26:a3:20  txqueuelen 1000  (Ethernet)

配置RS1和RS2
复制编辑RS脚本:

[root@RS1 ~]# cp RS.sh RS_new.sh
#/bin/bash

#修改vip为192.168.0.98
vip=192.168.0.98  
mask='255.255.255.255'

case $1 in
start)
        echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
        echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
        echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
        echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
    
        ifconfig lo:1 $vip netmask $mask broadcast $vip up    #修改接口为lo:1
        route add -host $vip dev lo:1  #修改接口为lo:1
        ;;
stop)
        ifconfig lo:1 down    #修改接口为lo:1
        echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
        echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
        echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
        echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
        ;;

*)
        echo "Usage $(basename $0) start|stop "
        exit 1
        ;;
esac

运行脚本:

[root@RS1 ~]# bash -x RS_new.sh start
+ vip=192.168.0.98
+ mask=255.255.255.255
+ case $1 in
+ echo 1
+ echo 1
+ echo 2
+ echo 2
+ ifconfig lo:1 192.168.0.98 netmask 255.255.255.255 broadcast 192.168.0.98 up
+ route add -host 192.168.0.98 dev lo:1

在RS2 上也按照如上步骤执行操作即可

测试访问
此时在客户端通过192.168.0.99和192.168.0.98均能访问到后端RS所提供的web服务:

[root@client ~]# for i in {1..10} ; do curl http://192.168.0.98; done
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
[root@client ~]# for i in {1..10} ; do curl http://192.168.0.99; done
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>

在客户端上编辑/etc/hosts,添加域名解析到99和98:

[root@client ~]# vim /etc/hosts
192.168.0.99 www.ilinux.io
192.168.0.98 www.ilinux.io

此时通过域名解析能使得只要有99和98有一个正常工作,客户端均能正常访问服务。

[root@client ~]# for i in {1..10} ; do curl http://www.ilinux.io; done
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>
<h1>This is RS2 192.168.0.84</h1>
<h1>This is RS1 192.168.0.83</h1>

参考文档:https://www.jianshu.com/p/eefa8afabb09

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351