ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Linux高级技巧:深度理解和学习高可用集群之Keepalived!

Linux高级技巧:深度理解和学习高可用集群之Keepalived!

原创 Linux操作系统 作者:老男孩Linux 时间:2025-11-05 13:45:33 0 删除 编辑

  高可用集群介绍

  高可用集群是什么

  高可用性集群,一般指在集群中任意一个节点失效的情况下,该节点上的所有任务会自动转移到其他正常的节点上,此过程并不影响整个集群的运行。

   高可用性集群核心作用为:

  当一台机器宕机时,另外一台机器接管宕机的机器的IP资源和服务资源,提供服务;

  常用于不易实现负载均衡的应用,比如负载均衡器,主数据库、主存储对之间;

  高可用性集群常用的开源软件包括Keepalived、Heartbeat等,其架构图如图所示:

  当集群中的一个节点系统发生故障时,运行着的集群服务会迅速做出反应,将该系统的服务分配到集群中其他正在工作的系统上运行。

  考虑到计算机硬件和软件的容错性,高可用性集群的主要目的是使集群的整体服务尽可能可用。

  如果高可用性集群中的主节点发生了故障,那么这段时间内将由备节点代替它。

  备节点通常是主节点的镜像。当它代替主节点时,它可以完全接管主节点(包括IP地址及其他资 源)的服务,因此,使集群系统环境对于用户来说是一致的,即不会影响用户的访问。

   高可用集群企业场景

  主辅负载均衡器之间,例如:LVS负载均衡器、Nginx反向代理之间。

  主辅存储之间、主辅数据库之间,例如:MFS,Hadoop集群主节点之间,MySQL主辅数据库之间。

  高可用开源软件

  Heartbeat简介

  Heartbeat项目是Linux-HA工程的一个组件,它实现了一个高可用集群系统,含有心跳服务和集群通信是高可用集群的两个关键组件,Heartbeat的核心实现简单说明如下:

  以别名的方式配置VIP,命令为ifconfig, 格式标签eth0:0;

  有3个配置文件:ha.cf #基本配置、haresources #资源配置、aukeys #认证;

  用于带有数据资源的高可用对之间,例如:数据库、存储;

  heartbeat+drbd+mysql早期数据库高可用方案

  drbd基于block复制(镜像)

  Keepalived简介

  Keepalived的核心实现简单说明如下:

  以辅助IP形式配置VIP,命令为ip;

  只有一个配置文件keepalived.conf;

  没有数据流动的的高可用对之间;

  如果有数据流动复制需求,需在keepalived之外自行解决;

  Keepalived介绍及原理

  Keepalived介绍

  Keepalived软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能。

  因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件。

   Keepalived核心功能

  管理LVS;

  对LVS节点做健康检查(基于端口和URL);

  实现VRRP高可用功能;

  Keepalived高可用故障切换转移原理

  Keepalived高可用服务对之间的故障切换转移,是通过VRRP协议(中文虚拟路由器冗余协议)来实现的。

  在Keepalived服务正常工作时,主Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点自己还活着。

  当主Master节点发生故障时,就无法发送心跳消息了,备节点也就因此无法继续检测到来自主Master节点的心跳了,进而调用自身的接管程序,接管主Master节点的IP资源及服务。

  而当主Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。

  Keepalived服务搭建

  部署规划

  部署架构图

  部署测试节点Web01

[root@web01 conf.d]# cat 02_www.etiantian.org.confserver {listen 80;server_name www.etiantian.org;root /data/www;location / {index index.html;}}[root@web01 conf.d]# mkdir -p /data/www[root@web01 conf.d]# echo web01 >/data/www/index.html[root@web01 conf.d]#[root@web01 conf.d]# nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful[root@web01 conf.d]# systemctl restart nginx[root@web01 conf.d]# grep www /etc/hosts[root@web01 conf.d]# curl -H "host:www.etiantian.org" 10.0.0.7web01

  部署测试节点Web02

[root@web01 conf.d]# cat 02_www.etiantian.org.confserver {listen 80;server_name www.etiantian.org;12344)分别安装Nginx负载lb01,lb02节点5)分别配置Nginx负载lb01,lb02节点
root /data/www;location / {index index.html;}}[root@web02 conf.d]# mkdir -p /data/www[root@web02 conf.d]#[root@web02 conf.d]# echo web01 >/data/www/index.html[root@web02 conf.d]# echo web02 >/data/www/index.html[root@web02 conf.d]# nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful[root@web02 conf.d]# systemctl restart nginx[root@web02 conf.d]# curl -H "host:www.etiantian.org" 10.0.0.8web02

  分别安装Nginx负载lb01,lb02节点

1.安装nginx[root@lb02 ~]# cat /etc/yum.repos.d/nginx.repo[nginx-stable]name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/gpgcheck=1enabled=1gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
priority=1##yum install yum-plugin-priorities -y
yum install nginx -y
systemctl start nginx
systemctl enable nginx

  分别配置Nginx负载lb01,lb02节点

[root@lb02 ~]# cd /etc/nginx/conf.d[root@lb02 conf.d]# cat 03_www.etiantian.org.confupstream www {server 172.16.1.7 weight=1 ; #默认80端口server 172.16.1.8 weight=1; #默认80端口}server {listen 80;server_name www.etiantian.org;location / {proxy_pass http://www;proxy_set_header Host $http_host;}}nginx -t
systemctl restart nginx#从vip 10.0.0.6/5 测试Nginx负载成功[root@lb02 conf.d]# curl -H "host:www.etiantian.org" 10.0.0.6web01[root@lb02 conf.d]# curl -H "host:www.etiantian.org" 10.0.0.6web02

  在lb01,lb02分别安装keepalived

yum install keepalived -y
systemctl start keepalived[root@lb01 ~]# ps -ef|grep keep|grep -v greproot 1455 1 0 16:36 ? 00:00:00 /usr/sbin/keepalived -D
root 1456 1455 0 16:36 ? 00:00:00 /usr/sbin/keepalived -D
root 1457 1455 0 16:36 ? 00:00:00 /usr/sbin/keepalived -D
systemctl stop keepalived
rpm -qa keepalived
keepalived-1.3.5-19.el7.x86_64

  keepalived配置文件说明

#Keepalived配置文件分三个核心:GLOBAL CONFIGURATION ##全局VRRPD CONFIGURATION ##VRRP高可用LVS CONFIGURATION ##管理LVS,nginx负载用不到,此处删掉[root@lb01 keepalived]# cat keepalived.confglobal_defs {router_id lb01 #<==id为lb01,不同的keepalived.conf此ID要唯一。}vrrp_instance VI_1 { #<==实例名字为VI_1,相同实例的备节点名字要和这个相同。state MASTER #<==状态为MASTER,备节点状态需要为BACKUP。interface eth0 #<==通信接口为eth0,此参数备节点设置和主节点相同。virtual_router_id 51 #<==实例ID为55,keepalived.conf里唯一。priority 150 #<==优先级为150,备节点的优先级必须比此数字低。advert_int 1 #<==通信检查间隔时间1秒。authentication {auth_type PASS #<==PASS认证类型,此参数备节点设置和主节点相同。auth_pass 1111 #<==密码是1111,此参数备节点设置和主节点相同。}virtual_ipaddress {10.0.0.3/24 dev eth0 label eth0:3# <==虚拟IP,即VIP,子网掩码为24位,绑定接口为eth0,别名为eth0:3,此参数备节点设置和主节点相同。}}# 提示:此处设置的虚拟IP为10.0.0.3,即网站域名绑定的IP。

  配置 lb01 keepalived.conf

[root@lb01 ~]# cat /etc/keepalived/keepalived.confglobal_defs {router_id lb01}vrrp_instance VI_1 {state BACKUP
interface eth0
virtual_router_id 51priority 50advert_int 1authentication {auth_type PASS
auth_pass 1111}virtual_ipaddress {10.0.0.3/24 dev eth0 label eth0:3}}systemctl restart keepalived
ifconfig|egrep '10.0.0.3|10.0.0.4'

  配置 lb02 keepalived.conf

[root@lb02 ~]# cat /etc/keepalived/keepalived.confglobal_defs {router_id lb02}vrrp_instance VI_1 {state MASTER
interface eth0
virtual_router_id 51priority 100advert_int 1authentication {auth_type PASS
auth_pass 1111}virtual_ipaddress {10.0.0.3/24 dev eth0 label eth0:3}}systemctl restart keepalived
ifconfig|egrep '10.0.0.3|10.0.0.4'#此时,停止一端服务器。看另一端IP接管情况

  Keepalived服务搭建

  单实例场景与多实例

#单实例##一边跑所有业务,另一边处于热备干等接管状态,这种模式很浪费机器。##例如:lb01跑所有业务,lb02热备干等接管##缺点明显:浪费机器#多实例##两边同时跑不同的服务;同时互相处于对方的热备。##例如:lb01跑www业务,lb02跑blog业务##优点:两边同时跑业务,节省资源。##缺点:需要所有流量一台落到一台机器,单台机器仍要能撑得住。

  多实例lb01

  同时配置两个VIP,对应不同业务,但是同一时间跑一个,这里跑10.0.0.4这个VIP。

[root@lb01 ~]# cat /etc/keepalived/keepalived.confglobal_defs {router_id lb01}vrrp_instance VI_1 {state BACKUP
interface eth0
virtual_router_id 51priority 50advert_int 1authentication {auth_type PASS
auth_pass 1111}virtual_ipaddress {10.0.0.3/24 dev eth0 label eth0:3}}vrrp_instance VI_2 {state MASTER
interface eth0
virtual_router_id 52priority 150advert_int 1authentication {auth_type PASS
auth_pass 1111}virtual_ipaddress {10.0.0.4/24 dev eth0 label eth0:4}}

  多实例lb02

  同时配置两个VIP,对应不同业务,但是同一时间跑一个,这里跑10.0.0.3这个VIP。

[root@lb02 ~]# cat /etc/keepalived/keepalived.confglobal_defs {router_id lb02}vrrp_instance VI_1 {state MASTER
interface eth0
virtual_router_id 51priority 100advert_int 1authentication {auth_type PASS
auth_pass 1111}virtual_ipaddress {10.0.0.3/24 dev eth0 label eth0:3}}vrrp_instance VI_2 {state BACKUP
interface eth0
virtual_router_id 52priority 50advert_int 1authentication {auth_type PASS
auth_pass 1111}virtual_ipaddress {10.0.0.4/24 dev eth0 label eth0:4}}

  Keepalived高可用裂脑

  什么是裂脑?

  由于某些原因,导致两台高可用服务器对在指定时间内,无法检测到对方的心跳消息,各自取得资源及服务的所有权,而此时的两台高可用服务器对都还活着并在正常运行。

  这样就会导致同一个IP或服务在两端同时存在而发生冲突,最严重的是两台主机占用同一个VIP地址,当用户写入数据时可能会分别写入到两端,这可能会导致服务器两端的数据不一致或造成数据丢失,这种情况就被称为裂脑。

  产生裂脑的原因

  1)高可用服务器对之间心跳线链路故障,导致无法正常通信。

  2)高可用服务器对上开启了iptables防火墙阻挡了心跳消息传输。

  3)高可用服务器对上心跳网卡地址等信息配置不正确,导致发送心跳失败。

  4)keepalived配置问题。

  解决裂脑的常见方案

  1)同时使用串行电缆和以太网电缆连接,同时用两条心跳线路

  2)当检测到裂脑时强行关闭一个心跳节点(这个功能需特殊设备支持,如Stonith 、fence)。相当于备节点接收不到心跳消息,发送关机命令通过单独的线路关闭主节点的电源。

  fence和Stonith设备其实就是一个智能电源。

  Keepalived备节点启动故障

  监听网卡上不存在IP地址问题

  如果配置使用“listen 10.0.0.3:80;”的方式指定IP监听服务,而本地的网卡上没有10.0.0.3这个IP,Nginx就会报错:

[root@lb01 server]# nginxnginx: [emerg] bind() to 10.0.0.3:80 failed (99: Cannot assign requested address)

  如果要实施双主即主备同时跑不同的服务,配置文件里指定了IP监听,加入如下内核参数配置:

net.ipv4.ip_nonlocal_bind = 1

  此项表示启动nginx而忽略配置中监听的IP是否存在,它同样适合Haproxy。

  Keepalived针对服务高可用

  高可用服务自身往往只能解决针对物理服务器宕机切换,但是如果服务器不宕机,而nginx负载服务宕了。

  此时VIP是不漂移的,因此,高可用切换就会出现问题,那如何解决呢?

  功能:keepalived判断nginx负载服务是否异常,如果nginx服务异常,则关闭Nginx服务,实现服务器的切换。

  分别在lb01,lb02上配置如下脚本

[root@lb01 scripts]# cat chk_nginx_proxy.sh # !/bin/sh# 如果nginx服务停止,则关闭keep.if [ `netstat -lntup|grep nginx|wc -l` -ne 1 ];then
    systemctl stop keepalived
fi[root@lb01 scripts]# chmod +x chk_nginx_proxy.sh [root@lb01 scripts]# /server/scripts/chk_nginx_proxy.sh ##要可以执行

  测试杀掉nginx后,会不会停止keep服务:

[root@lb01 scripts]# pkill nginx[root@lb01 scripts]# sh chk_nginx_proxy.sh [root@lb01 scripts]# ps -ef|egrep "nginx|keep"root       1769   1197  0 18:35 pts/0    00:00:00 grep -E --color=auto nginx|keep

  分别在lb01,lb02上配置文件

  lb01上配置keepalived.conf:

[root@lb01 scripts]# cat /etc/keepalived/keepalived.conf global_defs {
   router_id lb01}vrrp_script chk_nginx_proxy {#<==定义vrrp脚本,检测HTTP端口。
    script "/server/scripts/chk_nginx_proxy.sh"#<==执行脚本,当nginx服务有问题,就停掉keepalived服务。
    interval 2 #<==间隔2秒。
    weight 2}vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 53
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
      10.0.0.3/24 dev eth0 label eth0:3
    }
    track_script {
    chk_nginx_proxy    #<==触发检查。
    }}vrrp_instance VI_2 {
    state MASTER
    interface eth0
    virtual_router_id 52
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
      10.0.0.4/24 dev eth0 label eth0:4
    }}

  lb02上配置keepalived.conf:

[root@lb02 scripts]# cat /etc/keepalived/keepalived.confglobal_defs {
   router_id lb02}vrrp_script chk_nginx_proxy {#<==定义vrrp脚本,检测HTTP端口。
    script "/server/scripts/chk_nginx_proxy.sh"#<==执行脚本,当nginx服务有问题,就停掉keepalived服务。
    interval 2 #<==间隔2秒。
    weight 2}vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 53
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
      10.0.0.3/24 dev eth0 label eth0:3
    }track_script {chk_nginx_proxy    #<==触发检查。}}vrrp_instance VI_2 {
    state BACKUP
    interface eth0
    virtual_router_id 52
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
      10.0.0.4/24 dev eth0 label eth0:4
    }}

 


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69952968/viewspace-3099778/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
老男孩it教育——致力于帮助有志向的年轻人通过努力学习获得体面的工作和生活。专注于Linux云计算运维、Python全栈开发、网络安全、新媒体运营、容器云架构师、MySQL数据库、go语言的培训。学习可call:18710030740

注册时间:2019-11-06

  • 博文量
    393
  • 访问量
    1012141