Keepalived+Nginx实现高可用(上)

news2024/12/23 3:06:25

一、背景与简介

        为了服务的高可用性,避免单点故障问题,通常我们使用"冗余设计思想"进行架构设计。冗余设计思想,本质就是将同一个应用或者服务放置在多台不同的服务器上[鸡蛋不放在同一个篮子里],这样减少整体服务宕机的可能性。我们通过概率学就能简单知道,例如一台服务器宕机的概率为1%,那么2台一样的机器同时宕机的概率就是0.01x0.01=0.01%, 依次类推,冗余的服务器越多,那么整体服务宕机的可能性就越小。  但是高可用和成本成正比关系,一个服务的可用性越高,付出的成本越高。

        通常在应用的业务部署中间件中,Nginx扮演着反向代理与流量分发的角色。 例如之前我所在的公司将服务部署在本地IDC机房,整体对外、对内的流量都是经过Nginx作为网关入口。 如果Nginx存在单点问题,所在的服务器一旦发生宕机或者整个Nginx服务不可用,那么对业务的影响是致命的。

        所以我们需要保证Nginx入口网关的高可用性。  我们学过一种编程思想:  面向抽象编程。 在这里,我们可以将要暴露Nginx网关服务的IP给到客户端的是VIP(Virtual IP)而非实际代理的物理IP。 我们将多个提供服务的物理IP形成一个逻辑IP组。VIP是一个虚拟IP(抽象层), VIP会时刻只对应一个物理IP, 一旦对应的物理IP发生故障,则可以漂移到这个逻辑IP组内健康的物理IP, 从而实现客户端无感故障迁移(客户端无效更改VIP地址,同时这个过程对于客户端而言是无感知的、透明的),实现服务的高可用。

        架构图如下:

        DNS服务器直接将域名绑定A记录指向VIP地址: 172.20.0.110, 客户端通过域名进行访问Nginx网关服务即可,后面Nginx网关服务无论是升级、故障转移等等,客户端无须修改域名或者代码,实现Nginx网关服务高可用以及无感故障转移。

二、开源组件Keepalived

1、基本介绍

        很幸运的是要实现上述的Nginx网关服务高可用问题,开源界有一个成熟的、可靠的中间件就是keepalived。

        网上资料是这么介绍keepalived: 

        Keepalived 软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件。

        Keepalived软件主要是通过VRRP协议实现高可用功能的。VRRP是Virtual Router RedundancyProtocol(虚拟路由器冗余协议)的缩写,VRRP出现的目的就是为了解决静态路由单点故障问题的,它能够保证当个别节点宕机时,整个网络可以不间断地运行。

        所以,Keepalived 一方面具有配置管理LVS的功能,同时还具有对LVS下面节点进行健康检查的功能,另一方面也可实现系统网络服务的高可用功能。

2、总结概括

        Keepalived是一个通过VRRP网络协议、提供VIP漂移技术来实现冗余高可用设计的一个开源中间件。 

        通过合理的配置Keepalived我们就可以实现服务的高可用。

三、案例实验

1、实验的目标以及实验环境

      本次实验都是基于docker-compose实现.

       设计有2个容器(2台服务器),分别是172.20.0.2作为主服务器、172.20.0.3作为备用服务器,  服务器上都部署了Nginx服务, 我们需要要暴露这个服务给到其他客户端提供一个VIP。  后面测试主服务器宕机的时候,访问VIP是否访问到了172.20.0.3的页面。等主服务器又恢复正常的时候,访问VIP是否访问到的是172.20.0.2的页面。

        Dockerfile内容如下:

FROM centos:7
RUN yum update -y
USER root
RUN yum install epel-release -y
RUN yum update -y
RUN yum install nginx keepalived -y
RUN yum install vim net-tools iproute -y

         运行的目录结构如下:

        docker-compose.yaml内容如下:

version: "3"
services:
  
  nginx-master:  # 172.20.0.2
    build:
      context: ./docker/
    working_dir: "/root/"
    privileged: true
    hostname: "nginx-master"
    expose:
      - 80
    entrypoint: ["tail", "-f", "/dev/null"]

  nginx-backup:  # 172.20.0.3
    build:
      context: ./docker/
    working_dir: "/root/"
    privileged: true
    hostname: "nginx-backup"
    expose:
      - 80
    entrypoint: [ "tail", "-f", "/dev/null" ]

        运行着2个容器, 执行docker-compose up -d --build

2、测试两个容器显示的页面内容

        在宿主机上执行curl命令,分别curl 2个IP查看返回Nginx提供的页面内容:

3、配置nginx-master容器(172.20.0.2)的keepalived.conf

  文件位于/etc/keepalived/keepalived.conf

global_defs {
        #keepalived节点唯一ID标识名称
        router_id keep_02       
}

vrrp_instance VI_1 {

        #节点角色: MASTER、BACKUP
        state MASTER            

        #绑定VIP的网卡名称
        interface eth0          

        #虚拟路由ID组, 备用节点和主节点必须属于同一个组
        virtual_router_id  172  
               
        #节点优先级, 取值范围 0-255, 主节点的优先级要大于备用节点
        priority  100           
 
        #主备同步检查时间间隔
        advert_int  1           
        
        #认证信息,主备一致
        authentication {        
           auth_type PASS
           auth_pass 1234
        }

        #VIP地址
        virtual_ipaddress {
           172.20.0.110     
        }
}

 启动keepalived:  

keepalived -n -l  # -n 前台运行  -l 显示运行日志

 此时查看ip addr:   可以看到VIP  172.20.0.110 已经绑定在eth0网卡上了

  宿主机此时curl 172.20.0.110得到结果是绑定在了master主节点的内容:

 

4、配置nginx-backup容器(172.20.0.3)的keepalived.conf

global_defs {
        #keepalived节点唯一ID标识名称
        router_id keep_03       
}

vrrp_instance VI_1 {

        #节点角色: MASTER、BACKUP
        state BACKUP           

        #绑定VIP的网卡名称
        interface eth0          

        #虚拟路由ID组, 备用节点和主节点必须属于同一个组
        virtual_router_id  172  
               
        #节点优先级, 取值范围 0-255, 主节点的优先级要大于备用节点
        priority  90          
 
        #主备同步检查时间间隔
        advert_int  1           
        
        #认证信息,主备一致
        authentication {        
           auth_type PASS
           auth_pass 1234
        }

        #VIP地址
        virtual_ipaddress {
           172.20.0.110     
        }
}

  启动keepalived:

keepalived -n -l  # -n 前台运行  -l 显示运行日志

  ​

此时查看: ip addr     主节点keepalived还正常运行,自然备用节点拿不到VIP

5、模拟主节点故障,手动关闭keepalived

此时在宿主机访问VIP  curl  172.20.0.110:

        此时我们看到,同样是访问VIP地址, 第4步骤访问的时候返回的是master: 172.20.0.2, 但是我们手动关闭主节点的keepalived进程模拟故障的时候, 再次curl VIP地址, 访问得到的内容就是backup: 172.20.0.3 。 

        此时已经发生故障转移了,但是客户端访问的VIP没发生变化,我们在宿主机上执行的curl命令一模一样,但是返回的内容不一样了(实际情况来说,没出故障前以及出故障之后,得到的AIP的内容应该是一致的。 只是在这里做演示,让大家看情况故障转移过程,所以故意让返回的页面内容存在差异,容易对比)

6、模拟恢复主节点故障,启动keepalived进程

        此时我们再次访问curl VIP :  curl 172.20.0.110, 得到的内容又是master: 172.20.0.110, VIP已经实现了故障转移(IP漂移)

四、 总结

        整个测试流程还算简单、清晰的。  我们使用keepalived要注意几点:

                1、主节点、备用节点要属于同一个广播域,也就是同一个交换机下

                2、启动keepalived默认是后台运行,启动后进入后台。但是为了更好调试错误加入了-n参数进行前台运行, 为了显示日志便于排错又增加了-l参数。  所以整体参数是

keepalived -n -l

                3、通过ip addr查看VIP代替ifconfig, ifconfig有时候是看不到VIP的存在,只看到了物理IP的存在

        那使用Keepalived上述过程,就能确保服务高正无忧、毫无缺点了么?  其实不尽然。

        1、大家会发现VIP时刻只会漂移到一个物理IP上,那么BACKUP备用节点都处于闲置状态,是不是太浪费资源了呢?

        2、IP漂移或者不漂移是通过Keepalived进程是否存活来决定的。 那么如果存在一种情况就是Keepalived进程存活,此时拿到了VIP,但是Nginx挂了, 那本质上就是VIP拿到了占着茅坑不拉屎,整个服务都挂了。这种情况又该如何处理IP及时漂移到可用Nginx节点来达到高可用的目的呢?  

        预知后事如何,请听下回分解~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1303407.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023 年山东省职业院校技能大赛(高等职业教育) “信息安全管理与评估”样题

2023 年山东省职业院校技能大赛(高等职业教育) “信息安全管理与评估”样题 目录 任务 1 网络平台搭建(50 分) 任务 2 网络安全设备配置与防护(250 分) 模块二 网络安全事件响应、数字取证调查、应用程序安…

深入探索 Spring Boot:简化开发,加速部署的全方位利器

目录 导言 1. 自动配置(Auto-Configuration) 2. 起步依赖(Starter Dependencies) 3. 嵌入式 Web 服务器 4. Actuator 5. 外部化配置 6. 简化的安全性配置 7. Spring Boot CLI 8. Spring Boot DevTools 导言 在当今软件开…

散点图直方图折线图的替代

散点图直方图折线图的替代 seaborn官网 数据科学数据可视化,散点图 直方图 折线图的新方法 1.hexbinplot https://seaborn.pydata.org/examples/hexbin marginals.html相当于散点图做了聚合/分箱,使数据的分布展示更明显。Library: seaborn 2.瀑布图展示…

Pytorch-LSTM轴承故障一维信号分类(一)

目录 前言 1 数据集制作与加载 1.1 导入数据 第一步,导入十分类数据 第二步,读取MAT文件驱动端数据 第三步,制作数据集 第四步,制作训练集和标签 1.2 数据加载,训练数据、测试数据分组,数据分batch…

Qt Widgets 绘图行为逐步分析拆解

Qt 是目前C语言首选的框架库。之所以称为框架库而不单单是GUI库,是因为Qt提供了远远超过GUI的功能封装,即使不使用GUI的后台服务,也可以用Qt大大提高跨平台的能力。 仅就界面来说,Qt 保持各个平台绘图等效果的统一,并…

【EMNLP 2023】面向垂直领域的知识预训练语言模型

近日,阿里云人工智能平台PAI与华东师范大学数据科学与工程学院合作在自然语言处理顶级会议EMNLP2023上发表基于双曲空间和对比学习的垂直领域预训练语言模型。通过比较垂直领域和开放领域知识图谱数据结构的不同特性,发现在垂直领域的图谱结构具有全局稀…

Flink之迟到的数据

迟到数据的处理 推迟水位线推进: WatermarkStrategy.<Event>forBoundedOutOfOrderness(Duration.ofSeconds(2))设置窗口延迟关闭&#xff1a;.allowedLateness(Time.seconds(3))使用侧流接收迟到的数据: .sideOutputLateData(lateData) public class Flink12_LateDataC…

【华为数据之道学习笔记】3-9元数据治理面临的挑战

华为在进行元数据治理以前&#xff0c;遇到的元数据问题主要表现为数据找不到、读不懂、不可信&#xff0c;数据分析师们往往会陷入数据沼泽中&#xff0c;例如以下常见的场景。 某子公司需要从发货数据里对设备保修和维保进行区分&#xff0c;用来不对过保设备进行服务场景分析…

uniapp - 简单版本自定义tab栏切换

tab切换是APP开发最常见的功能之一&#xff0c;uniapp中提供了多种形式的tab组件供我们使用。对于简单的页面而言&#xff0c;使用tabbar组件非常方便快捷&#xff0c;可以快速实现底部导航栏的效果。对于比较复杂的页面&#xff0c;我们可以使用tab组件自由定义样式和内容 目录…

Spring 的缓存机制【记录】

一、背景 在最近的业务需求开发过程中遇到了“传说中”的循环依赖问题&#xff0c;在之前学习Spring的时候经常会看到Spring是如何解决循环依赖问题的&#xff0c;所谓循环依赖即形成了一个环状的依赖关系&#xff0c;这个环中的某一个点产生不稳定变化都会导致整个链路产生不…

WPF仿网易云搭建笔记(5):信息流控制之IOC容器

文章目录 专栏和Gitee仓库前言IOC容器Prism IOC使用声明两个测试的服务类MainWindow IOC 注入[单例]MainWindow里面获取UserController无法使用官方解决方案 使用自定义IOC容器&#xff0c;完美解决既然Prism不好用&#xff0c;直接上微软的IOC解决方案App.xaml.csViewModel里面…

axios 基础的 一次封装 二次封装

一、平常axios的请求发送方式 修改起来麻烦的一批 代码一大串 二、axios的一次封装 我们会在src/utils创建一个request.js的文件来存放我们的基地址与拦截器 /* 封装axios用于发送请求 */ import axios from axios/* (1)request 相当于 Axios 的实例对象 (2)为什么要有reque…

python自动化测试实战 —— WebDriver API的使用

软件测试专栏 感兴趣可看&#xff1a;软件测试专栏 自动化测试学习部分源码 python自动化测试相关知识&#xff1a; 【如何学习Python自动化测试】—— 自动化测试环境搭建 【如何学习python自动化测试】—— 浏览器驱动的安装 以及 如何更…

Web安全-SQL注入【sqli靶场第11-14关】(三)

★★实战前置声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将其信息做其他用途&#xff0c;由用户承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 0、总体思路 先确认是否可以SQL注入&#xff0…

深拷贝、浅拷贝 react的“不可变值”

知识获取源–晨哥&#xff08;现实中的人 嘿嘿&#xff09; react中如果你想让一个值始终不变 或者说其他操作不影响该值 它只是作用初始化的时候 使用了浅拷贝–改变了初始值 会改变初始值(selectList1) 都指向同一个地址 const selectList1 { title: 大大, value: 1 };con…

ES-分析器

分析器 两种常用的英语分析器 1 测试工具 #可以通过这个来测试分析器 实际生产环境中我们肯定是配置在索引中来工作 GET _analyze {"text": "My Moms Son is an excellent teacher","analyzer": "english" }2 实际效果 比如我们有下…

前端框架(Front-end Framework)和库(Library)的区别

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

基于OpenCV+CNN+IOT+微信小程序智能果实采摘指导系统——深度学习算法应用(含python、JS工程源码)+数据集+模型(三)

目录 前言总体设计系统整体结构图系统流程图 运行环境Python环境TensorFlow 环境Jupyter Notebook环境Pycharm 环境微信开发者工具OneNET云平台 模块实现1. 数据预处理1&#xff09;爬取功能2&#xff09;下载功能 2. 创建模型并编译1&#xff09;定义模型结构2&#xff09;优化…

appium安卓app自动化,遇到搜索框无搜索按钮元素时无法搜索的解决方案

如XX头条&#xff0c;搜索框后面有“搜索”按钮&#xff0c;这样实现搜索操作较为方便。 但有些app没有设置该搜索按钮&#xff0c;初学者就要花点时间去学习怎么实现该功能了&#xff0c;如下图。 这时候如果定位搜索框&#xff0c;再点击操作&#xff0c;再输入文本后&#x…

java工程(ajax/axios/postman)向请求头中添加消息

1、问题概述 在项目中我们经常会遇到需要向请求头中添加消息的场景&#xff0c;然后后端通过request.getRequest()或者RequestHeader获取请求头中的消息。 下面提供几种前端向请求头添加消息的方式 2、创建一个springmvc工程用于测试 2.1、创建工程并引入相关包信息 sprin…