集群
集群的概述
1.集群是一组协同工作的服务实体
#每个节点提供相同服务,当一个服务down掉,自动切换备用服务
2.集群实体的可扩展性
#可以增加备用节点,也可以减少备用节点
3.集群实体的高可用性
#在集群中同一服务可以由多个服务节点提供,当部分服务节点失效后,其它服务节点可以接管服务。
4.集群实体地址
#指客户端访问集群实体获取服务资源的唯一入口地址,比如访问nginx只要通过浮动ip就可以访问了。
5.客户请求的负载均衡
#指集群中的分发设备(服务)将用户的请求任务比较均衡(不是平均)分布到集群实体中的服务节点
6.服务节点的错误恢复
#指集群中某个或某些服务节点(设备)不能正常工作(或提供服务),其它类似服务节点(设备)可以资源透明和持续的完成原有任务。!!!
HA集群的类型:
keepalived工作原理:
keepalive原理很简单,TCP会在空闲了一定时间后发送数据给对方:
1.如果主机可达,对方就会响应ACK应答,就认为是存活的。
2.如果可达,但应用程序退出,对方就发FIN应答,发送TCP撤消连接。
3.如果可达,但应用程序崩溃,对方就发RST消息。
4.如果对方主机不响应ack, rst,继续发送直到超时,就撤消连接。这个时间就是默认
的二个小时。
1. 主从
从服务器不对外提供服务,监控主服务器,如果主服务器出现故障,不能对外提供服务,那么从服务器会使用故障迁移,将资源从主服务器拿过来,由“自己”对外提供服务。
从服务器使用心跳检测链路监控主服务器。
2. 对称
2个节点都对外提供服务,互相监视。
脑裂(裂脑)
在高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障。两个节点上的HA软件像“裂脑人”一样,争抢“共享资源”、争起“应用服务”,就会发生严重后果——或者共享资源被瓜分、2边“服务”都起不来了;或者2边“服务”都起来了,但同时读写“共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。
产生脑裂的原因:
(1)心跳线故障
(2)网卡或驱动故障
(3)心跳连接的设备故障
(4)ip地址冲突,基本不会发生
(5)防火墙拦截了心跳数据包的传输
连接心跳的方式:
(1)串口线直连,有距离限制
(2)网线直连
直连的方式只适用于双节点
(3)使用交换机,通过网线连接
使用最多
要保证链路的纯净!!!
解决脑裂:
(1)心跳线冗余
(2)做好监控
一旦出现故障切换,报警要触发动作。
(3)仲裁
让节点完成ping 网关或存储 的动作,
能完成,证明节点是好的
不能完成,节点故障,自动放弃争抢
- 多机
3个节点都对外提供服务,互相监视。
HA集群的存活条件是节点的票数要过半数!!!
默认一个节点的票数是1票。
在双节点模式的集群,这个功能需要关掉。
三节点节点,在down掉2个节点的时候,集群就宣布死亡。
为了保证在这种情况下,集群还是存活的,仲裁磁盘带有票数。
仲裁磁盘有2票就可以了。
HA集群的概念:
服务
浮动IP
成员服务器或节点
失效域
心跳
共享存储
单一故障点
仲裁
失效迁移
监视器
高可用:
在Centos7和Centos6系统中都可以使用keepalived作为高可用
高可用是一样的;
负载均衡:
Centos6 建议使用piranha,
Centos7 使用keepalived
HA集群
使用keepalive在centos7环境部署nginx的HA集群:
准备
nginx1 172.16.0.31
nginx2 172.16.0.32
准备工作:
关闭selinux iptables
主机名
/etc/hosts
联网
同步时间
开始配置:
下载keepalived
[root@nginx1 ~]# yum install -y keepalived
[root@nginx2 ~]# yum install -y keepalived
修改keepalived配置文件
[root@nginx1 ~]# cd /etc/keepalived/
[root@nginx1 /etc/keepalived]# ls
keepalived.conf
[root@nginx1 /etc/keepalived]# vim keepalived.conf
! Configuration File for keepalived
global_defs {
router_id Nginx_HA_xxs !# 实现关联
!#HA的唯一标识
}
vrrp_script check_run {
script "/root/check_nginx.sh"
interval 2
!#监视器-脚本的路径
!#检查的时间间隔,秒
}
vrrp_sync_group VG1 { !# 实现关联
group {
VI_1
}
!#定义了一个实例组
}
vrrp_instance VI_1 {
!#第一个实例
state BACKUP
!#工作模式
!# MASTER 主
!# BACKUP 备
interface ens32
virtual_router_id 199 !# 实现关联 (不同的服务是通过这个区分的)
!# id virtual_router_id 取值在0-255之间,用来区分多个instance的VRRP组播 数不能过大
!#唯一标识的ID号
priority 100
!#优先级
advert_int 1
!#检查间隔
nopreempt
!#资源与服务不抢回
authentication {
auth_type PASS
auth_pass nginxHA
}
!#验证方式,密码
track_script { <--- 这套东西别忘了
check_run
}
!#使用上面定义的监视器脚本
virtual_ipaddress {
172.16.0.30 dev ens32 label ens32:0
!#浮动IP,绑在哪个网卡上,( 浮动ip是没设置过的 )
}
}
监视器-脚本:
[root@nginx1 ~]# yum install -y elinks
[root@nginx2 ~]# yum install -y elinks
[root@nginx1 ~]# vim check_nginx.sh
#!/bin/bash
# nginx的健康检查脚本
ELINKS="/usr/bin/links"
HOST="172.16.0.31"
GW="172.16.0.254"
CHECK_TIME=3
function check_nginx_health () {
# 三层检查
ping -W 1 -c1 $GW &> /dev/null
if [ $? -eq 0 ]
then
# 七层检查
$ELINKS -dump 1 $HOST &> /dev/null # 访问自己的页面ip,检查nginx服务是否开启
if [ $? -eq 0 ]
then
NGINX_OK=1
else
NGINX_OK=0
fi
else
NGINX_OK=0
fi
}
while [ $CHECK_TIME -ne 0 ]
do
let "CHECK_TIME-=1"
check_nginx_health
if [ $NGINX_OK -eq 1 ]
then
CHECK_TIME=0
exit
fi
if [ $NGINX_OK -eq 0 ] && [ $CHECK_TIME -eq 0 ]
then
systemctl stop keepalived
exit 1
fi
sleep 1
done
检查脚本是否可用
检查脚本是否可用
[root@nginx1 ~]# chmod +x check_nginx.sh
[root@nginx1 ~]# ./check_nginx.sh
[root@nginx1 ~]# echo $? # 返回值为0,证明状态可用
0
将脚本和keepalived配置文件拷贝给关联节点
[root@nginx1 ~]# scp check_nginx.sh 172.16.0.32:/root/
相同的脚本,在脚本中ip设置成自己的ip
[root@nginx2 ~]# vim check_nginx.sh
HOST="172.16.0.32"
[root@nginx2 ~]# ./check_nginx.sh
[root@nginx2 ~]# echo $?
0
配置文件传给对方即可,不需要修改配置文件
[root@nginx1 /etc/keepalived]# scp keepalived.conf 172.16.0.32:/etc/keepalived/
启动keepalived服务,并设置成开机自启动
[root@nginx1 ~]# systemctl start keepalived
[root@nginx1 ~]# echo "systemctl start keepalived" >> /etc/rc.local
[root@nginx1 ~]# chmod +x /etc/rc.d/rc.local
[root@nginx2 ~]# systemctl start keepalived
[root@nginx2 ~]# echo "systemctl start keepalived" >> /etc/rc.local
[root@nginx2 ~]# chmod +x /etc/rc.d/rc.local
能查看到虚拟网卡存在浮动ip就是设置成功了
虚拟网卡的ip,只存在于一台设备上,当一个设备关机或者keepalived服务停止后,
浮动ip会自动配置到另一个节点上
[root@nginx1 ~]# ifconfig ens32:0
ens32:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.16.0.30 netmask 255.255.255.255 broadcast 0.0.0.0
开始测试:
测试HA的牢固性
模拟测试:节点服务崩溃
1. 浮动IP在nginx1上
[root@nginx1 ~]# /usr/local/nginx/sbin/nginx -s stop
[root@nginx1 ~]# ifconfig
[root@nginx2 ~]# ifconfig ens32:0
ens32:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.16.0.30 netmask 255.255.255.255 broadcast 0.0.0.0
结果:浮动IP切换到nginx2。
模拟测试:节点服务断网
由于上边服务停止了,这里需要重新启动
[root@nginx1 ~]# /usr/local/nginx/sbin/nginx
[root@nginx1 ~]# systemctl start keepalived
模拟断网,讲nginx2重新启动,这样网络就切断了
[root@nginx2 ~]# reboot
节点1获得浮动ip
[root@nginx1 ~]# ifconfig ens32:0
ens32:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.16.0.30 netmask 255.255.255.255 broadcast 0.0.0.0
nginx端口正常
[root@nginx2 ~]# netstat -antp | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 931/nginx
keepalived启动正常
[root@nginx2 ~]# ps aux | grep keepalived
root 935 0.0 0.1 118676 1384 ? Ss 15:41 0:00 /usr/sbin/keepalived -D
root 936 0.0 0.2 118676 2612 ? S 15:41 0:00 /usr/sbin/keepalived -D
root 937 0.0 0.2 120800 2504 ? S 15:41 0:00 /usr/sbin/keepalived -D
重启节点1
[root@nginx1 ~]# reboot
节点2获得ip
[root@nginx2 ~]# ifconfig ens32:0
ens32:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.16.0.30 netmask 255.255.255.255 broadcast 0.0.0.0
[root@nginx1 ~]# netstat -antp | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 931/nginx
[root@nginx1 ~]# ps aux | grep keepalived
root 935 0.0 0.1 118676 1388 ? Ss 15:42 0:00 /usr/sbin/keepalived -D
root 936 0.0 0.2 118676 2616 ? S 15:42 0:00 /usr/sbin/keepalived -D
root 937 0.0 0.2 120800 2508 ? S 15:42 0:00 /usr/sbin/keepalived -D
注意事项:!!!
keepalived的守护进程一定要在服务启动之后,再启动。
当设置rc.local自启动时,需要检查服务和keepalived的启动顺序,配置脚本时,要设置一定的延时时间。
mysql的HA集群:
准备:
-
2个mysql
AA模式克隆mysql,注意 server_UUID
-
探测mysql的可用性?
授权一个只读的用户
mysql -u 用户名 -p密码 -e “quit” &> /dev/null
先配置双A模式的mysql。
在centos7环境,使用keepalive搭建mysql的HA集群:
mysqlA1 172.16.0.71
mysqlA2 172.16.0.72
浮动IP 172.16.0.60
- 配置mysql双A
[root@mysql-bin ~]# vim /etc/my.cnf # 添加字符集必须结束mysql进程在启动才能生效
[mysqld]
添加字符集设置
character-set-server = utf8
collation-server = utf8_general_ci
server-id = 71 # 在每个节点分别设置各自的server-id
gtid_mode = on # 双A模式也需要分别设置这两项
开启使用gtid
enforce_gtid_consistency = 1 # 双A模式也需要分别设置这两项
Mysql设置
A端
mysql> grant replication slave,reload,super on *.* to slave@'172.16.0.72' identified by '12345';
mysql> flush privileges;
B端
mysql> change master to
-> master_host='172.16.0.71',
-> master_port=3306,
-> master_user='slave',
-> master_password='12345',
-> master_auto_position=1;
mysql> start slave;
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.16.0.71
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000011
Read_Master_Log_Pos: 655
Relay_Log_File: slave_relay_bin.000004
Relay_Log_Pos: 862
Relay_Master_Log_File: binlog.000011
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
反向再配置一遍就是双A了。
- 配置HA集群
! Configuration File for keepalived
global_defs {
router_id mysqlHA_xxs
}
vrrp_script check_run {
script "/root/check_mysql.sh"
interval 2
}
vrrp_sync_group VG1 {
group {
VI_1
}
}
vrrp_instance VI_1 {
state BACKUP
interface ens32
virtual_router_id 106
priority 100
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass mysqlHA
}
track_script {
check_run
}
virtual_ipaddress {
172.16.0.60 dev ens32 label ens32:0
}
}
添加一个测试用户
(探测脚本要用)
mysql> grant select on *.* to test@'localhost' identified by '12345';
mysql> flush privileges;
mysql健康检查的脚本
#!/bin/bash
# mysql的健康检查脚本
GW="172.16.0.254"
CHECK_TIME=3
function check_mysql_health () {
# 三层检查
ping -W 1 -c1 $GW &> /dev/null
if [ $? -eq 0 ]
then
# 七层检查
/usr/local/mysql/bin/mysql -u test -p12345 -e "quit" &> /dev/null
if [ $? -eq 0 ]
then
MySQL_OK=1
else
MySQL_OK=0
fi
else
MySQL_OK=0
fi
}
while [ $CHECK_TIME -ne 0 ]
do
let "CHECK_TIME-=1"
check_mysql_health
if [ $MySQL_OK -eq 1 ]
then
CHECK_TIME=0
exit
fi
if [ $MySQL_OK -eq 0 ] && [ $CHECK_TIME -eq 0 ]
then
systemctl stop keepalived
exit 1
fi
sleep 1
done
[root@mysql01 ~]# vim check_mysql.sh
#!/bin/bash
# 检查mysql的可用性
HOST="172.16.14.32"
GW="172.16.0.254"
CHECK_TIME=3
function check_mysql_health () {
#三层检查
ping -W 1 -c1 $GW &> /dev/null
if [ $? -eq 0 ]
then
/usr/local/mysql/bin/mysql -u test -p12345 -e "quit" &> /dev/null
if [ $? -eq 0 ]
then
Mysql_OK=1
else
Mysql_OK=0
fi
else
Mysql_OK=0
fi
}
while [ $CHECK_TIME -ne 0 ]
do
let "CHECK_TIME-=1"
check_nginx_health
if [ $Mysql_OK -eq 1 ]
then
CHECK_TIME=0
exit
fi
if [ $Mysql_OK -eq 0 ] && [ $CHECK_TIME -eq 0 ]
then
systemctl stop keepalived
exit 1
fi
sleep 1
done