Haproxy/LVS负载均衡实现+keepalived实现高可用

haproxy+keepalived 集群高可用集群转发

环境介绍

#内核版本
Ubuntu 18.04.4 LTS \n \l
107-Ubuntu SMP Thu Jun 4 11:27:52 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
#节点介绍
192.168.1.113  hk-master1
192.168.1.114  hk-master2
192.168.1.111  hk-slave1
192.168.1.112  hk-slave2

内核调优

#调整Linux进程资源限制 vim /etc/security/limits.conf 
root soft core unlimited
root hard core unlimited
root soft nproc 600000
root hard nproc 600000
root soft nofile 648576
root hard nofile 600000
root soft memlock 32000
root hard memlock 32000
root soft msgqueue 8192000
root hard msgqueue 8192000

* soft core unlimited
* hard core unlimited
* soft nproc 600000
* hard nproc 600000
* soft nofile 600000
* hard nofile 600000
* soft memlock 32000
* hard memlock 32000
* soft msgqueue 8192000
* hard msgqueue 8192000
#验证(进程对资源的使用情况)
root@hk-master2:~# ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7376
max locked memory       (kbytes, -l) 32000
max memory size         (kbytes, -m) unlimited
open files                      (-n) 600000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 8192000
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 600000
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

#调整内核限制追加以下配置 /etc/sysctl.conf
 net.ipv4.conf.default.rp_filter = 1
 net.ipv4.ip_nonlocal_bind = 1 
 net.ipv4.ip_forward = 1 
 net.ipv4.conf.default.accept_source_route = 0
 kernel.sysrq = 0
 kernel.msgmnb = 65536
 kernel.msgmax = 65536
 kernel.shmmax = 68719476736
 kernel.shmall = 4294967296
 net.ipv4.tcp_mem = 786432 1048576 1572864
 net.ipv4.tcp_rmem = 4096 87380 4194304
 net.ipv4.tcp_wmem = 4096 16384 4194304
 net.ipv4.tcp_window_scaling = 1
 net.ipv4.tcp_sack = 1
 net.core.wmem_default = 8388608
 net.core.rmem_default = 8388608
 net.core.rmem_max = 16777216
 net.core.wmem_max = 16777216
 net.core.netdev_max_backlog = 262144
 net.core.somaxconn = 20480
 net.core.optmem_max = 81920
 net.ipv4.tcp_max_syn_backlog = 262144
 net.ipv4.tcp_syn_retries = 3
 net.ipv4.tcp_retries1 = 3
 net.ipv4.tcp_retries2 = 15
 net.ipv4.tcp_timestamps = 0 #代理不要开这个
 net.ipv4.tcp_fin_timeout = 1
 net.ipv4.tcp_max_tw_buckets = 20000
 net.ipv4.tcp_max_orphans = 3276800
 net.ipv4.tcp_synack_retries = 1
 net.ipv4.tcp_syncookies = 1
 net.ipv4.tcp_keepalive_time = 300
 net.ipv4.tcp_keepalive_intvl = 30
 net.ipv4.tcp_keepalive_probes = 3
 net.ipv4.ip_local_port_range = 10001 65000
 vm.overcommit_memory = 0
 vm.swappiness = 10
#验证 sysctl -p

haproxy安装和功能介绍

#安装
root@hk-master2:~# apt install -y haproxy
root@hk-master1:~# apt install -y haproxy

配置介绍

配置文件目录

主程序:/usr/sbin/haproxy
配置文件:/etc/haproxy/haproxy.cfg
Unit file:/usr/lib/systemd/system/haproxy.service

配置段:

#global 配置:
• chroot #锁定运行目录
• deamon #以守护进程运行
• #stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin #socket文件
• user, group, uid, gid #运行haproxy的用户身份
• nbproc #开启的haproxy进程数,与CPU保持一致
• nbthread #指定每个haproxy进程开启的线程数,默认为每个进程一个线程
• cpu-map 1 0 #绑定haproxy 进程至指定CPU
• maxconn #每个haproxy进程的最大并发连接数
• maxsslconn #SSL每个haproxy进程ssl最大连接数
• maxconnrate #每个进程每秒最大连接数
• spread-checks #后端server状态check随机提前或延迟百分比时间,建议2-5(20%-50%)之间
• pidfile #指定pid文件路径
• log 127.0.0.1 local3 info #定义全局的syslog服务器;最多可以定义两个
• defaults [<name>] #默认配置项,针对以下的frontend、backend和lsiten生效,可以多个name
• frontend <name> #前端servername,类似于Nginx的一个虚拟主机 server。 • backend <name> #后端服务器组,等于nginx的upstream
• listen <name> #将frontend和backend合并在一起配置
• 注:name字段只能使用”-”、”_”、”.”、和”:”,并且严格区分大小写,例如:Web和web是完全不
同的两组服务器。


#defaults 配置参数:
• option redispatch #当server Id对应的服务器挂掉后,强制定向到其他健康的服务器
• option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
• option http-keep-alive 60#开启会话保持
• option forwardfor #开启IP透传
• mode http #默认工作类型
• timeout connect 120s #转发客户端请求到后端server的最长连接时间(TCP之前) • timeout server 600s #转发客户端请求到后端服务端的超时超时时长(TCP之后)
• timeout client 600s #与客户端的最长空闲时间
• timeout http-keep-alive 120s #session 会话保持超时时间,范围内会转发到相同的后端服务器
• #timeout check 5s #对后端服务器的检测超时时间

#listen 配置参考:
listen WEB_PORT_80
    bind 192.168.7.102:80
    mode http
    option forwardfor
    server web1 192.168.7.101:8080 check inter 3000 fall 3 rise 5
    server web2 192.168.7.101:8080 check inter 3000 fall 3 rise 5

#后端服务器检测机制参数介绍:
check #对指定real进行健康状态检查,默认不开启
• addr IP #可指定的健康状态监测IP
• port num #指定的健康状态监测端口
• inter num #健康状态检查间隔时间,默认2000 ms
• fall num #后端服务器失效检查次数,默认为3 • rise num #后端服务器从下线恢复检查次数,默认为2 • weight #默认为1,最大值为256,0表示不参与负载均衡
• backup #将后端服务器标记为备份状态
• disabled #将后端服务器标记为不可用状态
• redirect prefix http://www.magedu.com/ #将请求临时重定向至其它URL,只适用于http模式
• maxconn <maxconn>:当前后端server的最大并发连接数
• backlog <backlog>:当server的连接数达到上限后的后援队列长度

调度算法

静态调度算法
balance: 指明对后端服务器的调度算法,配置在listen或backend
静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、链接数和相应速度等,且无法实时修改权重,只能重启后生效。
static-rr:基于权重的轮询调度,不支持权重的运行时调整及后端服务器慢启动,其后端主机数量没有限制 (出现请求按比例分发给后端)
first:根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置。  (配置的后端服务器连接数到了上线,才会分发到下台后端服务器)

动态调度算法
动态算法:基于后端服务器 状态进行调度适当调整,比如优先调度至当前负载较低的服务器,且权重可以在haproxy运行时动态调整无需重启。
roundrobin:基于权重的轮询动态调度算法,支持权重的运行时调整,不等于lvs 的rr,支持慢启动即新加的服务器会逐渐增加转发数,每个后端backend中最多支持4095个server,此为默认调度算法,server 权重设置 weight
leastconn: 加权的最少连接的动态,支持权重的运行时调整和慢启动,即当前后端服务器连接最少的优先调度,比较适合长连接的场景使用,比如MySQL等场景。
source调度算法
source:源地址hash,基于用户源地址hash并将请求转发到后端服务器,默认为静态即取模方式,但是可以通过hash-type支持的选项更改,后续同一个源地址请求将被转发至同一个后端web服务器,比较适用于session保持/缓存业务等场景。

• map-based:取模法,基于服务器权重的hash数组取模,该hash是静态的即不支持在线调整权重,不支持慢启动,其对后端服务器调度均衡,缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因权重发生变化而导致调度结果整体改变hash(o)mod n 。

•consistent:一致性哈希,该hash是动态的,支持在线调整权重,支持慢启动,优点在于当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动。

#配置案例:
listen web_prot_http_nodes
    bind 192.168.7.101:80
    mode http
    balance source
    hash-type consistent
    log global
    option forwardfor
    server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
    server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
uri调度算法
uri:基于对用户请求的uri做hash并将请求转发到后端指定服务器
• map-based:取模法
• consistent:一致性哈希

listen web_prot_http_nodes
    bind 192.168.7.101:80
    mode http #不支持tcp,会切换到tcp的roundrobin负载模式
    balance uri
    hash-type consistent
    log global
    option forwardfor
    server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
    server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5

url_param 调度算法
#url_param: 对用户请求的url中的<params>部分中的参数name作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个Backend Server
#url 传递的查询字符串进行bash
listen web_prot_http_nodes
    bind 192.168.7.101:80
    mode http #不支持tcp,会切换到tcp的roundrobin负载模式
    balance url_param name #基于参数name做hash
    hash-type consistent
    log global
    option forwardfor
    server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
    server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
hdr调度算法
#针对每个用户的http请求头中的指定信息做hash,此处由<name>指定的http首部将会被取出并做hash计算,然后由服务器总权重相除以后派发至某挑出的服务器,假如无有效的值,则会被轮询调度
hdr( Cookie、 User-Agent、host )

listen web_prot_http_nodes
    bind 192.168.7.101:80
    mode http
    balance hdr(User-Agent)
    hash-type consistent #一致性hash 
    log global
    option forwardfor
    server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
    server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
rdp-cookie调度算法
rdp-cookie对远程桌面的负载,使用cookie保持会话

listen RDP
    bind 192.168.7.101:3389
    balance rdp-cookie
    mode tcp
    server rdp0 172.18.139.20:3389 check fall 3 rise 5 inter 2000 weight 1
    server rdp1 172.18.139.21:3389 check fall 3 rise 5 inter 2000 weight 1
    
    

配置状态页

stats enable #基于默认的参数启用stats page
stats hide-version # 隐藏版本
stats refresh <delay> # 设定自动刷新时间间隔
stats uri <prefix> #自定义stats page uri,默认值:/haproxy?stats 
stats realm <realm> #账户认证时的提示信息,示例:stats realm : HAProxy\ Statistics
stats auth <user>:<passwd> #认证时的账号和密码,可使用多次,默认:no authentication
stats admin { if | unless } <cond> #启用stats page中的管理功能


listen stats
    bind :9009
    stats enable
    #stats hide-version 
    stats uri /haproxy-status
    stats realm HAPorxy\ Stats\ Page
    stats auth haadmin:123456
    stats auth admin:123456
    stats refresh 30s
    stats admin if TRUE

自定义错误页面

errorfile 500 /usr/local/haproxy/html/500.html #自定义错误页面跳转
errorfile 502 /usr/local/haproxy/html/502.html
errorfile 503 /usr/local/haproxy/html/503.html

errorloc 503 http://192.168.7.103/error_page/503.html

压缩功能

compression algo #启用http协议中的压缩机制,常用算法有gzip deflate
compression type #要压缩的类型
• 示例:
    • compression algo gzip
    • compression type compression type text/plain text/html text/css text/xml text/javascript application/javascript

配置https

bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
    crt 后证书文件为PEM格式,且同时包含证书和所有私钥
    cat demo.crt demo.key > demo.pem 
把80端口的请求重向定443
    bind *:80
    redirect scheme https if !{ ssl_fc }
向后端传递用户请求的协议和端口(frontend或backend)
    http_request set-header X-Forwarded-Port %[dst_port]
    http_request add-header X-Forwared-Proto https if { ssl_fc }
#配置示例:
frontend https_frontend
  bind *:443 ssl crt /etc/ssl/certs/servername.pem
  mode http
  option httpclose
  option forwardfor
  reqadd X-Forwarded-Proto:\ https
  default_backend web_server

backend web_server
  mode http
  balance roundrobin
  cookie SERVERID insert indirect nocache
  server s1 192.168.250.47:80 check cookie s1
  server s2 192.168.250.49:80 check cookie s2
 注意:这里的pem 文件是下面两个文件合并而成:
  cat servername.crt servername.key |tee servername.pem
  
#第二种四层转发
frontend https_frontend
  bind *:443
  mode tcp
  default_backend web_server

backend web_server
  mode tcp
  balance roundrobin
  stick-table type ip size 200k expire 30m
  stick on src
  server s1 192.168.250.47:443
  server s2 192.168.250.49:443
  
  注意,这种模式下mode 必须是tcp 模式
         

四层负载IP透传

#在四层负载设备中,把client发送的报文目标地址(原来是负载均衡设备的IP地址),根据均衡设备设置的选择web服务器的规则选择对应的web服务器IP地址,这样client就可以直接跟此服务器建立TCP连接并发送数据。

listen web_prot_http_nodes
    bind 192.168.7.102:80
    mode tcp
    server 192.168.7.102 blogs.studylinux.net:80 send-proxy check inter 3000 fall 3 rise 5 #send-proxy

Nginx配置:
    listen 80 proxy_protocol; 
        '"tcp_ip":"$proxy_protocol_addr",' #TCP获取客户端真实IP日志格式


七层负载IP透传

#七层负载均衡服务器起了一个代理服务器的作用,服务器建立一次TCP连接要三次握手,而client要访问webserver要先与七层负载设备进行三次握手后建立TCP连接,把要访问的报文信息发送给七层负载均衡;然后七层负载均衡再根据设置的均衡规则选择特定的webserver,然后通过三次握手与此台webserver建立TCP连接,然后webserver把需要的数据发送给七层负载均衡设备,负载均衡设备再把数据发送给client;所以,七层负载均衡设备起到了代理服务器的作用。

listen web_prot_http_nodes
    bind 192.168.7.102:80
    mode http
    #option forwardfor
    server 192.168.7.102 blogs.studylinux.net:80 check inter 3000 fall 3 rise 5

heepalived 安装和功能介绍

root@hk-master2:~# apt install -y haproxy
root@hk-master1:~# apt install -y haproxy

功能

基于vrrp协议完成地址流动
为vip地址所在的节点生成ipvs规则(在配置文件中预先定义) 
为ipvs集群的各RS做健康状态检测
基于脚本调用接口通过执行脚本完成脚本中定义的功能,进而影响集群事务,以此支持nginx、haproxy等服务

环境要求

#个节点时间同步
#关闭selinux
#添加防火墙策略/关闭防火墙
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 \
  --in-interface ens0 --destination 192.168.1.114 --protocol vrrp -j ACCEPT
success
firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 \
  --out-interface ens0 --destination 192.168.1.114 --protocol vrrp -j ACCEPT
success
firewall-cmd --reload
success

配置介绍

主配置文件:/etc/keepalived/keepalived.conf
主程序文件:/usr/sbin/keepalived
Unit File: 
    • /usr/lib/systemd/system/keepalived.service (CentOS) 
    • /lib/systemd/system/keepalived.service (Ubuntu)

#配置文件组成部分
TOP HIERACHY
    GLOBAL CONFIGURATION
        Global definitions
        
    VRRP CONFIGURATION
        VRRP instance(s):即一个vrrp虚拟路由器
        
    LVS CONFIGURATION
        Virtual server group(s)
        Virtual server(s):ipvs集群的vs和rs
        
#配置参数:
state MASTER|BACKUP:当前节点在此虚拟路由器上的初始状态,状态为MASTER或者BACKUP
interface IFACE_NAME:绑定为当前虚拟路由器使用的物理接口ens32,ens0,bond0,br0
virtual_router_id VRID:当前虚拟路由器惟一标识,范围是0-255
priority 100:当前物理节点在此虚拟路由器中的优先级;范围1-254
advert_int 1:vrrp通告的时间间隔,默认1s
authentication { #认证机制
auth_type AH|PASS
auth_pass <PASSWORD> 仅前8位有效
}
virtual_ipaddress { #虚拟IP
    <IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
    192.168.200.17/24 dev ens1
    192.168.200.18/24 dev ens2 label ens2:1
}
track_interface { #配置监控网络接口,一旦出现故障,则转为FAULT状态实现地址转移
    ens0
    ens1
    … 
    }

组播配置

#master :
global_defs { 
    notification_email { 
        root@localhost #keepalived 发生故障切换时邮件发送的对象,可以按行区分写多个
}
    notification_email_from keepalived@localhost
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id ha1.example.com
    vrrp_skip_check_adv_addr #所有报文都检查比较消耗性能,此配置为如果收到的报文和上一个报文是同一个路由器则跳过检查报文中的源地址
    vrrp_strict #严格遵守VRRP协议,不允许状况:1,没有VIP地址,2.单播邻居,3.在VRRP版本2中有IPv6地 址. • vrrp_garp_interval 0 #ARP报文发送延迟
    vrrp_gna_interval 0 #消息发送延迟
    vrrp_mcast_group4 224.0.0.18 #默认组播IP地址,224.0.0.0到239.255.255.255
    #vrrp_iptables
    }
    vrrp_instance VI_1 {
        state MASTER
        interface ens0
        virtual_router_id 80
        priority 100
        advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111qwer
    } 
    virtual_ipaddress {
        192.168.7.248 dev ens0 label ens0:0
    } 
}
#backup :
global_defs {
    notification_email {
        root@localhost
} 
    notification_email_from keepalived@localhost
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id ha2.example.com
    vrrp_skip_check_adv_addr #
    vrrp_strict #严格遵守VRRP协议。
    vrrp_garp_interval 0 #ARP报文发送延迟
    vrrp_gna_interval 0 #消息发送延迟
    vrrp_mcast_group4 224.0.0.18 #组播IP地址,224.0.0.0到239.255.255.255
    #vrrp_iptables
}
vrrp_instance VI_1 {
    state BACKUP
    interface ens0
    virtual_router_id 80
    priority 90
    advert_int 1
    authentication {
    auth_type PASS
    auth_pass 1111qwer
} 
virtual_ipaddress {
    192.168.7.248 dev ens0 label ens0:0
    } 
}

非抢占

#设置成双备模式 关闭vip抢占 + nopreempt
#hk-master1
vrrp_instance VI_1 {
    state BACKUP
    interface ens0
    virtual_router_id 80
    priority 100
    advert_int 1 
    nopreempt
#hk-master2
vrrp_instance VI_1 {
    state BACKUP
    interface ens0
    virtual_router_id 80
    priority 90
    advert_int 1 
    nopreempt

单波配置

unicast_src_ip 本机源IP
    unicast_peer {
    目标主机IP
}

通知配置

vim /etc/mail.rc
set from=12161xxqq.com
set smtp=smtp.qq.com
set smtp-auth-user=12161xxqq.com
set smtp-auth-password=xxxxxxx
set smtp-auth=login
set ssl-verify=ignore

nopreempt:定义工作模式为非抢占模式
preempt_delay 300:抢占式模式,节点上线后触发新选举操作的延迟时长,
默认模式
定义通知脚本:
    notify_master <STRING>|<QUOTED-STRING>:
        当前节点成为主节点时触发的脚本
    notify_backup <STRING>|<QUOTED-STRING>:
        当前节点转为备节点时触发的脚本
    notify_fault <STRING>|<QUOTED-STRING>:
        当前节点转为“失败”状态时触发的脚本
    notify <STRING>|<QUOTED-STRING>:
        通用格式的通知触发机制,一个脚本可完成以上三种状态的转换时的通知

[图片上传失败...(image-79b2d4-1593177183263)]

应用层监控

HTTP_GET|SSL_GET:应用层检测
HTTP_GET|SSL_GET {
    url {
        path <URL_PATH>:定义要监控的URL
        status_code <INT>:判断上述检测机制为健康状态的响应码
    }
connect_timeout <INTEGER>:连接请求的超时时长
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>:发出健康状态检测请求时使用的源端口
}
#real_server http监测
real_server 192.168.7.103 80 {
    weight 1
    HTTP_GET {
    url {
        path /index.html
        status_code 200
        } 
    }
    connect_timeout 5
    nb_get_retry 3
    delay_before_retry 3 
}3

tcp监控

传输层检测 TCP_CHECK
    TCP_CHECK {
        connect_ip <IP ADDRESS>:向当前RS的哪个IP地址发起健康状态检测请求
        connect_port <PORT>:向当前RS的哪个PORT发起健康状态检测请求
        bindto <IP ADDRESS>:发出健康状态检测请求时使用的源地址
        bind_port <PORT>:发出健康状态检测请求时使用的源端口
        connect_timeout <INTEGER>:连接请求的超时时长
    }

脚本监控

分两步:(1) 先定义一个脚本;(2) 调用此脚本
vrrp_script <SCRIPT_NAME> {
    script <STRING>|<QUOTED-STRING>
    interval <INTEGER> # 间隔时间,单位为秒,默认1秒
    timeout <INTEGER> # 超时时间
    weight <INTEGER:-254..254> # 权重,监测失败后会执行权重+操作
    fall <INTEGER> #脚本几次失败转换为失败
    rise <INTEGER> # 脚本连续监测成果后,把服务器从失败标记为成功的次数
    user USERNAME [GROUPNAME] # 执行监测的用户或组
    init_fail # 设置默认标记为失败状态,监测成功之后再转换为成功状态
}

vrrp_instance VI_1 {
…
track_script {
    SCRIPT_NAME_1
    SCRIPT_NAME_2
    }
}

配置案例:

#查找配置案例
root@hk-master2:~# find /usr/share/doc/keepalived/ -name keepalived.*
/usr/share/doc/keepalived/samples/keepalived.conf.vrrp.routes
/usr/share/doc/keepalived/samples/keepalived.conf.fwmark
/usr/share/doc/keepalived/samples/keepalived.conf.vrrp.sync
/usr/share/doc/keepalived/samples/keepalived.conf.SMTP_CHECK
/usr/share/doc/keepalived/samples/keepalived.conf.HTTP_GET.port
/usr/share/doc/keepalived/samples/keepalived.conf.vrrp.scripts
/usr/share/doc/keepalived/samples/keepalived.conf.SSL_GET
/usr/share/doc/keepalived/samples/keepalived.conf.virtual_server_group
/usr/share/doc/keepalived/samples/keepalived.conf.virtualhost
/usr/share/doc/keepalived/samples/keepalived.conf.vrrp.static_ipaddress
/usr/share/doc/keepalived/samples/keepalived.conf.misc_check
/usr/share/doc/keepalived/samples/keepalived.conf.vrrp.localcheck
/usr/share/doc/keepalived/samples/keepalived.conf.sample
/usr/share/doc/keepalived/samples/keepalived.conf.misc_check_arg
/usr/share/doc/keepalived/samples/keepalived.conf.IPv6
/usr/share/doc/keepalived/samples/keepalived.conf.quorum
/usr/share/doc/keepalived/samples/keepalived.conf.inhibit
/usr/share/doc/keepalived/samples/keepalived.conf.track_interface
/usr/share/doc/keepalived/samples/keepalived.conf.vrrp.lvs_syncd
/usr/share/doc/keepalived/samples/keepalived.conf.vrrp
/usr/share/doc/keepalived/samples/keepalived.conf.status_code
/usr/share/doc/keepalived/samples/keepalived.conf.vrrp.rules
/usr/share/doc/keepalived/keepalived.conf.SYNOPSIS.gz

#
root@hk-master2:~# vim /etc/keepalived/keepalived.conf #hk-master1与这个配置就routid和优先级不一样其他的都一样

! Configuration File for keepalived

global_defs {
   #notification_email {
    # acassen
   #}
 #  notification_email_from Alexandre.Cassen@firewall.loc
  # smtp_server 192.168.200.1
  # smtp_connect_timeout 30
   router_id LVS_DEVEL_114
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    garp_master_delay 10
    #smtp_alert
    virtual_router_id 51
    priority 99
    nopreempt
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.200 label ens33:1
    }
}

haproxy动态上线下线后端服务器

#以上基于hk-master1实现了一个vip-192.168.1.200。 这里基于这个vip做负载均衡配置
#hk-master1:
global
        log /dev/log    local0
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        nbproc 2
        maxconn 65536
        stats timeout 30s
        cpu-map 1 0
        cpu-map 2 1
        stats socket /run/haproxy/admin.sock1 mode 660 level admin process 1
        stats socket /run/haproxy/admin.sock2 mode 660 level admin process 2
        nbthread 12
        user haproxy
        group haproxy
        daemon
        #ulimit -n 65536

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000
        errorfile 400 /etc/haproxy/errors/400.http
        errorfile 403 /etc/haproxy/errors/403.http
        errorfile 408 /etc/haproxy/errors/408.http
        errorfile 500 /etc/haproxy/errors/500.http
        errorfile 502 /etc/haproxy/errors/502.http
        errorfile 503 /etc/haproxy/errors/503.http
        errorfile 504 /etc/haproxy/errors/504.http
listen stats
  mode http
  bind 192.168.1.113:9999
  stats enable
  log global
  stats uri /haproxy-status
  stats auth haadmin:123123

listen nginx
  bind 192.168.1.200:80
  mode http
  server 192.168.1.111 192.168.1.111:80 check inter 2s fall 3 rise 5
  server 192.168.1.112 192.168.1.112:80 check inter 2s fall 3 rise 5   
  
#升级前下线后端服务器
root@hk-master1:~# cat updatecode.sh 
#!/bin/bash
cpus=`cat /proc/cpuinfo |grep processor |wc -l`

for ((i=1;i<=$cpus;i++));  
  do
     echo "disable server $1/$2" | socat stdio /run/haproxy/admin.sock$i;
  done  

#升级完毕上线后端服务器
root@hk-master1:~# cat percode.sh 
#!/bin/bash
cpus=`cat /proc/cpuinfo |grep processor |wc -l`

for ((i=1;i<=$cpus;i++));  
  do
     echo "enable server $1/$2" | socat stdio /run/haproxy/admin.sock$i;
  done  

LVS+keepalived 高可用集群

lvs 主要的工作是提供调度算法,把客户端请求按照需求调度在 real 服务器,keepalived 主要的工作是提供 lvs 控制器的一个冗余,并且对 real 服务器做健康检查,发现不健康的 real 服务器,就把它从 lvs 集群中剔除,real 服务器只负责提供服务。

keepalived底层有关于IPVS的功能模块,可以直接在其配置文件中实现LVS的配置,不需要通过ipvsadm命令再单独配置

LVS 负载策略介绍

#IP 负载均衡技术(VS/NAT,VS/TUN,VS/DR):
Virtual Server via Network Address Translation(VS/NAT)
通过网络地址转换,调度器重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器;真实服务器的响应报文通过调度器时,报文的源地址被重写,再返回给客户,完成整个负载调度过程。

Virtual Server via IP Tunneling(VS/TUN)
采用 NAT 技术时,由于请求和响应报文都必须经过调度器地址重写,当客户请求越来越多时,调度器的处理能力将成为瓶颈。为了解决这个问题,调度器把请求报 文通过 IP 隧道转发至真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。由于一般网络服务应答比请求报文大许多,采用 VS/TUN 技术后,集群系统的最大吞吐量可以提高 10 倍。

Virtual Server via Direct Routing(VS/DR)
VS/DR 通过改写请求报文的 MAC 地址,将请求发送到真实服务器,而真实服务器将响应直接返回给客户。同 VS/TUN 技术一样,VS/DR 技术可极大地 提高集群系统的伸缩性。这种方法没有 IP 隧道的开销,对集群中的真实服务器也没有必须支持 IP 隧道协议的要求,但是要求调度器与真实服务器都有一块网卡连 在同一物理网段上。


LVS 调度算法

1.轮询:Round Robin,简称rr,分发器按照循环的方式将请求平均的发送给后端的rs

2.加权轮询:Weight Round-Robin,简称wrr,增对轮询的优化,会给每台rs定义对应的权重值,权重值大的rs会比权重值小的rs接收到更多分发器转发的请求

3.最小连接:Least-Connection,简称lc,分发器向每台rs转发请求时,会记录rs的连接数,根据连接数判断所有rs的情况,将最新的请求转发给连接数最少的rs

4.加权最小连接:Weight Least-Connection,简称wlc,增对最小连接的优化,定义每台rs的权重值,分发器将新的请求转发给rs时,会根据权重值判断转发请求给每台rs的比例,分发器可以自动判断rs的情况,动态调整权重值

#以上为4中常用调度算法,除此之外还有基于局部性的最小连接、带复制的基于局部性最小连接、目标地址散列调度、源地址散列调度等

LVS NAT模式搭建

测试环境:准备3台机器,1台分发器(dir)和2台rs

dir内网:192.168.1.113 外网:192.168.111.200
rs1内网:192.168.1.111
rs2内网:192.168.1.112

apt install -y iptables #all node
systemctl enable iptables --now #all node
#设置rs1与rs2的网关为dir的内网ip:
root@hk-slave1:/opt# vim /etc/netplan/01-netcfg.yaml 
root@hk-slave1:/opt# netplan apply
root@hk-slave1:/opt# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 ens33
0.0.0.0         192.168.1.113   0.0.0.0         UG    0      0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 ens33
# dir 上创建vip 开启代理后端服务的lvs 模块
root@hk-master1:~# cat  /usr/local/sbin/lvs_nat.sh
#! /bin/bash
# dir上开启路由转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
# 关闭icmp的重定向
echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
echo 0 > /proc/sys/net/ipv4/conf/default/send_redirects
# 注意区分网卡名字,两个网卡分别为ens33(内网)和ens37(外网)
echo 0 > /proc/sys/net/ipv4/conf/ens33/send_redirects
#echo 0 > /proc/sys/net/ipv4/conf/ens37/send_redirects
# dir设置nat防火墙
iptables -t nat -F
iptables -t nat -X
iptables -t nat -A POSTROUTING -s 192.168.1.0/24  -j MASQUERADE
# 定义ipvsadm路径到变量
IPVSADM='/sbin/ipvsadm'
# 清空ipvsadm规则
$IPVSADM -C
# 配置lvs,-s 指定调度算法为轮询
$IPVSADM -A -t 192.168.1.200:80 -s rr
# -r指定rs1,-w表示模式为nat,-w指定权重值
$IPVSADM -a -t 192.168.1.200:80 -r 192.168.1.111:80 -m -w 1
# 指定rs2
$IPVSADM -a -t 192.168.1.200:80 -r 192.168.1.112:80 -m -w 1
root@hk-master1:~# bash /usr/local/sbin/lvs_nat.sh 
# 验证代理配置
root@hk-master1:~# 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.1.200:80 rr
  -> 192.168.1.111:80             Masq    1      0          0         
  -> 192.168.1.112:80             Masq    1      0          0   
  
 #dir 主机 curl 调用虚拟ip 192.168.1.200
 root@hk-master1:~# curl 192.168.1.200
192.168.1.112 nginx page
root@hk-master1:~# curl 192.168.1.200
192.168.1.111 nginx page
root@hk-master1:~# curl 192.168.1.200
192.168.1.112 nginx page
root@hk-master1:~# curl 192.168.1.200
192.168.1.111 nginx page
root@hk-master1:~# 

LVS DR 模式搭建

测试环境:准备3台机器,1台分发器(dir)和2台rs

dir内网:192.168.1.113
rs1内网:192.168.1.111
rs2内网:192.168.1.112
VIP:192.168.1.200

DR模式rs1,与rs2机器的网关不需要配置为dir的ip地址,同样使用iptables工具管理防火墙,也要下载ipvsadm

root@hk-master1:~#iptables -F 
root@hk-master1:~# ipvsadm -C
root@hk-master1:~# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

root@hk-master1:~# bash /usr/local/sbin/lvs_dr.sh 
SIOCADDRT: File exists

root@hk-master1:~# 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.1.200:80 rr
  -> 192.168.1.111:80             Route   1      0          0         
  -> 192.168.1.112:80             Route   1      0          0         

root@hk-master1:~# cat /usr/local/sbin/lvs_dr.sh 
#! /bin/bash
# 开启端口转发
echo 1 > /proc/sys/net/ipv4/ip_forward
ipv=/sbin/ipvsadm
vip=192.168.1.200
rs1=192.168.1.111
rs2=192.168.1.112
# 添加VIP
ifconfig ens33:2 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip dev ens33:2
# 清空ipvsadm规则
$ipv -C
# 定义lvs调度算法为轮询
$ipv -A -t $vip:80 -s rr
# 指定转发目标rs1,-g表示dr模式,-w定义权重值
$ipv -a -t $vip:80 -r $rs1:80 -g -w 1
# 指定转发目标rs2
$ipv -a -t $vip:80 -r $rs2:80 -g -w 1

# rs1和rs2 都执行:
root@hk-slave1:/opt# bash /usr/local/sbin/lvs_rs.sh 

root@hk-slave1:/opt# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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
    inet 192.168.1.200/32 brd 192.168.1.200 scope global lo:0
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/enser 00:0c:29:9f:37:c7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.111/24 brd 192.168.1.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe9f:37c7/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/enser 02:42:d9:b9:ab:13 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:d9ff:feb9:ab13/64 scope link 
       valid_lft forever preferred_lft forever

root@hk-slave1:/opt# cat /usr/local/sbin/lvs_rs.sh 
#!/bin/bash
netplan apply
vip=192.168.1.200
# 把vip绑定在lo上,是为了实现rs直接把结果返回给客户端
ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip lo:0
# 以下操作为更改arp内核参数,目的是为了让rs顺利发送mac地址给客户端
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


结合keepalive 实现高可用

以上面配置的LVS DR模式为例,使用keepalived+lvs的场景:

1.dir会将收到的请求分发给后端的rs,但是当某台rs宕机的时候,dir不会知道,还会继续分发请求到宕机的rs机器,为了避免该情况出现,可以使用keepalived的避免

#清空规则
root@hk-master1:~# iptables -F
root@hk-master1:~# ipvsadm -C
#编辑keepalive配置文件
root@hk-master1:~# 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.1.200:80 rr persistent 1
  -> 192.168.1.111:80             Route   100    0          0         
  -> 192.168.1.112:80             Route   100    0          0         
root@hk-master1:~# vim /etc/keepalived/keepalived.conf 
root@hk-master1:~# cat /etc/keepalived/keepalived.conf 
vrrp_instance VI_1 {
    state BACKUP
    #绑定vip的网卡
    interface ens33
    #路由id,需要与backup机器相同
    virtual_router_id 51
    #定义权重,备用服务器上要小于100
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass keepalived123
    }
    virtual_ipaddress {
        192.168.1.200
    }
}
virtual_server 192.168.1.200 80 {
    #每隔10秒查询realserver状态
    delay_loop 10
    #lvs 算法
    lb_algo rr
    #DR模式
    lb_kind DR
    #同一IP的连续1秒内被分配到同一台rs
    persistence_timeout 1
    #用TCP协议检查rs
    protocol TCP

    real_server 192.168.1.111 80 {
        #权重
        weight 100
        TCP_CHECK {
        #10秒无响应超时
        connect_timeout 10
        nb_get_retry 3
        delay_before_retry 3
        connect_port 80
        }
    }
    real_server 192.168.1.112 80 {
        weight 100
        TCP_CHECK {
        connect_timeout 10
        nb_get_retry 3
        delay_before_retry 3
        connect_port 80
        }
     }
}           

#验证配置
root@hk-master1:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/enser 00:0c:29:bb:35:0d brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.113/24 brd 192.168.1.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet 192.168.1.200/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:febb:350d/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/enser 02:42:c9:56:f7:39 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
root@hk-master1:~# 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.1.200:80 wlc persistent 1
  -> 192.168.1.111:80             Route   100    1          0   
  
  #浏览器测试
  #在rs当中一台服务停的时候会暂时出现访问不了的清空
curl: (7) Failed to connect to 192.168.1.200 port 80: Connection refused
root@hk-master2:~# curl 192.168.1.200
curl: (7) Failed to connect to 192.168.1.200 port 80: Connection refused
root@hk-master2:~# curl 192.168.1.200
192.168.1.112 nginx page
root@hk-master2:~# curl 192.168.1.200

2.完整的架构dir需要两台,实现高可用,当dir1宕机时,dir2会切换为dir1,接收请求并分发到后端的rs

#配置一台dir的从服务器
scp /etc/keepalived/keepalived.conf 192.168.1.114:/etc/keepalived/
root@hk-master2:~# cat /etc/keepalived/keepalived.conf 
vrrp_instance VI_1 {
    state BACKUP
    #绑定vip的网卡
    interface ens33
    #路由id,需要与backup机器相同
    virtual_router_id 51
    #定义权重,备用服务器上要小于100
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass keepalived123
    }
    virtual_ipaddress {
        192.168.1.200
    }
}
virtual_server 192.168.1.200 80 {
    #每隔10秒查询realserver状态
    delay_loop 10
    #lvs 算法
    lb_algo wlc
    #DR模式
    lb_kind DR
    #同一IP的连续1秒内被分配到同一台rs
    persistence_timeout 1
    #用TCP协议检查rs
    protocol TCP

    real_server 192.168.1.111 80 {
        #权重
        weight 100
        TCP_CHECK {
        #10秒无响应超时
        connect_timeout 10
        nb_get_retry 3
        delay_before_retry 3
        connect_port 80
        }
    }
    real_server 192.168.1.112 80 {
        weight 100
        TCP_CHECK {
        connect_timeout 10
        nb_get_retry 3
        delay_before_retry 3
        connect_port 80
        }
     }
}

#重启 rs 中的一台nginx 测试keepalived
root@hk-master1:~# tail -f /var/log/syslog
Jun 26 20:55:17 k8s-node3 Keepalived_healthcheckers[46661]: TCP connection to [192.168.1.111]:tcp:80 failed.
Jun 26 20:55:17 k8s-node3 Keepalived_healthcheckers[46661]: Check on service [192.168.1.111]:tcp:80 failed after 1 retry.
Jun 26 20:55:17 k8s-node3 Keepalived_healthcheckers[46661]: Removing service [192.168.1.111]:tcp:80 to VS [192.168.1.200]:tcp:80
Jun 26 20:56:45 k8s-node3 Keepalived_healthcheckers[46661]: TCP connection to [192.168.1.111]:tcp:80 success.
Jun 26 20:56:45 k8s-node3 Keepalived_healthcheckers[46661]: Adding service [192.168.1.111]:tcp:80 to VS [192.168.1.200]:tcp:80
root@hk-master2:~# tail -f /var/log/syslog
Jun 26 20:55:15 k8s-node4 Keepalived_healthcheckers[43729]: Check on service [192.168.1.111]:tcp:80 failed after 1 retry.
Jun 26 20:55:15 k8s-node4 Keepalived_healthcheckers[43729]: Removing service [192.168.1.111]:tcp:80 to VS [192.168.1.200]:tcp:80
Jun 26 20:56:43 k8s-node4 Keepalived_healthcheckers[43729]: TCP connection to [192.168.1.111]:tcp:80 success.
Jun 26 20:56:43 k8s-node4 Keepalived_healthcheckers[43729]: Adding service [192.168.1.111]:tcp:80 to VS [192.168.1.200]:tcp:80

#测试 vip 飘逸
root@hk-master1:~# systemctl stop keepalived.service 
root@hk-master2:~# tail -f /var/log/syslog
Jun 26 20:57:36 k8s-node4 Keepalived_vrrp[43730]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jun 26 20:57:37 k8s-node4 Keepalived_vrrp[43730]: VRRP_Instance(VI_1) Entering MASTER STATE
root@hk-master2:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/enser 00:0c:29:0f:45:99 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.114/24 brd 192.168.1.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet 192.168.1.200/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe0f:4599/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/enser 02:42:d1:34:f6:db brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

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

推荐阅读更多精彩内容