高可用冗余服务介绍
1) 解决网站单点故障
负载均衡服务
数据库服务(高可用 MHA)
存储服务器(NFS 实现高可用 Keepalived高可用脚本 (脚本)+sersync)
heartbeat+drbd(同步数据): http://www.linux-ha.org/wiki/Heartbeat
备份服务器 数据同步
批量管理服务
2)减轻服务器压力 (负载均衡压力)
实现方式: 利用keepalived服务软件
keepalived软件介绍:
1) 利用keepalived软件实现管理lvs服务
2) 利用keepalived软件实现后端节点健康检查功能
3) 利用keepalived软件可以实现冗余功能 ***
高可用服务实现主和备切换原理(vrrp 虚拟路由冗余协议)
Keepalived的工作原理: Keepalived高可用对之间是通过VRRP通信的,因此,我从VRRP开始讲起: 1)VRRP,全程Vritual Redundancy Protocol,中文名为虚拟路由器冗余协议,VRRP的出现是为了解决静态里有的单点故障。 2) VRRP是通一种竞选协议机制来将路由任务交给某台VRRP路由器的。 3)VRRP用IP多播的方式(默认多播地址(224.0.0.18))实现高可用对之间通信。 4)工作时主节点发包,备节点接包,当备节点接受不到主节点发的数据包的时候,就启动接管程序接管主节点的资源。备节点可以有多个,通过优先级竞选,但一般Keepalived系统运维工作中都是一对。 5)VRRP使用了加密协议加密数据,但Keepalived官方目前还是推荐用明文的方式配置认证类型和密码。 介绍完了VRRP,接下来我再介绍一下Keepalived服务的工作原理: Keepalived高可用对之间是通过VRRP进行通信的,VRRP是通过竞选机制来确定主备的,主的优先级高于备,因此,工作时主就会优先获得所有的资源,备节点处于等待状态,当主挂了的时候,
备节点就会接管主节点的资源,然后顶替主节点对外提供服务。 在Keepalived服务队之间,只有作为主的服务器会一直发送VRRP广播包,告诉备它还活着,此时备不会抢占主,当主不可用时,即备监听不到主发送的广播包时,就会启动相关服务接管资源,
保证业务的联系性。接管速度最快小于1秒!
实现高可用服务方法:keepalived
keepalived服务软件:
1) 为LVS而诞生。方便管理LVS
2) 利用keepalived实现负载均衡节点健康检查
3)实现高可用功能 负载均衡主备, NFS
综合架构高可用服务部署:
第一个历程: lb01/lb02负载均衡服务器上部署安装高可用服务 yum install -y keepalived 第二个历程: 编写keepalived配置文件 lb01负载均衡服务器 - 主 vim /etc/keepalived/keepalived.conf [root@lb01 ~]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { --- 全局配置 notification_email { acassen@firewall.loc --- 邮箱地址配置(主服务出现vip切换, 需要进行邮件告知管理员) } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 --- 邮件信息配置 smtp_connect_timeout 30 router_id lb01 --- 定义一个高可用集群中节点名称 } vrrp_instance(家族) oldboy { --- vrrp协议响应参数配置 数据库-实例 tomcat--实例 state MASTER --- 指定服务器在高可用服务中的身份(MASTER BACKUP) interface eth0 --- 指定vip地址出现在哪个网卡上 virtual_router_id 66 --- 家族标识 priority 150 --- 设置服务器优先级, 优先级越高, 越有可能成为主 advert_int 1 --- 主服务器发送组播包间隔 authentication { --- 配置高可用服务认证信息 auth_type PASS --- 确认进行组播通讯主机是在一个实例中 auth_pass 1234 } virtual_ipaddress { 10.0.0.3 --- 定义vip地址信息 } } lb02负载均衡服务器 - 备 vim /etc/keepalived/keepalived.conf [root@lb01 ~]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { --- 全局配置 notification_email { acassen@firewall.loc --- 邮箱地址配置(主服务出现vip切换, 需要进行邮件告知管理员) } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 --- 邮件信息配置 smtp_connect_timeout 30 router_id lb02 --- 定义一个高可用集群中节点名称 *主备不一样* } vrrp_instance(家族) oldboy { --- vrrp协议响应参数配置 数据库-实例 tomcat--实例 state BACKUP --- 指定服务器在高可用服务中的身份(MASTER BACKUP) *主备不一样* interface eth0 --- 指定vip地址出现在哪个网卡上 virtual_router_id 66 --- 家族标识 priority 100 --- 设置服务器优先级, 优先级越高, 越有可能成为主 *主备不一样* advert_int 1 --- 主服务器发送组播包间隔 authentication { --- 配置高可用服务认证信息 auth_type PASS --- 确认进行组播通讯主机是在一个实例中 auth_pass 1234 } virtual_ipaddress { 10.0.0.3 --- 定义vip地址信息 } } 第三个里程: 进行测试检查 检查主备切换: PS: 注意DNS域名解析, vip 网站域名 建立关系
高可用服务企业应用说明
1)高可用服务脑裂问题解决
主和备 都拥有vip地址
a.物理原因
主备之间心跳线通讯异常
设备上有防火墙服务开启
systemctl status firewalld.service
b 逻辑原因:
高可用服务服务配置文件错误
报警通知
脚本: 实时发现是否出现脑裂问题
思路1)确认监控那个主机
监控负载均衡备服务器
1:主备进行切换 进行报警
2:主备脑裂问题 进行报警
思路2) 如何进行报警通知
编写定时任务,利用邮件发送通知
思路3) 如何发现出现问题了
ip a s eth0|grep "10.0.0.3" echo $? 0或者 !0
[root@lb02 scripts]# cat monitor_vip.sh #!/bin/bash vip_info="10.0.0.3" ip a s eth0|grep "$vip_info" > /dev/null REVAL=$? if [ $REVAL -eq 0 ] then echo "please check keepalived server"|mail -s "keepalived error" **********@qq.com fi
设置定时任务:
* * * * * /bin/sh /server/scripts/monitor_vip.sh &>/dev/null
查看脚本的执行流程:
[root@lb02 scripts]# sh -x monitor_vip.sh + vip_info=10.0.0.3 + ip a s eth0 + grep 10.0.0.3 + REVAL=1 + '[' 1 -eq 0 ']'
2)实现监控nginx服务状态,进行主备切换
情况一:主服务器进行监控
a 确认nginx 服务进程信息
[root@lb01 ~]# ps -ef|grep -v grep|grep nginx root 11450 1 0 06:26 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf www 11451 11450 0 06:26 ? 00:00:00 nginx: worker process [root@lb01 ~]# ps -ef|grep "n[g]inx" root 11450 1 0 06:26 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf www 11451 11450 0 06:26 ? 00:00:00 nginx: worker process
中括号起作用是因为 grep进程是 '[n]ginx' 不是nginx ****
b 确认nginx服务端口信息
[root@lb01 ~]# netstat -lntup|grep -c nginx 1
备注:当有多个扩展配置文件的时候,是会出现多个nginx信息的 (80, 81 8080..)
方法一:实现秒级执行监控脚本
[root@lb01 scripts]# cat monitor_lb01.sh #!/bin/bash ps_num=$(ps -ef|grep -c n[g]inx) while true do if [ $ps_num -lt 2 ] then systemctl stop keepalived echo "please check lb01 nginx server"|mail -s "lb01 nginx error" **********@qq.com fi done
方法二: 编写keepalived配置文件
vrrp_script check_web { --- 设置监控项目名称 script "/server/scripts/monitor_lb01.sh" --- 指定监控脚本路径和名称信息 interval 2 --- 监控脚本执行间隔时间 默认秒 weight 2 --- 影响高可用服务优先级??? } track_script { check_web --- 需要调用监控项目信息 } PS: 确认脚本文件权限拥有执行权限 lb01配置文件 [root@lb01 scripts]# cat /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id lb01 } vrrp_script check_web { script "/server/scripts/monitor_lb01.sh" interval 2 weight 2 } vrrp_instance oldboy { state MASTER interface eth0 virtual_router_id 66 priority 150 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 10.0.0.3 } track_script { check_web } }
查看脚本执行的结果:
[root@lb01 scripts]# systemctl stop nginx [root@lb01 scripts]# systemctl is-active nginx keepalived.service unknown unknown
情况二:备服务器进行监控
weight 2 --- 修改服务优先级
1) 权重数值可以是正数: weight 10
a 脚本执行成功: 返回值为0 实际优先级=weight+priority(默认的优先级) 优先级增加
b 脚本执行失败: 返回值为非0 实际优先级=priority(默认的优先级)
2) 权重数值可以是负数: weight -10
a 脚本执行成功: 返回值为0 实际优先级=priority(默认的优先级)
b 脚本执行失败: 返回值为非0 实际优先级=priority(默认的优先级)+(-weight) 优先级减少
主服务器出现问题,备将优先级抢占过来 a 备服务器上权重值(正数/负数) 正数 b 脚本执行结果(成功/失败) 成功 备优先级=weight+priority >主优先级 脚本如何进行监控: 思路1: 发现主服务器网站页面出现故障(返回状态码 200 301 302)
[root@lb01 scripts]# curl -I www.baidu.com 2>/dev/null|awk 'NR==1 {print $2}'
200
[root@lb01 scripts]# curl -I www.360buy.com 2>/dev/null|awk 'NR==1 {print $2}'
301
[root@lb01 scripts]# curl -I www.baidu.com 2>/dev/null|awk 'NR==1 {print $2}'
200
[root@lb01 scripts]# curl -I www.360buy.com 2>/dev/null|awk 'NR==1 {print $2}'
301
-w : 指定输出的信息 -o : 指定默认输出到指定文件中 -s : 减少输出信息 #!/bin/bash code_info="$(curl -I -w "%{http_code} " -o /dev/null -s www.oldboy.com)" if [ $code_info -ne 200 ] then exit 0 else exit 1 fi 编写keepalived配置文件 vrrp_script check_web { --- 设置监控项目名称 script "/server/scripts/monitor_lb02.sh" --- 指定监控脚本路径和名称信息 interval 2 --- 监控脚本执行间隔时间 默认秒 weight 60 --- 影响高可用服务优先级??? } track_script { check_web --- 需要调用监控项目信息 }
3)高可用服务的双柱
第一个历程: 编写keepalived配置文件: lb01: vip 10.0.0.3 www.oldboy.com global_defs { notification_email { router_id lb01 } vrrp_instance oldboy { state MASTER interface eth0 virtual_router_id 66 priority 150 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 10.0.0.3 } } vrrp_instance oldgirl { state BACKUP interface eth0 virtual_router_id 67 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 4321 } virtual_ipaddress { 10.0.0.4 } } lb02: vip 10.0.0.4 bbs.oldboy.com global_defs { notification_email { router_id lb02 } vrrp_instance oldboy { state BACKUP interface eth0 virtual_router_id 66 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 10.0.0.3 } } vrrp_instance oldgirl { state MASTER interface eth0 virtual_router_id 67 priority 150 advert_int 1 authentication { auth_type PASS auth_pass 4321 } virtual_ipaddress { 10.0.0.4 } } 第二个历程: 编写lb01负载均衡配置文件 lb01 lb02 配置方法一: lb01 lb02 upstream oldboy { server 172.16.1.7:80; server 172.16.1.8:80; server 172.16.1.9:80; } sever { listen 10.0.0.3:80; server_name www.oldboy.com; location proxy_pass http://oldboy; } sever { listen 10.0.0.4:80; server_name bbs.oldboy.com; location proxy_pass http://oldboy; } 监听地址有什么要求: 监听地址必须是本地网卡上有的地址 ========================================================================== 如何监听本地网卡上没有的地址 修改系统内核文件 echo 'net.ipv4.ip_nonlocal_bind = 1' >>/etc/sysctl.conf sysctl -p ========================================================================== 配置方式二: upstream oldboy { server 172.16.1.7:80; server 172.16.1.8:80; server 172.16.1.9:80; } sever { listen 80; server_name localhost; www.oldboy.com --> 10.0.0.3 --> lb01 location bbs.oldboy.com --> 10.0.0.4 --> lb02 proxy_pass http://oldboy; }