一、Keepalived 软件介绍:
Keeplived 软件起初就是专为 LVS 负载均衡软件设计的,用来管理并监控 LVS 集群系统中各个服务器节点的状态,后来又加入了能够实现高可用的 VRRP 功能。所以 Keepalived 除了可以管理 LVS 软件外,还能够做为其余服务(Nginx、Haproxy、MySQL 等)的高可用解决方案软件。
Keeplived 软件主要是经过 VRRP 协议实现高可用功能的,VRRP 出现的目的就是为了解决静态路由单点故障问题的,它可以保证当个别节点宕机时,整个网络能够不间断的运行,因此 Keepalived 一方面具备配置管理 LVS 的功能,同时还具备对 LVS 下面节点进行健康检查的功能,另外一方面也可实现系统网络服务的高可用性。
Keeplived 软件的官方网站是 http://www.keepalived.org。
二、Keeplived 高可用故障切换转移原理:
Keeplived 高可用服务对之间的故障切换转移,是经过 VRRP 协议(Virtual Router Redundancy Protocol,中文意思:虚拟路由器冗余协议)来实现的。
在 Keepailved 服务正常工做时,主 Master 节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备 Backup 节点本身还活着,当主 Master 节点发生故障时,就没法发送心跳信息了,备节点也就所以没法继续监测到来自主 Master 节点的心跳了,进而调用自身的接管程序,接管主 Master 节点的 IP 资源及服务。而当主 Master 节点恢复时,备 Bacckup 节点又会释放主节点故障时自身接管的 IP 资源及服务,恢复到原来的备用角色。
三、企业面试题:简要回答 Keeplived 的工做原理:
Keeplived 软件高可用对之间是经过 VRRP 协议通讯的,所以,我从 VRRP 协议介绍开始:
① VRRP 协议全称 Virtual Router Redundancy Protocol,中文意思:虚拟路由器冗余协议。它的出现是为了解决静态路由的单点故障;
② VRRP 协议是经过一种竞选协议机制来将路由任务交给某台 VRRP 路由器的;
③ VRRP 协议是经过 IP 多播方式(默认多播地址 224.0.0.18)实现高可用对之间通讯的;
④ 工做主节点发包,备节点接包,当备节点接收不到主节点发的数据包的时候,就启动接管程序接管主节点的资源,备节点能够有多个,经过优先级竞选,但通常 Keepalived 系统运维工做中都是用一对。
⑤ VRRP 使用了加密协议加密数据,但 Keepalived 官方目前仍是推荐用明文的方式配置认证类型和密码。
介绍完了 VRRP 协议,接下来介绍 Keepalived 服务的工做原理:
Keepalived 高可用对之间是经过 VRRP 协议进行通讯的,VRRP 协议是经过竞选机制来肯定主备的,主优先级高于备,所以工做时主会优先得到全部的资源,备节点处于等待状态,当主挂了的时候,备节点就会接管主节点的资源,而后顶替主节点对外提供服务。
在 Keepalived 服务对之间,只有做为主的服务器会一直发送 VRRP 广播包,告诉备它还活着,此时备不会抢占主,当主不可用时,即备监听不到主发送的广播包时就会启动相关服务接管资源,保证业务的连续性,接管速度最快能够小于 1 秒。
四、keepalived 高可用服务搭建:
1)、搭建环境准备:
2)、Keepalived 软件安装:
a、在两台负载均衡服务器安装 Keepalived 软件:html
[root@lb01 ~]# yum install keepalived -y [root@lb01 ~]# rpm -qa keepalived keepalived-1.2.13-5.el6_6.x86_64
b、在两台负载均衡服务器启动 Keepalived 软件:前端
[root@lb01 ~]# /etc/init.d/keepalived start Starting keepalived: [ OK ] [root@lb01 ~]# ps -ef|grep keep|grep -v grep # 有三个进程表示正常 root 1186 1 0 Jul26 ? 00:00:03 /usr/sbin/keepalived -D root 1187 1186 0 Jul26 ? 00:00:03 /usr/sbin/keepalived -D root 1188 1186 0 Jul26 ? 00:00:12 /usr/sbin/keepalived -D
c、添加虚拟 IP 的两种方式:node
① ifconfig eth0:0 192.168.153.100/24 up ② ip addr add 192.168.153.100/24 dev eth0 label eth0:1 # 这种给添加的 IP 加标签的方式能够用 ifconfig 命令查到添加的 IP,不然只能用 ip add 查看添加的 IP。 提示:Keepalived 默认使用第二种方式添加的虚拟 IP 。早期的 Heartbeat 使用第一种方式添加虚拟 IP,在 Heartbeat 3.0 版本之后也使用第二种方式添加虚拟 IP 了。 [root@lb01 ~]# ip addr add 192.168.153.100/24 dev eth0 label eth0:1 [root@lb01 ~]# ip add|grep 153.100 inet 192.168.153.100/24 scope global secondary eth0:1
d、编辑 Keepalived 配置文件:ios
[root@lb01 ~]# man keepalived.conf # Keepalived 配置文件有三个部分。 TOP HIERACHY GLOBAL CONFIGURATION # 全局配置 VRRPD CONFIGURATION # VRRP 的配置 LVS CONFIGURATION # 结合 LVS 的配置
[root@lb01 ~]# vim /etc/keepalived/keepalived.conf 1 ! Configuration File for keepalived # 这里井号叹号都为注释。 2 3 global_defs { # 全局配置。 4 notification_email { 5 acassen@firewall.loc ############## 6 failover@firewall.loc # 这三行是接收邮件的收件人(没什么用)。 7 sysadmin@firewall.loc ############## 8 } 9 notification_email_from Alexandre.Cassen@firewall.loc # 发件人。 10 smtp_server 192.168.200.1 # 邮件服务器。 11 smtp_connect_timeout 30 # 邮件服务器。 12 router_id LVS_DEVEL # 路由 ID,不一样机器之间不能重复。 13 } 14 15 vrrp_instance VI_1 { # VRRP 实例【VI_1 是实例名字,能够配多个(VI_2等)】。 16 state MASTER # 角色(主),傀儡、不决定主备。 17 interface eth0 # 通讯的接口。 18 virtual_router_id 51 # 该实例的 ID,不一样的实例 ID 要不一样。 19 priority 150 # 优先级,竞选看优先级(决定主备的参数)。 20 advert_int 1 # 通讯检查间隔时间为 1 s,发广播的间隔时间内从 Backup 服务器没有接收到广播就接替工做。 21 authentication { # 主备通讯方式。 22 auth_type PASS # 认证机制,明文的密码方式。 23 auth_pass 1111 # 认证的密码。 24 } 25 virtual_ipaddress { # VIP 虚拟 IP,能够是一组也能够是一个。 26 192.168.153.100/24 dev eth0 label eth0:1 27 } 28 } 上面为主服务器的配置文件,绿色的部分都是备服务器须要修改的: 12 router_id LVS_DEVEL1 16 state BACKUP 19 priority 100
e、Master 节点和 Backup 节点特殊参数的不一样:
3)、此时查看两台服务器上面的虚拟 IP:nginx
在主节点查看虚拟 IP 的存在: [root@lb01 ~]# ip add|grep 153.100 # 主 Master 节点有添加的虚拟 IP(优先级高)。 inet 192.168.153.100/24 scope global secondary eth0:1 在备节点查看虚拟 IP 的存在: [root@lb02 ~]# ip add |grep 153.100 # 备 Backup 节点没有(主正常,备等待)。
4)、以 Windows为客户端测试主备节点的高可用:
① 经过 Windows 客户端连续 ping 虚拟 IP:
② 此时在主节点能够看到虚拟 IP :面试
[root@lb01 ~]# ip add|grep 192.168.136.100 inet 192.168.136.100/24 scope global secondary eth0:1
③ 关掉主节点的 Keepalived 服务:数据库
[root@lb01 ~]# /etc/init.d/keepalived stop Stopping keepalived: [ OK ]
④ 查看备节点的虚拟 IP(备接管主的工做):vim
[root@lb02 ~]# ip add|grep 192.168.136.100 inet 192.168.136.100/24 scope global secondary eth0:1
⑤ 启动主节点的 Keepalived 服务并查看虚拟 IP :浏览器
[root@lb01 ~]# /etc/init.d/keepalived start Starting keepalived: [ OK ] [root@lb01 ~]# ip add|grep 192.168.136.100 # 略有延迟,编译安装快? inet 192.168.136.100/24 scope global secondary eth0:1
5)、Keepalived 多实例的配置及实现:
首先添加另外一个虚拟 IP :[root@lb01 ~]# ip addr add 192.168.153.200/24 dev eth0 label eth0:2
修改两台负载均衡器的 keepalived.conf 配置文件:
① 在 lb 01 的 keepalived.conf 配置文件添加以下内容:服务器
vrrp_instance VI_2 { # 表示第二个实例名字。(与第一个实例不一样) state BACKUP # 第二个实例的备 Backup 节点。 interface eth0 virtual_router_id 52 # 虚拟路由 id,不一样实例要不一样,同一实例主备相同。 priority 100 # 优先级。 advert_int 1 authentication { auth_type PASS auth_pass 1112 # 主备通讯的密码,同一实例主备相同(不一样实例最好区分,非必须)。 } virtual_ipaddress { 192.168.153.200/24 dev eth0 label eth0:2 # 添加的虚拟 IP 不一样实例不一样,网卡标签不一样。 } }
② 在 lb 02 的 keepalived.conf 配置文件添加以下内容:
vrrp_instance VI_2 { # 表示第二个实例名字。(与第一个实例不一样) state MASTER # 第二个实例的主 MASTER 节点。 interface eth0 virtual_router_id 52 # 虚拟路由 id,不一样实例要不一样,同一实例主备相同。 priority 150 # 优先级。 advert_int 1 authentication { auth_type PASS auth_pass 1112 # 主备通讯的密码,同一实例主备相同(不一样实例最好区分,非必须)。 } virtual_ipaddress { 192.168.153.200/24 dev eth0 label eth0:2· # 添加的虚拟 IP 不一样实例不一样,网卡标签不一样。 } }
③ 重启两台服务器使配置生效:
[root@lb01 ~]# /etc/init.d/keepalived restart Stopping keepalived: [ OK ] Starting keepalived: [ OK ] [root@lb02 ~]# /etc/init.d/keepalived restart Stopping keepalived: [ OK ] Starting keepalived: [ OK ]
④ 经过查看虚拟 IP 测试多实例的生效:
[root@lb01 ~]# ip add|egrep "153.100|153.200" # 实例一优先级高的是 lb01,因此 VIP 100存在。 inet 192.168.153.100/24 scope global secondary eth0:1 [root@lb02 ~]# ip add |egrep "153.100|153.200" # 实例二优先级高的是 lb02,因此 VIP 200存在。 inet 192.168.153.200/24 scope global secondary eth0:2
关闭 lb01 服务器的 Keepalived 服务:
[root@lb01 ~]# /etc/init.d/keepalived stop Stopping keepalived: [ OK ] [root@lb01 ~]# ip add |egrep "153.100|153.200" # 此时该服务器没有 VIP 在工做了。 [root@lb02 ~]# ip add|egrep "153.100|153.200" # lb02 服务器接管了两个 VIP 的工做。 inet 192.168.153.100/24 scope global secondary eth0:1 inet 192.168.153.200/24 scope global secondary eth0:2
启动 lb01 服务器的 Keepalived 服务:
[root@lb01 ~]# /etc/init.d/keepalived start Starting keepalived: [ OK ] [root@lb01 ~]# ip add|egrep "153.100|153.200" # 实例一优先级高的是 lb01,因此 VIP 100存在。 inet 192.168.153.100/24 scope global secondary eth0:1 [root@lb02 ~]# ip add |egrep "153.100|153.200" # 实例二优先级高的是 lb02,因此 VIP 200存在。 inet 192.168.153.200/24 scope global secondary eth0:2
关闭 lb02 服务器的 Keepalived 服务:
[root@lb02 ~]# /etc/init.d/keepalived stop Stopping keepalived: [ OK ] [root@lb02 ~]# ip add |egrep "153.100|153.200" # 此时该服务器没有 VIP 在工做了。 [root@lb01 ~]# ip add|egrep "153.100|153.200" # lb01 服务器接管了两个 VIP 的工做。 inet 192.168.153.100/24 scope global secondary eth0:1 inet 192.168.153.200/24 scope global secondary eth0:2
五、Keepalived 配合 Nginx 负载均衡实现高可用:
方案一:两台负载同时启动 Nginx 代理,Keepalived 负责 VIP 漂移,VIP 漂移到哪一个机器哪一个就提供访问:
① 检查环境:
两台 Nginx 负载均衡器的 Keepalived 服务和 Nginx 服务都是开启状态:
[root@lb01 ~]# /etc/init.d/keepalived status keepalived (pid 2622) is running... [root@lb02 ~]# /etc/init.d/keepalived status keepalived (pid 2622) is running... [root@lnmp01 conf]# ps -ef|grep nginx|grep -v grep root 2045 1 0 Jun22 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx nginx 2137 2045 0 Jun22 ? 00:00:00 nginx: worker process [root@lnmp02 conf]# ps -ef|grep nginx|grep -v grep root 2045 1 0 Jun22 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx nginx 2137 2045 0 Jun22 ? 00:00:00 nginx: worker process
② 备份并编辑 Web 服务器的配置文件:
[root@lb01 conf]# pwd /application/nginx/conf [root@lb01 conf]# vim nginx.conf [root@lb01 conf]# cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream www_server_pools{ # ip_hash; server 192.168.136.150:80 weight=1; server 192.168.136.151:80 weight=1; } server { listen 80; server_name www.etiantian.org; location / { proxy_pass http://www_server_pools; } } }
③ 检查 Web01 和 Web02 服务器 www 站点首页文件:
[root@lnmp01 ~]# cat /application/nginx/html/www/index.html www.etiantian.org 150 [root@lnmp02 ~]# cat /application/nginx/html/www/index.html www.etiantian.org 151
④ 修改负载均衡服务器 hosts 并 curl 访问 Web 服务器:
[root@lb01 conf]# vim /etc/hosts [root@lb01 conf]# cat /etc/hosts 192.168.153.100 www.etiantian.org # 将域名解析到虚拟 IP。
[root@lb01 conf]# for n in `seq 10`;do curl www.etiantian.org;done # 实现。 www.etiantian.org 150 www.etiantian.org 151 www.etiantian.org 150 www.etiantian.org 151 www.etiantian.org 150 www.etiantian.org 151 www.etiantian.org 150 www.etiantian.org 151 www.etiantian.org 150 www.etiantian.org 151
⑤ 实现两台负载均衡器的高可用,要让它们的 Nginx 配置文件一致:
[root@lb02 conf]# cd /application/nginx/conf/ [root@lb02 conf]# vim nginx.conf # 跟以上配置一致。 [root@lb02 conf]# ../sbin/nginx -t nginx: the configuration file /application/nginx-1.6.3/conf/nginx.conf syntax is ok nginx: configuration file /application/nginx-1.6.3/conf/nginx.conf test is successful [root@lb02 conf]# ../sbin/nginx -s reload
测试 lb02 负载均衡器的工做是否正常:
[root@lb02 conf]# tail -1 /etc/hosts 192.168.136.162 www.etiantian.org # 备节点没有 VIP,因此解析到本身的 IP 测试。
[root@lb02 conf]# for n in `seq 10`;do curl www.etiantian.org;done www.etiantian.org 150 www.etiantian.org 151 www.etiantian.org 150 www.etiantian.org 151 www.etiantian.org 150 www.etiantian.org 151 www.etiantian.org 150 www.etiantian.org 151 www.etiantian.org 150 www.etiantian.org 151
⑥ 在 Windows 作域名对应 VIP 的解析并经过浏览器访问:
徽标键 + R 运行窗口 drivers 命令修改 hosts以下:
192.168.136.100 www.etiantian.org
经过浏览器访问域名 www.etiantian.org:
访问到 Web 01 的首页文件:
刷新后访问到 Web 02 的首页文件:
⑦ 此时让 LB01 宕机,再访问,业务不受影响:
缘由:VIP 飘到 LB 02 服务器了,lb 02 接管工做,以下:
[root@lb02 conf]# ip add|egrep 136.100 inet 192.168.136.100/24 scope global secondary eth0:1
⑧ 开启 LB01 服务器,再访问,业务不受影响,VIP 从新飘回LB01:
[root@lb01 conf]# ip add|egrep 136.100 inet 192.168.136.100/24 scope global secondary eth0:1 [root@lb02 conf]# ip add|egrep 136.100 # lb02 没有 VIP 100 了。
方案二:经过 Keepalived 多实例配合 Nginx 实现双主:
www.etiantian.org 的 VIP 为 192.168.136.100 ,在 lb01 上是主。
blog.etiantian.org 的 VIP 为 192.168.136.200 ,在 lb02 上是主。
① 编辑 lb01 的 Nginx 配置文件:
[root@lb01 conf]# vim nginx.conf [root@lb01 conf]# cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream www_server_pools{ # ip_hash; server 192.168.136.150:80 weight=1; server 192.168.136.151:80 weight=1; } server { listen 192.168.136.100:80; server_name www.etiantian.org; location / { proxy_pass http://www_server_pools; } } server { listen 192.168.136.200:80; server_name blog.etiantian.org; location / { proxy_pass http://www_server_pools; } } }
② Nginx 没法启动的问题:
[root@lb01 conf]# pkill nginx [root@lb01 conf]# /application/nginx/sbin/nginx nginx: [emerg] bind() to 192.168.136.200:80 failed (99: Cannot assign requested address) [root@lb01 conf]# lsof -i :80 # Nginx 没法启动。 [root@lb01 conf]# ifconfig|egrep 136.200 # 缘由:配置文件监听了网卡上不存在的 IP。 [root@lb01 conf]# echo 'net.ipv4.ip_nonlocal_bind = 1' >>/etc/sysctl.conf # 添加内核参数。 [root@lb01 conf]# sysctl -p|grep net.ipv4.ip_nonlocal_bind net.ipv4.ip_nonlocal_bind = 1 # 启动 Nginx 时忽略配置中监听的 VIP 是否存在。 [root@lb01 conf]# /application/nginx/sbin/nginx # 启动成功。 [root@lb01 conf]# lsof -i :80 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nginx 3040 root 6u IPv4 15768 0t0 TCP www.etiantian.org:http (LISTEN) nginx 3040 root 7u IPv4 15769 0t0 TCP 192.168.136.200:http (LISTEN) nginx 3041 nginx 6u IPv4 15768 0t0 TCP www.etiantian.org:http (LISTEN) nginx 3041 nginx 7u IPv4 15769 0t0 TCP 192.168.136.200:http (LISTEN)
③ 让 lb02 服务器的 Nginx 配置文件和 lb01 相同:
[root@lb02 conf]# vim nginx.conf [root@lb02 conf]# echo 'net.ipv4.ip_nonlocal_bind = 1' >>/etc/sysctl.conf [root@lb02 conf]# sysctl -p|grep net.ipv4.ip_nonlocal_bind net.ipv4.ip_nonlocal_bind = 1 [root@lb02 conf]# pkill nginx [root@lb02 conf]# ../sbin/nginx -t [root@lb02 conf]# ../sbin/nginx
④ 查看 Keepalilved 配置文件(多实例):
说明:192.168.136.100 这个 VIP 在 lb01 上是 MASTER,在 lb02 上是 BACKUP;
192.168.136.200 这个 VIP 在 lb02 上是 MASTER,在 lb01 上是 BACKUP;
[root@lb01 conf]# cat /etc/keepalived/keepalived.conf # lb01 配置。(lb02 略) router_id LVS_DEVEL_1 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 150 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.136.100/24 dev eth0 label eth0:1 } } vrrp_instance VI_2 { state BACKUP interface eth0 virtual_router_id 5 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1112 } virtual_ipaddress { 192.168.136.200/24 dev eth0 label eth0:2 } }
⑤ 查看两边运行的 VIP 及Web 服务器 blog 站点首页文件:
[root@lb01 conf]# ip add|egrep "136.100|136.200" # lb01 提供服务的 VIP 是 100。 inet 192.168.136.100/24 scope global secondary eth0:1 [root@lb02 conf]# ip add|egrep "136.100|136.200" # lb02 提供服务的 VIP 是 200。 inet 192.168.136.200/24 scope global secondary eth0:2
[root@lnmp01 ~]# cat /application/nginx/html/blog/index.html blog.etiantian.org 150 [root@lnmp02 ~]# cat /application/nginx/html/blog/index.html blog.etiantian.org 151
⑥ 在负载均衡器测试访问 blog 站点:
[root@lb02 conf]# vim /etc/hosts # lb02 上面提供服务的 VIP 为 200。 192.168.136.200 blog.etiantian.org
[root@lb02 conf]# for n in `seq 10`;do curl blog.etiantian.org;done blog.etiantian.org 150 blog.etiantian.org 151 blog.etiantian.org 150 blog.etiantian.org 151 blog.etiantian.org 150 blog.etiantian.org 151 blog.etiantian.org 150 blog.etiantian.org 151 blog.etiantian.org 150 blog.etiantian.org 151
⑦ 在 WINDOWS 上作 hosts 解析并经过浏览器测试:
Windows 上的 hosts 解析:
192.168.136.100 www.etiantian.org 192.168.136.200 blog.etiantian.org
经过 ping 域名确保配置可用:
C:\Users\admin>ping blog.etiantian.org -t 正在 Ping blog.etiantian.org [192.168.136.200] 具备 32 字节的数据 来自 192.168.136.200 的回复: 字节=32 时间<1ms TTL=64 来自 192.168.136.200 的回复: 字节=32 时间<1ms TTL=64 来自 192.168.136.200 的回复: 字节=32 时间<1ms TTL=64
C:\Users\admin>ping www.etiantian.org -t 正在 Ping www.etiantian.org [192.168.136.100] 具备 32 字节的数据: 来自 192.168.136.100 的回复: 字节=32 时间=38ms TTL=64 来自 192.168.136.100 的回复: 字节=32 时间<1ms TTL=64 来自 192.168.136.100 的回复: 字节=32 时间<1ms TTL=64
经过浏览器访问域名测试:
首先访问 www.etiantian.org 结果以下:
刷新后实现负载均衡:
经过访问 blog.etiantian.org 结果以下:
刷新后实现负载均衡:
⑧ 把 lb01 停掉,查看业务运行状况:
关掉后 ping 两个域名都是能通的:
C:\Users\admin>ping blog.etiantian.org -t 正在 Ping blog.etiantian.org [192.168.136.200] 具备 32 字节的数据 来自 192.168.136.200 的回复: 字节=32 时间<1ms TTL=64 来自 192.168.136.200 的回复: 字节=32 时间<1ms TTL=64 来自 192.168.136.200 的回复: 字节=32 时间<1ms TTL=64
C:\Users\admin>ping www.etiantian.org -t 正在 Ping www.etiantian.org [192.168.136.100] 具备 32 字节的数据: 来自 192.168.136.100 的回复: 字节=32 时间=38ms TTL=64 来自 192.168.136.100 的回复: 字节=32 时间<1ms TTL=64 来自 192.168.136.100 的回复: 字节=32 时间<1ms TTL=64
查看 lb02 负载均衡器提供服务的 VIP:
[root@lb02 conf]# ifconfig|egrep "136.100|36.200" inet addr:192.168.136.100 Bcast:0.0.0.0 Mask:255.255.255.0 # 该 VIP 飘到 lb02 了。 inet addr:192.168.136.200 Bcast:0.0.0.0 Mask:255.255.255.0
此时经过浏览器访问两个域名,业务是正常的(结果略)。
⑨ 从新把负载均衡器 lb01 启动,检查业务状况:
经过 ping 两个域名都能 ping 通:
C:\Users\admin>ping blog.etiantian.org -t 正在 Ping blog.etiantian.org [192.168.136.200] 具备 32 字节的数据 来自 192.168.136.200 的回复: 字节=32 时间<1ms TTL=64 来自 192.168.136.200 的回复: 字节=32 时间<1ms TTL=64 来自 192.168.136.200 的回复: 字节=32 时间<1ms TTL=64
C:\Users\admin>ping www.etiantian.org -t 正在 Ping www.etiantian.org [192.168.136.100] 具备 32 字节的数据: 来自 192.168.136.100 的回复: 字节=32 时间=38ms TTL=64 来自 192.168.136.100 的回复: 字节=32 时间<1ms TTL=64 来自 192.168.136.100 的回复: 字节=32 时间<1ms TTL=64
此时经过浏览器访问两个域名,业务是正常的(结果略)。
查看两个负载均衡器 VIP 的工做状况:
[root@lb01 conf]# ifconfig|egrep "136.100|36.200" # VIP 100 从新飘回。 inet addr:192.168.136.100 Bcast:0.0.0.0 Mask:255.255.255.0 [root@lb02 conf]# ifconfig|egrep "136.100|36.200" # VIP 200 正常。 inet addr:192.168.136.200 Bcast:0.0.0.0 Mask:255.255.255.0
⑩ 把 lb02 停掉,查看业务运行状况(同上,略)。
注意:Web 服务能够来回切换,可是数据库千万不能用该方式切换,由于把数据库从主切到备,用户在备上写数据,再切回主会致使主从数据库数据不一致的状况(通常数据库经过手动切换)。
服务器网线松动等网络故障; 服务器硬件故障发生损坏现象而崩溃; Nginx 服务死掉。 提示:keepalived 是服务器级别的切换(基于系统的,不是基于软件的)。
一、问题描述:负载均衡服务器没宕机,但 Nginx 服务宕了,如何保证高可用正常切换?
思路:监控 Nginx 服务状态,若是不正常就停掉 Keepalived 或 halt 关机。
模拟问题场景以下:
[root@lb01 conf]# pkill nginx [root@lb01 conf]# lsof -i :80 [root@lb01 conf]# ifconfig|egrep "136.100|136.200" inet addr:192.168.136.100 Bcast:0.0.0.0 Mask:255.255.255.0
此时 www.etiantian.org 域名没法访问:
方法一:经过守护进程脚本实现:
[root@lb01 scripts]# ps -C nginx PID TTY TIME CMD 3436 ? 00:00:00 nginx 3437 ? 00:00:00 nginx [root@lb01 scripts]# ps -C nginx --no-header 3482 ? 00:00:00 nginx 3483 ? 00:00:00 nginx [root@lb01 scripts]# ps -C nginx --no-header|wc -l 2
[root@lb01 scripts]# pkill nginx [root@lb01 scripts]# ps -C nginx --no-header [root@lb01 scripts]# ps -C nginx --no-header|wc -l 0
[root@lb01 scripts]# /application/nginx/sbin/nginx [root@lb01 conf]# mkdir -p /server/scripts/ [root@lb01 conf]# cd /server/scripts/ [root@lb01 scripts]# vim check_w_proxy.sh [root@lb01 scripts]# cat check_w_proxy.sh #!/bin/sh while true do nginxpid=`ps -C nginx --no-header|wc -l` if [ $nginxpid -eq 0 ];then /application/nginx/sbin/nginx sleep 5 nginxpid=`ps -C nginx --no-header|wc -l` if [ $nginxpid -eq 0 ];then /etc/init.d/keepalived stop exit 1 fi fi sleep 5 done
[root@lb01 scripts]# yum install dos2unix -y [root@lb01 scripts]# dos2unix check_w_proxy.sh [root@lb01 scripts]# sh check_w_proxy.sh & # 让脚本后台运行。 [1] 3510
测试过程:
[root@lb01 scripts]# ps -ef|grep nginx # Nginx 服务正常。 root 3482 1 0 23:54 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx nginx 3483 3482 0 23:54 ? 00:00:00 nginx: worker process [root@lb01 scripts]# ps -ef|grep keepalived # Keepalived 服务正常。 root 2622 1 0 18:16 ? 00:00:01 /usr/sbin/keepalived -D root 2624 2622 0 18:16 ? 00:00:01 /usr/sbin/keepalived -D root 2625 2622 0 18:16 ? 00:00:12 /usr/sbin/keepalived -D root 3618 3087 0 23:59 pts/1 00:00:00 grep keepalived [root@lb01 scripts]# ifconfig|egrep "136.100|136.200" # VIP 100 工做正常。 inet addr:192.168.136.100 Bcast:0.0.0.0 Mask:255.255.255.0
[root@lb01 scripts]# pkill nginx # 杀掉 Nginx 服务进程。 [root@lb01 scripts]# ifconfig|egrep "136.100|136.200" # VIP 没有飘移。 inet addr:192.168.136.100 Bcast:0.0.0.0 Mask:255.255.255.0 [root@lb01 scripts]# ps -ef|grep nginx # 查看 Nginx 服务进程(脚本里启动了 Nginx)。 root 3772 1 0 00:02 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx nginx 3774 3772 0 00:02 ? 00:00:00 nginx: worker process root 3786 3087 0 00:02 pts/1 00:00:00 grep nginx
编辑上面的脚本让 Nginx 不尝试启动:
[root@lb01 scripts]# vim check_w_proxy.sh [root@lb01 scripts]# cat check_w_proxy.sh # 注释掉启动 Nginx 的内容。 #!/bin/sh while true do nginxpid=`ps -C nginx --no-header|wc -l` if [ $nginxpid -eq 0 ];then # /application/nginx/sbin/nginx # sleep 5 # nginxpid=`ps -C nginx --no-header|wc -l` # if [ $nginxpid -eq 0 ];then /etc/init.d/keepalived stop exit 1 fi # fi sleep 5 done
从新执行该脚本:
[root@lb01 scripts]# ps -ef|grep check # 查看该守护进程。 root 3510 3087 0 Jun23 pts/1 00:00:00 sh check_w_proxy.sh [root@lb01 scripts]# jobs # 查看后台执行的程序。 [1]+ Running sh check_w_proxy.sh & [root@lb01 scripts]# fg # 拿到前台执行。 sh check_w_proxy.sh ^C # 经过 Ctrl + c 中止该程序的运行。 [root@lb01 scripts]# sh check_w_proxy.sh & # 再让脚本后台运行。 [1] 4178 [root@lb01 scripts]# ps -ef|grep nginx|grep -v grep # Nginx 是运行状态。 root 3772 1 0 00:02 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx nginx 3774 3772 0 00:02 ? 00:00:00 nginx: worker process [root@lb01 scripts]# ifconfig|egrep "136.100|136.200" # VIP 工做正常。 inet addr:192.168.136.100 Bcast:0.0.0.0 Mask:255.255.255.0
[root@lb01 scripts]# pkill nginx # 杀掉 Nginx 进程。 [root@lb01 scripts]# Stopping keepalived: [ OK ] # 守护进程自动关闭 Keepalived。 [1]+ Exit 1 sh check_w_proxy.sh [root@lb01 scripts]# ps -ef|grep nginx # 查看 Nginx 进程(没有了)。 root 4374 3087 0 00:16 pts/1 00:00:00 grep nginx [root@lb01 scripts]# ps -ef|grep nginx|grep -v grep [root@lb01 scripts]# ifconfig|egrep "136.100|136.200" # VIP 没有了。
到 lb02 查看 VIP 漂移的状况:
[root@lb02 conf]# ifconfig|egrep "136.100|136.200" # VIP 飘到了 lb02 上提供服务。 inet addr:192.168.136.100 Bcast:0.0.0.0 Mask:255.255.255.0 inet addr:192.168.136.200 Bcast:0.0.0.0 Mask:255.255.255.0
此时业务也回归正常了:
方法二:Keepalived 配置触发:
① 修改 Keepalived 配置文件:
[root@lb01 scripts]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL_1 } vrrp_script check_w_proxy { # 定义 VRRP 脚本检查 Nginx 进程号。 script "/server/scripts/check_w_proxy.sh" # 当 Nginx 有问题就执行脚本停掉 Keepailved。 interval 2 # 间隔时间 2s 。 weight 2 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 150 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.136.100/24 dev eth0 label eth0:1 } track_script { # 放到哪一个实例哪一个实例就进行触发。 check_w_proxy # 触发检查。 } } vrrp_instance VI_2 { state BACKUP interface eth0 virtual_router_id 5 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1112 } virtual_ipaddress { 192.168.136.200/24 dev eth0 label eth0:2 } }
② 重启并测试配置结果:
[root@lb01 scripts]# /application/nginx/sbin/nginx # 启动 Nginx。 [root@lb01 scripts]# /etc/init.d/keepalived stop # 关闭 Keepalived 服务。 Stopping keepalived: [ OK ] [root@lb01 scripts]# /etc/init.d/keepalived start # 启动 Keepalived 服务。 Starting keepalived: [ OK ] [root@lb01 scripts]# chmod +x check_w_proxy.sh # 给脚本加执行权限。 [root@lb01 scripts]# ps -ef|grep nginx|grep -v grep # Nginx 服务正常。 root 4485 1 0 00:40 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx nginx 4486 4485 0 00:40 ? 00:00:00 nginx: worker process [root@lb01 scripts]# ifconfig|egrep "136.100|136.200" # VIP 工做正常。 inet addr:192.168.136.100 Bcast:0.0.0.0 Mask:255.255.255.0
③ 正常状况下杀掉 Nginx 后 Keepalived 会停掉,VIP 飘移到 lb02上面:
[root@lb01 ~]# ip add|grep 136.100 # lb01 上的 VIP 正常工做。 inet 192.168.136.100/24 scope global secondary eth0:1 [root@lb01 ~]# pkill nginx # 杀掉 Nginx 进程。 [root@lb01 ~]# ps -ef|grep keepalived|grep -v grep # 触发脚本关掉了 Keepalived 服务。 [root@lb01 ~]# ip add|grep 136.100 # lb01 上的 VIP 没有了(漂移到 lb02 了)。 [root@lb02 scripts]# ip add|egrep "136.100|136.200" # LB02 接替 lb01 的工做,VIP 飘过来。 inet 192.168.136.200/24 scope global secondary eth0:2 inet 192.168.136.100/24 scope global secondary eth0:1 [root@lb01 ~]# /application/nginx/sbin/nginx # 从新启动 Nginx 服务。 [root@lb01 ~]# /etc/init.d/keepalived start # 从新启动 Keepalived 服务。 Starting keepalived: [ OK ] [root@lb01 ~]# ip add|grep 136.100 # lb01 上的 VIP 恢复了正常工做。 inet 192.168.136.100/24 scope global secondary eth0:1 [root@lb02 scripts]# ip add|egrep "136.100|136.200" # lb02 恢复正常工做状态。 inet 192.168.136.200/24 scope global secondary eth0:2
二、多组 Keepalived 服务器在一个局域网的冲突问题:
当在同一个局域网内部署了多组 Keepalived 服务器对,而又未使用专门的心跳线通讯时,可能会发生高可用接管的严重故障问题。Keepalived 高可用功能是经过 VRRP 协议实现的,VRRP 协议默认经过 IP 多播的形式实现高可用对之间的通讯,若是同一个局域网内存在多组 Keepalived 服务器对,就会形成 IP 多播地址冲突问题,致使接管错乱,不一样组的 Keepalived 都会使用默认的 224.0.0.
18 做为多播地址。此时的解决办法是在同组的 Keepalived 服务器全部的配置文件里指定独一无二的多播地址,配置以下:
global_defs { route_id LVS_19 vrrp_mcast_group4 224.0.0.19 # 这个就是指定多播地址的配置。 }
三、配置指定文件接收 Keepalived 服务日志:
默认状况下 Keepalived 服务日志会输出到系统日志 /var/log/message,和其余日志信息混合在一块儿很不方便,能够将其调整成独立的文件记录 Keepalived 服务日志。
[root@lb01 scripts]# tailf /var/log/messages Jun 24 01:01:32 lb01 Keepalived[5896]: Stopping Keepalived v1.2.13 (03/19,2015) Jun 24 01:01:32 lb01 Keepalived_vrrp[5899]: VRRP_Instance(VI_1) sending 0 priority Jun 24 01:01:32 lb01 Keepalived_vrrp[5899]: VRRP_Instance(VI_1) removing protocol VIPs. Jun 24 01:01:32 lb01 Keepalived_healthcheckers[5898]: Netlink reflector reports IP 192.168.136.100 removed
配置指定文件记录 Keepalived 服务日志操做步骤:
① 编辑文件 /etc/sysconfig/keepalived 以下:
KEEPALIVED_OPTIONS="-D -d -S 0" [root@lb01 scripts]# less /etc/sysconfig/keepalived # 查看配置参数的详细信息。 # --vrrp -P Only run with VRRP subsystem. # --check -C Only run with Health-checker subsystem. # --dont-release-vrrp -V Dont remove VRRP VIPs & VROUTEs on daemon stop. # --dont-release-ipvs -I Dont remove IPVS topology on daemon stop. # --dump-conf -d Dump the configuration data. # 导出数据。 # --log-detail -D Detailed log messages. # 详细日志。 # --log-facility -S 0-7 Set local syslog facility (default=LOG_DAEMON) # 指定设备。 KEEPALIVED_OPTIONS="-D -d -S 0" [root@lb01 scripts]# sed -i '14 s#KEEPALIVED_OPTIONS="-D"#KEEPALIVED_OPTIONS="-D -d -S 0"#g' /etc/sysconfig/keepalived # 修改内容。 [root@lb01 scripts]# sed -n '14p' /etc/sysconfig/keepalived KEEPALIVED_OPTIONS="-D -d -S 0"
② 修改 /etc/rsyslog.conf 文件添加以下内容:
[root@lb01 scripts]# tail -3 /etc/rsyslog.conf # keepalived local0.* /var/log/keepalived.log # ### end of the forwarding rule ###
[root@lb01 scripts]# /etc/init.d/rsyslog restart # 重启 rsyslog。 Shutting down system logger: [ OK ] Starting system logger: [ OK ] [root@lb01 scripts]# cat /var/log/keepalived.log [root@lb01 scripts]# /etc/init.d/keepalived restart Stopping keepalived: [FAILED] Starting keepalived: [ OK ] [root@lb01 scripts]# cat /var/log/keepalived.log # 生成 Keepalived 日志内容。 Jun 24 01:49:27 lb01 Keepalived[6057]: Starting Keepalived v1.2.13 (03/19,2015) Jun 24 01:49:27 lb01 Keepalived[6058]: Starting Healthcheck child process, pid=6060 Jun 24 01:49:27 lb01 Keepalived[6058]: Starting VRRP child process, pid=6061 。。。。。。。。。。。。省略若干内容。。。。。。。。。。。。。
③ 让 /var/log/message 不记录 Keepalived 日志:【local0.none】
[root@lb01 scripts]# vim /etc/rsyslog.conf [root@lb01 scripts]# sed -n '42p' /etc/rsyslog.conf *.info;mail.none;authpriv.none;cron.none;local0.none /var/log/messages [root@lb01 scripts]# /etc/init.d/rsyslog restart Shutting down system logger: [ OK ] Starting system logger: [ OK ] [root@lb01 scripts]# > /var/log/messages # 清空系统日志。 [root@lb01 scripts]# > /var/log/keepalived.log # 清空 Keepalived 日志。 [root@lb01 scripts]# /etc/init.d/keepalived restart Stopping keepalived: [ OK ] Starting keepalived: [ OK ] [root@lb01 scripts]# cat /var/log/messages # 系统日志为空(再也不记录 Keepalived 日志)。
[root@lb01 scripts]# cat /var/log/keepalived.log # 只有配置的 Keepalived 日志文件记录 Keepalived 的日志。 Jun 24 02:00:47 lb01 Keepalived[6058]: Stopping Keepalived v1.2.13 (03/19,2015) Jun 24 02:00:47 lb01 Keepalived_vrrp[6061]: VRRP_Instance(VI_1) sending 0 priority Jun 24 02:00:47 lb01 Keepalived_vrrp[6061]: VRRP_Instance(VI_1) removing protocol VIPs ```. **四、Keepalived 高可用服务器对裂脑问题:** **什么是裂脑:** 因为某些缘由,致使两台高可用服务器对在指定时间内,没法检测到对方的心跳信息,各自取得资源及服务的全部权,而此时的两台高可用服务器对都还活着并在正常运行,这样就会致使同一个 IP 或服务在两端同时存在而发生冲突,最严重的是两台主机占用同一个 VIP 地址,每当用户写入数据时可能会分别写入到两端,这可能会致使服务器两端的数据不一致或数据丢失,这种状况被称为裂脑。 **列脑发生的缘由:** ① 高可用服务器对之间心跳线链路故障,致使没法正常通讯: 心跳线坏了(断掉、老化); 网卡及相关驱动坏了,IP 配置及冲突问题(网卡直连); 心跳间链接的设备故障(网卡及交换机); 仲裁的机器出问题(采用仲裁的方案)。 ② 高可用服务器对上开启了 iptables 防火墙阻挡了心跳消息传输: ③ 高可用服务器对上心跳网卡地址等信息配置不正确,致使发送心跳失败: ④ 其余服务配置不当等缘由,如心跳方式不一样,心跳广播冲突、软件 Bug 等。 提示:Keepalived 配置统一 VRRP 实例,若是 virtual_route_id 参数两端配置不一致也会致使裂脑。 **避免裂脑问题的常见方法:** ① 同时使用串行电缆和以太网电缆链接,同时用两条心跳线路,这样一条线路坏了,另外一个仍是好的,依然能传送心跳信息; ② 当检测到裂脑时强行关闭一个心跳节点(这个功能须要特殊设备,如 Stonith、Fence)。至关于设备节点接收不到心跳信息,发送关机命令经过单独的线路关闭主节点的电源;【Stonith:Shoot the other node in the head(爆头,关掉另外一个节点)】。 ③ 作好对裂脑的监控报警(如邮件及手机短信等或值班),在问题发生时人为第一时间介入仲裁,下降损失。例如:百度的监控报警短信就有上行和下行的区别。报警信息报到管理员手机上,管理员能够经过手机回复对应数字或简单的字符串操做返回给服务器,让服务器根据指令自动处理相应故障,这样解决故障的时间更短。 固然,在实施高可用方案时,要根据实际业务肯定是否能容忍这样的损失,根据不一样的需求选择不一样的解决方案(通常网站的常规业务,这个损失是可容忍的)。 **常见的解决裂脑的方案:** 做为互联网应用服务器的高可用,特别是前端 Web 负载均衡器的高可用,裂脑的问题对普通业务的影响是能够忍受的,若是是数据库或者存储的业务,通常出现裂脑问题就很是严重了。所以能够经过增长冗余心跳线路来避免裂脑问题的发生,同时增强对系统的监控,以便裂脑发生时人为快速介入解决问题。 ① 若是开启 iptables 防火墙,必定要让心跳消息经过,通常经过容许 IP 段的方式解决; ② 能够拉一条以太网网线或者串口线做为主备节点心跳线路的冗余; ③ 开发检测程序经过监控软件(例如 Nagios)监控裂脑。 生产场景检测裂脑的思路: ① 简单判断的思想:只要备节点出现 VIP 就报警,这个报警有两种状况,一是主机宕机备机接管了;二十主机没宕,裂脑了,不管哪一种状况,都进行报警,而后由人工查看判断及解决。 ② 比较严禁的判断:备节点出现对应 VIP,而且主节点及对应服务(若是远程链接主节点看是否有 VIP 就更好了)还活着,就说明裂脑了。 在备节点开发脚本测试是否发生裂脑问题:
[root@lb01 conf]# cd /server/scripts/
[root@lb01 scripts]# vim check_split_brain.sh
[root@lb01 scripts]# cat check_split_brain.sh
#!/bin/sh
lb01_vip=192.168.136.100
lb01_ip=192.168.136.161
while true
do
ping -c 2 -W 3 $lb01_ip &>/dev/null
if [ $? -eq 0 -a ip add|grep "$lb01_vip"|wc -l
-eq 1 ]thenecho "Ha is split brain.Warning."elseecho "Ha is OK"fisleep 5done[root@lb02 scripts]# sh check_split_brain.sh # 执行脚本检查结果。Ha is OKHa is OK